aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
Diffstat (limited to 'drivers')
-rw-r--r--drivers/acpi/acpi_extlog.c20
-rw-r--r--drivers/acpi/acpica/tbutils.c38
-rw-r--r--drivers/acpi/acpica/utresrc.c9
-rw-r--r--drivers/acpi/apei/ghes.c47
-rw-r--r--drivers/acpi/arm64/iort.c22
-rw-r--r--drivers/acpi/battery.c2
-rw-r--r--drivers/acpi/bus.c29
-rw-r--r--drivers/acpi/button.c16
-rw-r--r--drivers/acpi/device_pm.c3
-rw-r--r--drivers/acpi/nfit/core.c54
-rw-r--r--drivers/acpi/nfit/mce.c2
-rw-r--r--drivers/acpi/nfit/nfit.h3
-rw-r--r--drivers/acpi/pci_root.c2
-rw-r--r--drivers/acpi/processor_driver.c4
-rw-r--r--drivers/acpi/processor_throttling.c16
-rw-r--r--drivers/acpi/scan.c71
-rw-r--r--drivers/acpi/sleep.c28
-rw-r--r--drivers/acpi/sysfs.c7
-rw-r--r--drivers/acpi/utils.c16
-rw-r--r--drivers/ata/ahci.c38
-rw-r--r--drivers/ata/libahci_platform.c5
-rw-r--r--drivers/ata/libata-core.c2
-rw-r--r--drivers/ata/sata_mv.c13
-rw-r--r--drivers/ata/sata_rcar.c15
-rw-r--r--drivers/base/core.c16
-rw-r--r--drivers/base/node.c2
-rw-r--r--drivers/base/pinctrl.c3
-rw-r--r--drivers/base/platform-msi.c2
-rw-r--r--drivers/base/power/main.c5
-rw-r--r--drivers/base/power/wakeup.c29
-rw-r--r--drivers/block/DAC960.c2
-rw-r--r--drivers/block/amiflop.c10
-rw-r--r--drivers/block/aoe/aoeblk.c1
-rw-r--r--drivers/block/aoe/aoecmd.c12
-rw-r--r--drivers/block/aoe/aoedev.c2
-rw-r--r--drivers/block/ataflop.c16
-rw-r--r--drivers/block/brd.c1
-rw-r--r--drivers/block/cciss.c4
-rw-r--r--drivers/block/drbd/drbd_actlog.c2
-rw-r--r--drivers/block/drbd/drbd_bitmap.c6
-rw-r--r--drivers/block/drbd/drbd_int.h5
-rw-r--r--drivers/block/drbd/drbd_main.c14
-rw-r--r--drivers/block/drbd/drbd_nl.c2
-rw-r--r--drivers/block/drbd/drbd_receiver.c6
-rw-r--r--drivers/block/drbd/drbd_req.c8
-rw-r--r--drivers/block/drbd/drbd_req.h2
-rw-r--r--drivers/block/drbd/drbd_worker.c16
-rw-r--r--drivers/block/floppy.c9
-rw-r--r--drivers/block/loop.c67
-rw-r--r--drivers/block/loop.h1
-rw-r--r--drivers/block/mtip32xx/mtip32xx.c54
-rw-r--r--drivers/block/mtip32xx/mtip32xx.h2
-rw-r--r--drivers/block/nbd.c59
-rw-r--r--drivers/block/null_blk.c125
-rw-r--r--drivers/block/paride/pcd.c9
-rw-r--r--drivers/block/paride/pd.c3
-rw-r--r--drivers/block/paride/pf.c19
-rw-r--r--drivers/block/pktcdvd.c40
-rw-r--r--drivers/block/ps3disk.c11
-rw-r--r--drivers/block/ps3vram.c16
-rw-r--r--drivers/block/rbd.c30
-rw-r--r--drivers/block/rsxx/dev.c17
-rw-r--r--drivers/block/rsxx/dma.c13
-rw-r--r--drivers/block/rsxx/rsxx_priv.h2
-rw-r--r--drivers/block/skd_main.c32
-rw-r--r--drivers/block/sunvdc.c4
-rw-r--r--drivers/block/swim.c8
-rw-r--r--drivers/block/swim3.c29
-rw-r--r--drivers/block/sx8.c20
-rw-r--r--drivers/block/umem.c4
-rw-r--r--drivers/block/virtio_blk.c23
-rw-r--r--drivers/block/xen-blkback/blkback.c45
-rw-r--r--drivers/block/xen-blkback/common.h26
-rw-r--r--drivers/block/xen-blkback/xenbus.c15
-rw-r--r--drivers/block/xen-blkfront.c81
-rw-r--r--drivers/block/xsysace.c9
-rw-r--r--drivers/block/z2ram.c4
-rw-r--r--drivers/bluetooth/btmrvl_main.c2
-rw-r--r--drivers/cdrom/cdrom.c7
-rw-r--r--drivers/cdrom/gdrom.c10
-rw-r--r--drivers/char/Kconfig9
-rw-r--r--drivers/char/Makefile1
-rw-r--r--drivers/char/ipmi/ipmi_watchdog.c2
-rw-r--r--drivers/char/mem.c2
-rw-r--r--drivers/char/mmtimer.c858
-rw-r--r--drivers/char/pcmcia/cm4040_cs.c6
-rw-r--r--drivers/char/random.c51
-rw-r--r--drivers/char/tpm/tpm_crb.c9
-rw-r--r--drivers/char/tpm/tpm_ppi.c20
-rw-r--r--drivers/clk/meson/Kconfig1
-rw-r--r--drivers/clk/sunxi-ng/Kconfig1
-rw-r--r--drivers/clk/sunxi-ng/ccu-sun50i-a64.h4
-rw-r--r--drivers/clk/sunxi-ng/ccu-sun5i.c2
-rw-r--r--drivers/clk/sunxi-ng/ccu-sun6i-a31.c2
-rw-r--r--drivers/clk/sunxi-ng/ccu-sun8i-h3.h4
-rw-r--r--drivers/clk/sunxi-ng/ccu-sun8i-v3s.c2
-rw-r--r--drivers/clocksource/Kconfig80
-rw-r--r--drivers/clocksource/Makefile5
-rw-r--r--drivers/clocksource/arc_timer.c6
-rw-r--r--drivers/clocksource/arm_arch_timer.c12
-rw-r--r--drivers/clocksource/arm_global_timer.c2
-rw-r--r--drivers/clocksource/armv7m_systick.c2
-rw-r--r--drivers/clocksource/asm9260_timer.c2
-rw-r--r--drivers/clocksource/bcm2835_timer.c2
-rw-r--r--drivers/clocksource/bcm_kona_timer.c4
-rw-r--r--drivers/clocksource/cadence_ttc_timer.c3
-rw-r--r--drivers/clocksource/clkevt-probe.c56
-rw-r--r--drivers/clocksource/clksrc-dbx500-prcmu.c2
-rw-r--r--drivers/clocksource/clksrc_st_lpc.c2
-rw-r--r--drivers/clocksource/clps711x-timer.c4
-rw-r--r--drivers/clocksource/dw_apb_timer_of.c8
-rw-r--r--drivers/clocksource/exynos_mct.c4
-rw-r--r--drivers/clocksource/fsl_ftm_timer.c10
-rw-r--r--drivers/clocksource/h8300_timer16.c2
-rw-r--r--drivers/clocksource/h8300_timer8.c2
-rw-r--r--drivers/clocksource/h8300_tpu.c2
-rw-r--r--drivers/clocksource/jcore-pit.c2
-rw-r--r--drivers/clocksource/meson6_timer.c2
-rw-r--r--drivers/clocksource/mips-gic-timer.c7
-rw-r--r--drivers/clocksource/moxart_timer.c256
-rw-r--r--drivers/clocksource/mps2-timer.c2
-rw-r--r--drivers/clocksource/mtk_timer.c2
-rw-r--r--drivers/clocksource/mxs_timer.c2
-rw-r--r--drivers/clocksource/nomadik-mtu.c2
-rw-r--r--drivers/clocksource/pxa_timer.c2
-rw-r--r--drivers/clocksource/qcom-timer.c4
-rw-r--r--drivers/clocksource/renesas-ostm.c2
-rw-r--r--drivers/clocksource/rockchip_timer.c4
-rw-r--r--drivers/clocksource/samsung_pwm_timer.c10
-rw-r--r--drivers/clocksource/sun4i_timer.c173
-rw-r--r--drivers/clocksource/tango_xtal.c2
-rw-r--r--drivers/clocksource/tcb_clksrc.c109
-rw-r--r--drivers/clocksource/tegra20_timer.c4
-rw-r--r--drivers/clocksource/time-armada-370-xp.c6
-rw-r--r--drivers/clocksource/time-efm32.c4
-rw-r--r--drivers/clocksource/time-lpc32xx.c2
-rw-r--r--drivers/clocksource/time-orion.c2
-rw-r--r--drivers/clocksource/time-pistachio.c2
-rw-r--r--drivers/clocksource/timer-atlas7.c2
-rw-r--r--drivers/clocksource/timer-atmel-pit.c2
-rw-r--r--drivers/clocksource/timer-atmel-st.c2
-rw-r--r--drivers/clocksource/timer-digicolor.c2
-rw-r--r--drivers/clocksource/timer-fttmr010.c476
-rw-r--r--drivers/clocksource/timer-imx-gpt.c24
-rw-r--r--drivers/clocksource/timer-integrator-ap.c2
-rw-r--r--drivers/clocksource/timer-keystone.c2
-rw-r--r--drivers/clocksource/timer-nps.c6
-rw-r--r--drivers/clocksource/timer-of.c171
-rw-r--r--drivers/clocksource/timer-of.h69
-rw-r--r--drivers/clocksource/timer-oxnas-rps.c4
-rw-r--r--drivers/clocksource/timer-prima2.c2
-rw-r--r--drivers/clocksource/timer-probe.c (renamed from drivers/clocksource/clksrc-probe.c)20
-rw-r--r--drivers/clocksource/timer-sp804.c4
-rw-r--r--drivers/clocksource/timer-stm32.c2
-rw-r--r--drivers/clocksource/timer-sun5i.c5
-rw-r--r--drivers/clocksource/timer-ti-32k.c2
-rw-r--r--drivers/clocksource/timer-u300.c2
-rw-r--r--drivers/clocksource/versatile.c4
-rw-r--r--drivers/clocksource/vf_pit_timer.c2
-rw-r--r--drivers/clocksource/vt8500_timer.c2
-rw-r--r--drivers/clocksource/zevio-timer.c2
-rw-r--r--drivers/cpufreq/Kconfig.arm9
-rw-r--r--drivers/cpufreq/Makefile2
-rw-r--r--drivers/cpufreq/cpufreq.c22
-rw-r--r--drivers/cpufreq/cpufreq_conservative.c4
-rw-r--r--drivers/cpufreq/intel_pstate.c5
-rw-r--r--drivers/cpufreq/kirkwood-cpufreq.c19
-rw-r--r--drivers/cpufreq/pasemi-cpufreq.c2
-rw-r--r--drivers/cpuidle/cpuidle.c1
-rw-r--r--drivers/cpuidle/dt_idle_states.c4
-rw-r--r--drivers/crypto/Kconfig15
-rw-r--r--drivers/dax/super.c9
-rw-r--r--drivers/devfreq/event/exynos-nocp.c6
-rw-r--r--drivers/devfreq/event/exynos-ppmu.c8
-rw-r--r--drivers/dma/ep93xx_dma.c39
-rw-r--r--drivers/dma/mv_xor_v2.c109
-rw-r--r--drivers/dma/omap-dma.c39
-rw-r--r--drivers/dma/pl330.c3
-rw-r--r--drivers/dma/sh/rcar-dmac.c3
-rw-r--r--drivers/dma/sh/usb-dmac.c2
-rw-r--r--drivers/edac/altera_edac.c26
-rw-r--r--drivers/edac/i5000_edac.c6
-rw-r--r--drivers/edac/i5400_edac.c4
-rw-r--r--drivers/edac/ie31200_edac.c13
-rw-r--r--drivers/edac/mce_amd.c2
-rw-r--r--drivers/edac/mv64x60_edac.c88
-rw-r--r--drivers/edac/pnd2_edac.c20
-rw-r--r--drivers/edac/sb_edac.c682
-rw-r--r--drivers/edac/thunderx_edac.c2
-rw-r--r--drivers/extcon/Kconfig1
-rw-r--r--drivers/extcon/extcon-arizona.c4
-rw-r--r--drivers/extcon/extcon-intel-int3496.c5
-rw-r--r--drivers/extcon/extcon.c11
-rw-r--r--drivers/firmware/dmi-id.c2
-rw-r--r--drivers/firmware/dmi_scan.c50
-rw-r--r--drivers/firmware/efi/Kconfig9
-rw-r--r--drivers/firmware/efi/arm-runtime.c16
-rw-r--r--drivers/firmware/efi/capsule-loader.c117
-rw-r--r--drivers/firmware/efi/capsule.c11
-rw-r--r--drivers/firmware/efi/efi-bgrt.c27
-rw-r--r--drivers/firmware/efi/efi-pstore.c17
-rw-r--r--drivers/firmware/efi/efi.c3
-rw-r--r--drivers/firmware/efi/libstub/secureboot.c4
-rw-r--r--drivers/firmware/efi/test/efi_test.c11
-rw-r--r--drivers/firmware/google/vpd.c8
-rw-r--r--drivers/gpio/gpio-aspeed.c3
-rw-r--r--drivers/gpio/gpio-crystalcove.c54
-rw-r--r--drivers/gpio/gpio-mvebu.c15
-rw-r--r--drivers/gpio/gpiolib-acpi.c2
-rw-r--r--drivers/gpio/gpiolib.c3
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.c4
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c1
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_fb.c7
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c24
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_vm.h1
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_vram_mgr.c10
-rw-r--r--drivers/gpu/drm/amd/amdgpu/atombios_crtc.c4
-rw-r--r--drivers/gpu/drm/amd/amdgpu/ci_dpm.c6
-rw-r--r--drivers/gpu/drm/amd/amdgpu/dce_v10_0.c7
-rw-r--r--drivers/gpu/drm/amd/amdgpu/dce_v11_0.c7
-rw-r--r--drivers/gpu/drm/amd/amdgpu/dce_v6_0.c7
-rw-r--r--drivers/gpu/drm/amd/amdgpu/dce_v8_0.c7
-rw-r--r--drivers/gpu/drm/amd/amdgpu/gmc_v6_0.c15
-rw-r--r--drivers/gpu/drm/amd/amdgpu/gmc_v7_0.c15
-rw-r--r--drivers/gpu/drm/amd/amdgpu/gmc_v8_0.c15
-rw-r--r--drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c16
-rw-r--r--drivers/gpu/drm/amd/amdgpu/vce_v3_0.c95
-rw-r--r--drivers/gpu/drm/amd/powerplay/hwmgr/smu7_hwmgr.c32
-rw-r--r--drivers/gpu/drm/amd/powerplay/hwmgr/vega10_hwmgr.c2
-rw-r--r--drivers/gpu/drm/amd/powerplay/hwmgr/vega10_thermal.c20
-rw-r--r--drivers/gpu/drm/bridge/synopsys/Kconfig1
-rw-r--r--drivers/gpu/drm/drm_atomic_helper.c11
-rw-r--r--drivers/gpu/drm/drm_connector.c38
-rw-r--r--drivers/gpu/drm/drm_dp_helper.c83
-rw-r--r--drivers/gpu/drm/drm_drv.c7
-rw-r--r--drivers/gpu/drm/drm_plane.c5
-rw-r--r--drivers/gpu/drm/etnaviv/etnaviv_gem.h3
-rw-r--r--drivers/gpu/drm/etnaviv/etnaviv_gem_submit.c2
-rw-r--r--drivers/gpu/drm/exynos/exynos_drm_drv.c8
-rw-r--r--drivers/gpu/drm/exynos/exynos_drm_drv.h5
-rw-r--r--drivers/gpu/drm/exynos/exynos_drm_dsi.c26
-rw-r--r--drivers/gpu/drm/gma500/psb_intel_lvds.c18
-rw-r--r--drivers/gpu/drm/hisilicon/kirin/dw_drm_dsi.c2
-rw-r--r--drivers/gpu/drm/i915/gvt/execlist.c30
-rw-r--r--drivers/gpu/drm/i915/gvt/handlers.c30
-rw-r--r--drivers/gpu/drm/i915/i915_debugfs.c6
-rw-r--r--drivers/gpu/drm/i915/i915_drv.c13
-rw-r--r--drivers/gpu/drm/i915/i915_drv.h13
-rw-r--r--drivers/gpu/drm/i915/i915_gem.c67
-rw-r--r--drivers/gpu/drm/i915/i915_gem_execbuffer.c17
-rw-r--r--drivers/gpu/drm/i915/i915_gem_gtt.c108
-rw-r--r--drivers/gpu/drm/i915/i915_gem_request.c2
-rw-r--r--drivers/gpu/drm/i915/i915_gem_request.h2
-rw-r--r--drivers/gpu/drm/i915/i915_gem_shrinker.c5
-rw-r--r--drivers/gpu/drm/i915/i915_gem_tiling.c2
-rw-r--r--drivers/gpu/drm/i915/i915_guc_submission.c4
-rw-r--r--drivers/gpu/drm/i915/i915_irq.c15
-rw-r--r--drivers/gpu/drm/i915/i915_pci.c3
-rw-r--r--drivers/gpu/drm/i915/i915_pvinfo.h8
-rw-r--r--drivers/gpu/drm/i915/i915_reg.h2
-rw-r--r--drivers/gpu/drm/i915/i915_sw_fence.c35
-rw-r--r--drivers/gpu/drm/i915/i915_sw_fence.h2
-rw-r--r--drivers/gpu/drm/i915/i915_vgpu.c10
-rw-r--r--drivers/gpu/drm/i915/i915_vma.c5
-rw-r--r--drivers/gpu/drm/i915/intel_acpi.c14
-rw-r--r--drivers/gpu/drm/i915/intel_display.c75
-rw-r--r--drivers/gpu/drm/i915/intel_dp.c45
-rw-r--r--drivers/gpu/drm/i915/intel_dp_aux_backlight.c2
-rw-r--r--drivers/gpu/drm/i915/intel_dp_mst.c5
-rw-r--r--drivers/gpu/drm/i915/intel_drv.h13
-rw-r--r--drivers/gpu/drm/i915/intel_engine_cs.c20
-rw-r--r--drivers/gpu/drm/i915/intel_fbc.c19
-rw-r--r--drivers/gpu/drm/i915/intel_lpe_audio.c36
-rw-r--r--drivers/gpu/drm/i915/intel_lrc.c8
-rw-r--r--drivers/gpu/drm/i915/intel_lspcon.c2
-rw-r--r--drivers/gpu/drm/i915/intel_pm.c45
-rw-r--r--drivers/gpu/drm/i915/intel_psr.c5
-rw-r--r--drivers/gpu/drm/i915/intel_ringbuffer.c41
-rw-r--r--drivers/gpu/drm/i915/intel_ringbuffer.h19
-rw-r--r--drivers/gpu/drm/i915/intel_sprite.c21
-rw-r--r--drivers/gpu/drm/i915/intel_uc.h2
-rw-r--r--drivers/gpu/drm/i915/selftests/i915_gem_context.c8
-rw-r--r--drivers/gpu/drm/imx/imx-ldb.c2
-rw-r--r--drivers/gpu/drm/mediatek/mtk_dsi.c15
-rw-r--r--drivers/gpu/drm/mediatek/mtk_hdmi.c2
-rw-r--r--drivers/gpu/drm/meson/meson_drv.c20
-rw-r--r--drivers/gpu/drm/mgag200/mgag200_mode.c9
-rw-r--r--drivers/gpu/drm/msm/Kconfig1
-rw-r--r--drivers/gpu/drm/msm/mdp/mdp5/mdp5_mdss.c2
-rw-r--r--drivers/gpu/drm/msm/mdp/mdp5/mdp5_plane.c9
-rw-r--r--drivers/gpu/drm/msm/msm_drv.c1
-rw-r--r--drivers/gpu/drm/msm/msm_drv.h1
-rw-r--r--drivers/gpu/drm/msm/msm_fence.c10
-rw-r--r--drivers/gpu/drm/msm/msm_gem.c6
-rw-r--r--drivers/gpu/drm/msm/msm_gem_prime.c7
-rw-r--r--drivers/gpu/drm/msm/msm_gem_submit.c14
-rw-r--r--drivers/gpu/drm/msm/msm_gpu.c4
-rw-r--r--drivers/gpu/drm/mxsfb/mxsfb_crtc.c42
-rw-r--r--drivers/gpu/drm/nouveau/include/nvkm/subdev/timer.h1
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_acpi.c20
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_drm.c38
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_drv.h3
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_vga.c13
-rw-r--r--drivers/gpu/drm/nouveau/nv50_display.c3
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/mxm/base.c9
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/timer/base.c7
-rw-r--r--drivers/gpu/drm/qxl/qxl_display.c4
-rw-r--r--drivers/gpu/drm/radeon/ci_dpm.c6
-rw-r--r--drivers/gpu/drm/radeon/cik.c11
-rw-r--r--drivers/gpu/drm/radeon/evergreen.c11
-rw-r--r--drivers/gpu/drm/radeon/r600.c2
-rw-r--r--drivers/gpu/drm/radeon/radeon.h2
-rw-r--r--drivers/gpu/drm/radeon/radeon_combios.c7
-rw-r--r--drivers/gpu/drm/radeon/radeon_device.c4
-rw-r--r--drivers/gpu/drm/radeon/radeon_fence.c2
-rw-r--r--drivers/gpu/drm/radeon/radeon_kms.c2
-rw-r--r--drivers/gpu/drm/radeon/radeon_uvd.c2
-rw-r--r--drivers/gpu/drm/radeon/si.c11
-rw-r--r--drivers/gpu/drm/rockchip/analogix_dp-rockchip.c12
-rw-r--r--drivers/gpu/drm/rockchip/cdn-dp-core.c9
-rw-r--r--drivers/gpu/drm/rockchip/rockchip_drm_vop.c8
-rw-r--r--drivers/gpu/drm/rockchip/rockchip_drm_vop.h3
-rw-r--r--drivers/gpu/drm/rockchip/rockchip_vop_reg.c2
-rw-r--r--drivers/gpu/drm/tegra/drm.c22
-rw-r--r--drivers/gpu/drm/vmwgfx/vmwgfx_cmdbuf_res.c1
-rw-r--r--drivers/gpu/drm/vmwgfx/vmwgfx_drv.h4
-rw-r--r--drivers/gpu/drm/vmwgfx/vmwgfx_fifo.c2
-rw-r--r--drivers/gpu/drm/vmwgfx/vmwgfx_kms.c115
-rw-r--r--drivers/gpu/drm/vmwgfx/vmwgfx_kms.h15
-rw-r--r--drivers/gpu/drm/vmwgfx/vmwgfx_stdu.c27
-rw-r--r--drivers/gpu/drm/vmwgfx/vmwgfx_surface.c23
-rw-r--r--drivers/gpu/host1x/dev.c2
-rw-r--r--drivers/gpu/ipu-v3/ipu-common.c15
-rw-r--r--drivers/gpu/ipu-v3/ipu-pre.c13
-rw-r--r--drivers/gpu/vga/vgaarb.c2
-rw-r--r--drivers/hid/Kconfig6
-rw-r--r--drivers/hid/hid-asus.c12
-rw-r--r--drivers/hid/hid-core.c285
-rw-r--r--drivers/hid/hid-elecom.c62
-rw-r--r--drivers/hid/hid-ids.h6
-rw-r--r--drivers/hid/i2c-hid/i2c-hid.c22
-rw-r--r--drivers/hid/usbhid/hid-quirks.c1
-rw-r--r--drivers/hid/wacom_wac.c45
-rw-r--r--drivers/hsi/clients/ssi_protocol.c2
-rw-r--r--drivers/hwmon/Kconfig1
-rw-r--r--drivers/hwmon/aspeed-pwm-tacho.c65
-rw-r--r--drivers/hwtracing/coresight/coresight-etm3x.c20
-rw-r--r--drivers/hwtracing/coresight/coresight-etm4x.c20
-rw-r--r--drivers/i2c/busses/i2c-designware-platdrv.c2
-rw-r--r--drivers/i2c/busses/i2c-imx.c8
-rw-r--r--drivers/i2c/busses/i2c-ismt.c2
-rw-r--r--drivers/i2c/busses/i2c-rcar.c2
-rw-r--r--drivers/i2c/busses/i2c-tiny-usb.c25
-rw-r--r--drivers/ide/ide-atapi.c12
-rw-r--r--drivers/ide/ide-cd.c11
-rw-r--r--drivers/ide/ide-cd_ioctl.c1
-rw-r--r--drivers/ide/ide-devsets.c1
-rw-r--r--drivers/ide/ide-disk.c1
-rw-r--r--drivers/ide/ide-dma.c2
-rw-r--r--drivers/ide/ide-eh.c16
-rw-r--r--drivers/ide/ide-floppy.c6
-rw-r--r--drivers/ide/ide-io.c10
-rw-r--r--drivers/ide/ide-ioctls.c2
-rw-r--r--drivers/ide/ide-park.c2
-rw-r--r--drivers/ide/ide-pm.c8
-rw-r--r--drivers/ide/ide-probe.c7
-rw-r--r--drivers/ide/ide-tape.c3
-rw-r--r--drivers/ide/ide-taskfile.c7
-rw-r--r--drivers/ide/siimage.c6
-rw-r--r--drivers/iio/accel/hid-sensor-accel-3d.c2
-rw-r--r--drivers/iio/accel/mma9551.c4
-rw-r--r--drivers/iio/accel/st_accel_core.c7
-rw-r--r--drivers/iio/accel/st_accel_spi.c4
-rw-r--r--drivers/iio/adc/Kconfig24
-rw-r--r--drivers/iio/adc/Makefile2
-rw-r--r--drivers/iio/adc/ad7791.c8
-rw-r--r--drivers/iio/adc/aspeed_adc.c6
-rw-r--r--drivers/iio/adc/bcm_iproc_adc.c8
-rw-r--r--drivers/iio/adc/cpcap-adc.c108
-rw-r--r--drivers/iio/adc/hi8435.c46
-rw-r--r--drivers/iio/adc/ina2xx-adc.c218
-rw-r--r--drivers/iio/adc/lpc32xx_adc.c8
-rw-r--r--drivers/iio/adc/max9611.c10
-rw-r--r--drivers/iio/adc/meson_saradc.c90
-rw-r--r--drivers/iio/adc/mxs-lradc-adc.c39
-rw-r--r--drivers/iio/adc/rcar-gyroadc.c16
-rw-r--r--drivers/iio/adc/stm32-adc-core.c269
-rw-r--r--drivers/iio/adc/stm32-adc-core.h2
-rw-r--r--drivers/iio/adc/stm32-adc.c762
-rw-r--r--drivers/iio/adc/sun4i-gpadc-iio.c38
-rw-r--r--drivers/iio/adc/ti-adc084s021.c275
-rw-r--r--drivers/iio/adc/ti-adc108s102.c348
-rw-r--r--drivers/iio/adc/ti_am335x_adc.c2
-rw-r--r--drivers/iio/adc/twl4030-madc.c209
-rw-r--r--drivers/iio/adc/xilinx-xadc-core.c5
-rw-r--r--drivers/iio/buffer/industrialio-buffer-dma.c1
-rw-r--r--drivers/iio/buffer/industrialio-buffer-dmaengine.c1
-rw-r--r--drivers/iio/common/hid-sensors/Kconfig2
-rw-r--r--drivers/iio/common/hid-sensors/hid-sensor-attributes.c54
-rw-r--r--drivers/iio/common/hid-sensors/hid-sensor-trigger.c80
-rw-r--r--drivers/iio/dac/Kconfig3
-rw-r--r--drivers/iio/dac/ad5064.c71
-rw-r--r--drivers/iio/humidity/hts221.h3
-rw-r--r--drivers/iio/humidity/hts221_core.c54
-rw-r--r--drivers/iio/humidity/hts221_i2c.c1
-rw-r--r--drivers/iio/humidity/hts221_spi.c1
-rw-r--r--drivers/iio/imu/inv_mpu6050/inv_mpu_core.c222
-rw-r--r--drivers/iio/imu/inv_mpu6050/inv_mpu_i2c.c8
-rw-r--r--drivers/iio/imu/inv_mpu6050/inv_mpu_iio.h8
-rw-r--r--drivers/iio/imu/inv_mpu6050/inv_mpu_ring.c6
-rw-r--r--drivers/iio/imu/inv_mpu6050/inv_mpu_trigger.c11
-rw-r--r--drivers/iio/imu/st_lsm6dsx/st_lsm6dsx.h5
-rw-r--r--drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_buffer.c20
-rw-r--r--drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_core.c52
-rw-r--r--drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_i2c.c1
-rw-r--r--drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_spi.c1
-rw-r--r--drivers/iio/industrialio-core.c21
-rw-r--r--drivers/iio/industrialio-trigger.c3
-rw-r--r--drivers/iio/inkern.c4
-rw-r--r--drivers/iio/light/Kconfig10
-rw-r--r--drivers/iio/light/Makefile1
-rw-r--r--drivers/iio/light/isl29018.c2
-rw-r--r--drivers/iio/light/isl29028.c (renamed from drivers/staging/iio/light/isl29028.c)76
-rw-r--r--drivers/iio/light/ltr501.c4
-rw-r--r--drivers/iio/light/rpr0521.c307
-rw-r--r--drivers/iio/light/tsl2583.c106
-rw-r--r--drivers/iio/magnetometer/st_magn_spi.c2
-rw-r--r--drivers/iio/orientation/hid-sensor-rotation.c55
-rw-r--r--drivers/iio/pressure/Kconfig2
-rw-r--r--drivers/iio/pressure/st_pressure_core.c8
-rw-r--r--drivers/iio/pressure/zpa2326.c18
-rw-r--r--drivers/iio/proximity/as3935.c20
-rw-r--r--drivers/iio/proximity/sx9500.c3
-rw-r--r--drivers/iio/temperature/maxim_thermocouple.c1
-rw-r--r--drivers/iio/trigger/stm32-timer-trigger.c174
-rw-r--r--drivers/infiniband/core/addr.c10
-rw-r--r--drivers/infiniband/core/cm.c4
-rw-r--r--drivers/infiniband/core/cma.c13
-rw-r--r--drivers/infiniband/core/core_priv.h10
-rw-r--r--drivers/infiniband/core/netlink.c2
-rw-r--r--drivers/infiniband/core/sa_query.c6
-rw-r--r--drivers/infiniband/core/umem.c2
-rw-r--r--drivers/infiniband/core/umem_odp.c6
-rw-r--r--drivers/infiniband/core/uverbs_marshall.c8
-rw-r--r--drivers/infiniband/hw/bnxt_re/bnxt_re.h4
-rw-r--r--drivers/infiniband/hw/bnxt_re/ib_verbs.c471
-rw-r--r--drivers/infiniband/hw/bnxt_re/ib_verbs.h22
-rw-r--r--drivers/infiniband/hw/bnxt_re/main.c4
-rw-r--r--drivers/infiniband/hw/bnxt_re/qplib_fp.c384
-rw-r--r--drivers/infiniband/hw/bnxt_re/qplib_fp.h18
-rw-r--r--drivers/infiniband/hw/bnxt_re/qplib_rcfw.c314
-rw-r--r--drivers/infiniband/hw/bnxt_re/qplib_rcfw.h61
-rw-r--r--drivers/infiniband/hw/bnxt_re/qplib_res.h4
-rw-r--r--drivers/infiniband/hw/bnxt_re/qplib_sp.c333
-rw-r--r--drivers/infiniband/hw/bnxt_re/qplib_sp.h2
-rw-r--r--drivers/infiniband/hw/cxgb4/cm.c9
-rw-r--r--drivers/infiniband/hw/cxgb4/device.c12
-rw-r--r--drivers/infiniband/hw/hfi1/chip.c67
-rw-r--r--drivers/infiniband/hw/hfi1/chip_registers.h2
-rw-r--r--drivers/infiniband/hw/hfi1/hfi.h11
-rw-r--r--drivers/infiniband/hw/hfi1/intr.c3
-rw-r--r--drivers/infiniband/hw/hfi1/pcie.c4
-rw-r--r--drivers/infiniband/hw/hfi1/rc.c5
-rw-r--r--drivers/infiniband/hw/hfi1/sysfs.c3
-rw-r--r--drivers/infiniband/hw/i40iw/i40iw_cm.c3
-rw-r--r--drivers/infiniband/hw/i40iw/i40iw_ctrl.c12
-rw-r--r--drivers/infiniband/hw/i40iw/i40iw_main.c22
-rw-r--r--drivers/infiniband/hw/i40iw/i40iw_osdep.h1
-rw-r--r--drivers/infiniband/hw/i40iw/i40iw_type.h2
-rw-r--r--drivers/infiniband/hw/i40iw/i40iw_utils.c17
-rw-r--r--drivers/infiniband/hw/i40iw/i40iw_virtchnl.c5
-rw-r--r--drivers/infiniband/hw/mlx4/mad.c1
-rw-r--r--drivers/infiniband/hw/mlx5/main.c20
-rw-r--r--drivers/infiniband/hw/mlx5/mlx5_ib.h3
-rw-r--r--drivers/infiniband/hw/mlx5/qp.c59
-rw-r--r--drivers/infiniband/hw/nes/nes_cm.c3
-rw-r--r--drivers/infiniband/hw/qedr/qedr.h5
-rw-r--r--drivers/infiniband/hw/qedr/qedr_cm.c10
-rw-r--r--drivers/infiniband/hw/qedr/verbs.c68
-rw-r--r--drivers/infiniband/hw/qib/qib_rc.c4
-rw-r--r--drivers/infiniband/sw/rxe/rxe.h5
-rw-r--r--drivers/infiniband/sw/rxe/rxe_verbs.c9
-rw-r--r--drivers/infiniband/ulp/ipoib/ipoib_ethtool.c2
-rw-r--r--drivers/infiniband/ulp/ipoib/ipoib_ib.c1
-rw-r--r--drivers/infiniband/ulp/ipoib/ipoib_main.c17
-rw-r--r--drivers/infiniband/ulp/ipoib/ipoib_vlan.c11
-rw-r--r--drivers/infiniband/ulp/srp/ib_srp.c4
-rw-r--r--drivers/input/keyboard/tm2-touchkey.c2
-rw-r--r--drivers/input/misc/axp20x-pek.c44
-rw-r--r--drivers/input/misc/soc_button_array.c20
-rw-r--r--drivers/input/mouse/elan_i2c_i2c.c30
-rw-r--r--drivers/input/mouse/elantech.c16
-rw-r--r--drivers/input/mouse/synaptics.c37
-rw-r--r--drivers/input/rmi4/rmi_f03.c2
-rw-r--r--drivers/input/rmi4/rmi_f54.c17
-rw-r--r--drivers/input/serio/i8042-x86ia64io.h7
-rw-r--r--drivers/input/touchscreen/atmel_mxt_ts.c1
-rw-r--r--drivers/input/touchscreen/edt-ft5x06.c2
-rw-r--r--drivers/input/touchscreen/silead.c3
-rw-r--r--drivers/iommu/amd_iommu.c28
-rw-r--r--drivers/iommu/dmar.c11
-rw-r--r--drivers/iommu/intel-iommu.c4
-rw-r--r--drivers/iommu/intel_irq_remapping.c31
-rw-r--r--drivers/iommu/of_iommu.c9
-rw-r--r--drivers/irqchip/Kconfig6
-rw-r--r--drivers/irqchip/Makefile4
-rw-r--r--drivers/irqchip/irq-armada-370-xp.c148
-rw-r--r--drivers/irqchip/irq-aspeed-i2c-ic.c115
-rw-r--r--drivers/irqchip/irq-aspeed-vic.c5
-rw-r--r--drivers/irqchip/irq-gic-v2m.c2
-rw-r--r--drivers/irqchip/irq-gic-v3-its-pci-msi.c35
-rw-r--r--drivers/irqchip/irq-gic-v3-its-platform-msi.c2
-rw-r--r--drivers/irqchip/irq-gic-v3-its.c113
-rw-r--r--drivers/irqchip/irq-gic-v3.c3
-rw-r--r--drivers/irqchip/irq-i8259.c2
-rw-r--r--drivers/irqchip/irq-imx-gpcv2.c2
-rw-r--r--drivers/irqchip/irq-mbigen.c2
-rw-r--r--drivers/irqchip/irq-mips-cpu.c2
-rw-r--r--drivers/irqchip/irq-mips-gic.c10
-rw-r--r--drivers/irqchip/irq-mvebu-gicp.c279
-rw-r--r--drivers/irqchip/irq-mvebu-gicp.h11
-rw-r--r--drivers/irqchip/irq-mvebu-icu.c289
-rw-r--r--drivers/irqchip/irq-or1k-pic.c2
-rw-r--r--drivers/irqchip/irq-renesas-h8300h.c2
-rw-r--r--drivers/irqchip/irq-renesas-h8s.c2
-rw-r--r--drivers/irqchip/irq-sunxi-nmi.c68
-rw-r--r--drivers/irqchip/irq-xtensa-mx.c2
-rw-r--r--drivers/irqchip/irq-xtensa-pic.c2
-rw-r--r--drivers/irqchip/qcom-irq-combiner.c7
-rw-r--r--drivers/isdn/i4l/isdn_ppp.c2
-rw-r--r--drivers/isdn/mISDN/stack.c2
-rw-r--r--drivers/leds/leds-bcm6328.c4
-rw-r--r--drivers/leds/leds-pca955x.c2
-rw-r--r--drivers/leds/trigger/ledtrig-heartbeat.c31
-rw-r--r--drivers/lightnvm/core.c13
-rw-r--r--drivers/lightnvm/pblk-cache.c8
-rw-r--r--drivers/lightnvm/pblk-core.c617
-rw-r--r--drivers/lightnvm/pblk-gc.c475
-rw-r--r--drivers/lightnvm/pblk-init.c389
-rw-r--r--drivers/lightnvm/pblk-map.c75
-rw-r--r--drivers/lightnvm/pblk-rb.c106
-rw-r--r--drivers/lightnvm/pblk-read.c93
-rw-r--r--drivers/lightnvm/pblk-recovery.c275
-rw-r--r--drivers/lightnvm/pblk-rl.c90
-rw-r--r--drivers/lightnvm/pblk-sysfs.c94
-rw-r--r--drivers/lightnvm/pblk-write.c353
-rw-r--r--drivers/lightnvm/pblk.h296
-rw-r--r--drivers/lightnvm/rrpc.c10
-rw-r--r--drivers/md/bcache/bcache.h7
-rw-r--r--drivers/md/bcache/btree.c6
-rw-r--r--drivers/md/bcache/btree.h2
-rw-r--r--drivers/md/bcache/debug.c2
-rw-r--r--drivers/md/bcache/io.c6
-rw-r--r--drivers/md/bcache/journal.c2
-rw-r--r--drivers/md/bcache/movinggc.c10
-rw-r--r--drivers/md/bcache/request.c28
-rw-r--r--drivers/md/bcache/request.h2
-rw-r--r--drivers/md/bcache/super.c14
-rw-r--r--drivers/md/bcache/writeback.c4
-rw-r--r--drivers/md/bitmap.c8
-rw-r--r--drivers/md/dm-bio-prison-v1.c4
-rw-r--r--drivers/md/dm-bio-prison-v1.h2
-rw-r--r--drivers/md/dm-bufio.c30
-rw-r--r--drivers/md/dm-cache-target.c36
-rw-r--r--drivers/md/dm-crypt.c41
-rw-r--r--drivers/md/dm-flakey.c13
-rw-r--r--drivers/md/dm-integrity.c72
-rw-r--r--drivers/md/dm-io.c17
-rw-r--r--drivers/md/dm-ioctl.c5
-rw-r--r--drivers/md/dm-log-writes.c13
-rw-r--r--drivers/md/dm-mpath.c85
-rw-r--r--drivers/md/dm-raid.c17
-rw-r--r--drivers/md/dm-raid1.c50
-rw-r--r--drivers/md/dm-rq.c30
-rw-r--r--drivers/md/dm-rq.h2
-rw-r--r--drivers/md/dm-snap-persistent.c3
-rw-r--r--drivers/md/dm-snap.c15
-rw-r--r--drivers/md/dm-stripe.c17
-rw-r--r--drivers/md/dm-target.c2
-rw-r--r--drivers/md/dm-thin.c93
-rw-r--r--drivers/md/dm-verity-target.c20
-rw-r--r--drivers/md/dm-zero.c4
-rw-r--r--drivers/md/dm.c90
-rw-r--r--drivers/md/md-cluster.c4
-rw-r--r--drivers/md/md.c40
-rw-r--r--drivers/md/md.h1
-rw-r--r--drivers/md/multipath.c10
-rw-r--r--drivers/md/raid1.c40
-rw-r--r--drivers/md/raid10.c41
-rw-r--r--drivers/md/raid5-cache.c10
-rw-r--r--drivers/md/raid5-ppl.c8
-rw-r--r--drivers/md/raid5.c45
-rw-r--r--drivers/media/Kconfig6
-rw-r--r--drivers/media/Makefile4
-rw-r--r--drivers/media/cec/Kconfig15
-rw-r--r--drivers/media/cec/Makefile2
-rw-r--r--drivers/media/cec/cec-adap.c2
-rw-r--r--drivers/media/cec/cec-api.c8
-rw-r--r--drivers/media/cec/cec-core.c8
-rw-r--r--drivers/media/i2c/Kconfig9
-rw-r--r--drivers/media/i2c/tc358743.c2
-rw-r--r--drivers/media/platform/Kconfig10
-rw-r--r--drivers/media/platform/mtk-vcodec/vdec/vdec_h264_if.c8
-rw-r--r--drivers/media/platform/mtk-vcodec/vdec/vdec_vp8_if.c8
-rw-r--r--drivers/media/platform/mtk-vcodec/vdec/vdec_vp9_if.c8
-rw-r--r--drivers/media/platform/vivid/Kconfig3
-rw-r--r--drivers/media/rc/rc-ir-raw.c13
-rw-r--r--drivers/media/rc/sir_ir.c6
-rw-r--r--drivers/media/usb/pulse8-cec/Kconfig3
-rw-r--r--drivers/media/usb/rainshadow-cec/Kconfig3
-rw-r--r--drivers/media/usb/rainshadow-cec/rainshadow-cec.c3
-rw-r--r--drivers/media/v4l2-core/videobuf2-core.c2
-rw-r--r--drivers/memory/atmel-ebi.c2
-rw-r--r--drivers/memstick/core/ms_block.c7
-rw-r--r--drivers/memstick/core/mspro_block.c8
-rw-r--r--drivers/mfd/arizona-core.c3
-rw-r--r--drivers/misc/cxl/context.c6
-rw-r--r--drivers/misc/cxl/cxl.h18
-rw-r--r--drivers/misc/cxl/fault.c23
-rw-r--r--drivers/misc/cxl/file.c7
-rw-r--r--drivers/misc/cxl/main.c17
-rw-r--r--drivers/misc/cxl/native.c43
-rw-r--r--drivers/misc/cxl/pci.c11
-rw-r--r--drivers/misc/mei/bus.c4
-rw-r--r--drivers/misc/sgi-xp/xp.h12
-rw-r--r--drivers/misc/sgi-xp/xp_main.c36
-rw-r--r--drivers/mmc/core/block.c37
-rw-r--r--drivers/mmc/core/pwrseq_simple.c7
-rw-r--r--drivers/mmc/core/queue.c3
-rw-r--r--drivers/mmc/host/cavium-octeon.c15
-rw-r--r--drivers/mmc/host/cavium-thunderx.c6
-rw-r--r--drivers/mmc/host/cavium.c25
-rw-r--r--drivers/mmc/host/meson-gx-mmc.c9
-rw-r--r--drivers/mmc/host/sdhci-iproc.c3
-rw-r--r--drivers/mmc/host/sdhci-pci-core.c9
-rw-r--r--drivers/mmc/host/sdhci-xenon-phy.c14
-rw-r--r--drivers/mmc/host/sdhci-xenon.c6
-rw-r--r--drivers/mmc/host/sdhci-xenon.h1
-rw-r--r--drivers/mtd/mtd_blkdevs.c31
-rw-r--r--drivers/mtd/nand/nand_base.c46
-rw-r--r--drivers/mtd/nand/nand_ids.c1
-rw-r--r--drivers/mtd/nand/nand_samsung.c3
-rw-r--r--drivers/mtd/nand/tango_nand.c23
-rw-r--r--drivers/mtd/ubi/block.c8
-rw-r--r--drivers/net/arcnet/arcnet.c7
-rw-r--r--drivers/net/arcnet/capmode.c2
-rw-r--r--drivers/net/arcnet/com20020-pci.c6
-rw-r--r--drivers/net/arcnet/com20020.c2
-rw-r--r--drivers/net/bonding/bond_3ad.c29
-rw-r--r--drivers/net/bonding/bond_main.c22
-rw-r--r--drivers/net/caif/caif_hsi.c2
-rw-r--r--drivers/net/caif/caif_serial.c2
-rw-r--r--drivers/net/caif/caif_spi.c2
-rw-r--r--drivers/net/caif/caif_virtio.c2
-rw-r--r--drivers/net/can/dev.c3
-rw-r--r--drivers/net/can/peak_canfd/peak_canfd.c2
-rw-r--r--drivers/net/can/slcan.c7
-rw-r--r--drivers/net/can/usb/gs_usb.c2
-rw-r--r--drivers/net/can/usb/peak_usb/pcan_usb_core.c4
-rw-r--r--drivers/net/can/vcan.c4
-rw-r--r--drivers/net/can/vxcan.c4
-rw-r--r--drivers/net/dsa/mv88e6xxx/global2.h6
-rw-r--r--drivers/net/dummy.c4
-rw-r--r--drivers/net/ethernet/8390/ax88796.c7
-rw-r--r--drivers/net/ethernet/amazon/ena/ena_com.c35
-rw-r--r--drivers/net/ethernet/amazon/ena/ena_ethtool.c2
-rw-r--r--drivers/net/ethernet/amazon/ena/ena_netdev.c179
-rw-r--r--drivers/net/ethernet/amazon/ena/ena_netdev.h18
-rw-r--r--drivers/net/ethernet/amd/xgbe/xgbe-desc.c5
-rw-r--r--drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_utils.h3
-rw-r--r--drivers/net/ethernet/atheros/atlx/atl2.c8
-rw-r--r--drivers/net/ethernet/broadcom/bcmsysport.c7
-rw-r--r--drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c21
-rw-r--r--drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c2
-rw-r--r--drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.c15
-rw-r--r--drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.h1
-rw-r--r--drivers/net/ethernet/broadcom/bnxt/bnxt.c61
-rw-r--r--drivers/net/ethernet/broadcom/bnxt/bnxt.h6
-rw-r--r--drivers/net/ethernet/cavium/liquidio/octeon_main.h4
-rw-r--r--drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c35
-rw-r--r--drivers/net/ethernet/chelsio/cxgb4/t4_hw.c9
-rw-r--r--drivers/net/ethernet/chelsio/cxgb4/t4fw_version.h6
-rw-r--r--drivers/net/ethernet/emulex/benet/be_main.c4
-rw-r--r--drivers/net/ethernet/ethoc.c3
-rw-r--r--drivers/net/ethernet/freescale/dpaa/dpaa_eth.c2
-rw-r--r--drivers/net/ethernet/freescale/fec_main.c16
-rw-r--r--drivers/net/ethernet/freescale/fman/Kconfig1
-rw-r--r--drivers/net/ethernet/freescale/fman/mac.c2
-rw-r--r--drivers/net/ethernet/freescale/fsl_pq_mdio.c9
-rw-r--r--drivers/net/ethernet/hisilicon/hns/hns_dsaf_misc.c15
-rw-r--r--drivers/net/ethernet/hisilicon/hns/hns_ethtool.c16
-rw-r--r--drivers/net/ethernet/ibm/emac/core.c67
-rw-r--r--drivers/net/ethernet/ibm/ibmvnic.c8
-rw-r--r--drivers/net/ethernet/intel/i40e/i40e.h1
-rw-r--r--drivers/net/ethernet/intel/i40e/i40e_ethtool.c4
-rw-r--r--drivers/net/ethernet/intel/i40e/i40e_main.c43
-rw-r--r--drivers/net/ethernet/intel/i40e/i40e_txrx.c7
-rw-r--r--drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c2
-rw-r--r--drivers/net/ethernet/intel/i40evf/i40e_txrx.c3
-rw-r--r--drivers/net/ethernet/marvell/mvpp2.c76
-rw-r--r--drivers/net/ethernet/mellanox/mlx4/en_ethtool.c5
-rw-r--r--drivers/net/ethernet/mellanox/mlx4/mcg.c15
-rw-r--r--drivers/net/ethernet/mellanox/mlx4/qp.c19
-rw-r--r--drivers/net/ethernet/mellanox/mlx4/resource_tracker.c16
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/cmd.c41
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/en.h8
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/en_ethtool.c8
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/en_main.c3
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/en_rep.c2
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/en_rx.c8
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/en_rx_am.c45
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/en_stats.h11
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/en_tc.c61
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/eq.c2
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c77
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/fs_core.c2
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/health.c13
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/main.c34
-rw-r--r--drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c3
-rw-r--r--drivers/net/ethernet/qlogic/qed/qed_debug.c2
-rw-r--r--drivers/net/ethernet/qlogic/qed/qed_main.c3
-rw-r--r--drivers/net/ethernet/qlogic/qlcnic/qlcnic.h26
-rw-r--r--drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.c2
-rw-r--r--drivers/net/ethernet/qlogic/qlcnic/qlcnic_hw.c2
-rw-r--r--drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c2
-rw-r--r--drivers/net/ethernet/qlogic/qlcnic/qlcnic_sriov_common.c2
-rw-r--r--drivers/net/ethernet/qualcomm/emac/emac-mac.c2
-rw-r--r--drivers/net/ethernet/qualcomm/emac/emac-phy.c75
-rw-r--r--drivers/net/ethernet/qualcomm/emac/emac.c22
-rw-r--r--drivers/net/ethernet/renesas/ravb_main.c24
-rw-r--r--drivers/net/ethernet/rocker/rocker_ofdpa.c2
-rw-r--r--drivers/net/ethernet/sfc/ef10.c15
-rw-r--r--drivers/net/ethernet/sfc/ef10_sriov.c2
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/altr_tse_pcs.c6
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/dwmac4_descs.c11
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/stmmac_main.c52
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/stmmac_ptp.h3
-rw-r--r--drivers/net/ethernet/ti/cpsw-common.c2
-rw-r--r--drivers/net/geneve.c12
-rw-r--r--drivers/net/gtp.c4
-rw-r--r--drivers/net/hamradio/6pack.c2
-rw-r--r--drivers/net/hamradio/bpqether.c2
-rw-r--r--drivers/net/hamradio/hdlcdrv.c2
-rw-r--r--drivers/net/hyperv/hyperv_net.h5
-rw-r--r--drivers/net/hyperv/netvsc_drv.c58
-rw-r--r--drivers/net/hyperv/rndis_filter.c30
-rw-r--r--drivers/net/ifb.c4
-rw-r--r--drivers/net/ipvlan/ipvlan_main.c2
-rw-r--r--drivers/net/loopback.c4
-rw-r--r--drivers/net/macsec.c4
-rw-r--r--drivers/net/macvlan.c87
-rw-r--r--drivers/net/netconsole.c2
-rw-r--r--drivers/net/nlmon.c2
-rw-r--r--drivers/net/phy/Kconfig3
-rw-r--r--drivers/net/phy/dp83640.c2
-rw-r--r--drivers/net/phy/marvell.c68
-rw-r--r--drivers/net/phy/mdio_bus.c13
-rw-r--r--drivers/net/phy/micrel.c44
-rw-r--r--drivers/net/phy/phy.c4
-rw-r--r--drivers/net/slip/slip.c7
-rw-r--r--drivers/net/team/team.c4
-rw-r--r--drivers/net/tun.c4
-rw-r--r--drivers/net/usb/ax88179_178a.c16
-rw-r--r--drivers/net/usb/cdc-phonet.c2
-rw-r--r--drivers/net/usb/cdc_ether.c31
-rw-r--r--drivers/net/usb/qmi_wwan.c6
-rw-r--r--drivers/net/usb/r8152.c2
-rw-r--r--drivers/net/usb/smsc95xx.c13
-rw-r--r--drivers/net/veth.c8
-rw-r--r--drivers/net/virtio_net.c7
-rw-r--r--drivers/net/vrf.c38
-rw-r--r--drivers/net/vsockmon.c2
-rw-r--r--drivers/net/vxlan.c41
-rw-r--r--drivers/net/wan/dlci.c2
-rw-r--r--drivers/net/wan/hdlc_fr.c2
-rw-r--r--drivers/net/wan/lapbether.c2
-rw-r--r--drivers/net/wireless/ath/ath6kl/main.c2
-rw-r--r--drivers/net/wireless/ath/wcn36xx/main.c2
-rw-r--r--drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c1
-rw-r--r--drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c3
-rw-r--r--drivers/net/wireless/broadcom/brcm80211/brcmfmac/firmware.c35
-rw-r--r--drivers/net/wireless/broadcom/brcm80211/brcmfmac/firmware.h4
-rw-r--r--drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwsignal.c2
-rw-r--r--drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c17
-rw-r--r--drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c20
-rw-r--r--drivers/net/wireless/broadcom/brcm80211/brcmfmac/usb.c9
-rw-r--r--drivers/net/wireless/cisco/airo.c2
-rw-r--r--drivers/net/wireless/intel/iwlwifi/iwl-7000.c4
-rw-r--r--drivers/net/wireless/intel/iwlwifi/iwl-8000.c4
-rw-r--r--drivers/net/wireless/intel/iwlwifi/iwl-prph.h1
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/fw-api-rs.h5
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/fw-api-tx.h3
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/fw-dbg.c12
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/mac-ctxt.c2
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/mvm.h6
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/ops.c32
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/rs.c46
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/rs.h15
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/sta.c26
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/sta.h2
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/tt.c8
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/tx.c12
-rw-r--r--drivers/net/wireless/intel/iwlwifi/pcie/trans.c6
-rw-r--r--drivers/net/wireless/intel/iwlwifi/pcie/tx-gen2.c9
-rw-r--r--drivers/net/wireless/intersil/hostap/hostap_ioctl.c2
-rw-r--r--drivers/net/wireless/intersil/hostap/hostap_main.c2
-rw-r--r--drivers/net/wireless/mac80211_hwsim.c2
-rw-r--r--drivers/net/wireless/marvell/libertas/main.c2
-rw-r--r--drivers/net/wireless/marvell/mwifiex/main.c2
-rw-r--r--drivers/net/xen-netback/common.h1
-rw-r--r--drivers/net/xen-netback/interface.c6
-rw-r--r--drivers/net/xen-netback/netback.c6
-rw-r--r--drivers/ntb/hw/intel/ntb_hw_intel.c2
-rw-r--r--drivers/ntb/ntb_transport.c58
-rw-r--r--drivers/ntb/test/ntb_perf.c4
-rw-r--r--drivers/nubus/nubus.c125
-rw-r--r--drivers/nvdimm/blk.c5
-rw-r--r--drivers/nvdimm/btt.c5
-rw-r--r--drivers/nvdimm/btt_devs.c9
-rw-r--r--drivers/nvdimm/pmem.c29
-rw-r--r--drivers/nvme/host/Kconfig12
-rw-r--r--drivers/nvme/host/Makefile1
-rw-r--r--drivers/nvme/host/core.c609
-rw-r--r--drivers/nvme/host/fabrics.c73
-rw-r--r--drivers/nvme/host/fabrics.h6
-rw-r--r--drivers/nvme/host/fc.c295
-rw-r--r--drivers/nvme/host/lightnvm.c18
-rw-r--r--drivers/nvme/host/nvme.h46
-rw-r--r--drivers/nvme/host/pci.c668
-rw-r--r--drivers/nvme/host/rdma.c266
-rw-r--r--drivers/nvme/host/scsi.c2460
-rw-r--r--drivers/nvme/target/admin-cmd.c65
-rw-r--r--drivers/nvme/target/configfs.c68
-rw-r--r--drivers/nvme/target/core.c3
-rw-r--r--drivers/nvme/target/discovery.c4
-rw-r--r--drivers/nvme/target/fc.c10
-rw-r--r--drivers/nvme/target/fcloop.c2
-rw-r--r--drivers/nvme/target/io-cmd.c4
-rw-r--r--drivers/nvme/target/loop.c69
-rw-r--r--drivers/nvme/target/nvmet.h2
-rw-r--r--drivers/nvme/target/rdma.c102
-rw-r--r--drivers/of/device.c4
-rw-r--r--drivers/of/platform.c3
-rw-r--r--drivers/parisc/ccio-dma.c12
-rw-r--r--drivers/parisc/dino.c5
-rw-r--r--drivers/parisc/lba_pci.c6
-rw-r--r--drivers/parisc/sba_iommu.c14
-rw-r--r--drivers/pci/Kconfig3
-rw-r--r--drivers/pci/access.c28
-rw-r--r--drivers/pci/dwc/pci-imx6.c33
-rw-r--r--drivers/pci/endpoint/Kconfig1
-rw-r--r--drivers/pci/endpoint/functions/Kconfig1
-rw-r--r--drivers/pci/host/vmd.c8
-rw-r--r--drivers/pci/msi.c2
-rw-r--r--drivers/pci/pci-acpi.c13
-rw-r--r--drivers/pci/pci-driver.c47
-rw-r--r--drivers/pci/pci-label.c4
-rw-r--r--drivers/pci/pci.c3
-rw-r--r--drivers/pci/switch/switchtec.c16
-rw-r--r--drivers/perf/arm_pmu_acpi.c11
-rw-r--r--drivers/phy/Kconfig492
-rw-r--r--drivers/phy/Makefile71
-rw-r--r--drivers/phy/allwinner/Kconfig31
-rw-r--r--drivers/phy/allwinner/Makefile2
-rw-r--r--drivers/phy/allwinner/phy-sun4i-usb.c (renamed from drivers/phy/phy-sun4i-usb.c)0
-rw-r--r--drivers/phy/allwinner/phy-sun9i-usb.c (renamed from drivers/phy/phy-sun9i-usb.c)0
-rw-r--r--drivers/phy/amlogic/Kconfig27
-rw-r--r--drivers/phy/amlogic/Makefile2
-rw-r--r--drivers/phy/amlogic/phy-meson-gxl-usb2.c273
-rw-r--r--drivers/phy/amlogic/phy-meson8b-usb2.c (renamed from drivers/phy/phy-meson8b-usb2.c)5
-rw-r--r--drivers/phy/broadcom/Kconfig69
-rw-r--r--drivers/phy/broadcom/Makefile7
-rw-r--r--drivers/phy/broadcom/phy-bcm-cygnus-pcie.c (renamed from drivers/phy/phy-bcm-cygnus-pcie.c)0
-rw-r--r--drivers/phy/broadcom/phy-bcm-kona-usb2.c (renamed from drivers/phy/phy-bcm-kona-usb2.c)0
-rw-r--r--drivers/phy/broadcom/phy-bcm-ns-usb2.c (renamed from drivers/phy/phy-bcm-ns-usb2.c)0
-rw-r--r--drivers/phy/broadcom/phy-bcm-ns-usb3.c (renamed from drivers/phy/phy-bcm-ns-usb3.c)230
-rw-r--r--drivers/phy/broadcom/phy-bcm-ns2-pcie.c (renamed from drivers/phy/phy-bcm-ns2-pcie.c)0
-rw-r--r--drivers/phy/broadcom/phy-bcm-ns2-usbdrd.c437
-rw-r--r--drivers/phy/broadcom/phy-brcm-sata.c (renamed from drivers/phy/phy-brcm-sata.c)73
-rw-r--r--drivers/phy/hisilicon/Kconfig20
-rw-r--r--drivers/phy/hisilicon/Makefile2
-rw-r--r--drivers/phy/hisilicon/phy-hi6220-usb.c (renamed from drivers/phy/phy-hi6220-usb.c)0
-rw-r--r--drivers/phy/hisilicon/phy-hix5hd2-sata.c (renamed from drivers/phy/phy-hix5hd2-sata.c)0
-rw-r--r--drivers/phy/marvell/Kconfig50
-rw-r--r--drivers/phy/marvell/Makefile6
-rw-r--r--drivers/phy/marvell/phy-armada375-usb2.c (renamed from drivers/phy/phy-armada375-usb2.c)0
-rw-r--r--drivers/phy/marvell/phy-berlin-sata.c (renamed from drivers/phy/phy-berlin-sata.c)0
-rw-r--r--drivers/phy/marvell/phy-berlin-usb.c (renamed from drivers/phy/phy-berlin-usb.c)0
-rw-r--r--drivers/phy/marvell/phy-mvebu-sata.c (renamed from drivers/phy/phy-mvebu-sata.c)0
-rw-r--r--drivers/phy/marvell/phy-pxa-28nm-hsic.c (renamed from drivers/phy/phy-pxa-28nm-hsic.c)0
-rw-r--r--drivers/phy/marvell/phy-pxa-28nm-usb2.c (renamed from drivers/phy/phy-pxa-28nm-usb2.c)0
-rw-r--r--drivers/phy/motorola/Kconfig12
-rw-r--r--drivers/phy/motorola/Makefile5
-rw-r--r--drivers/phy/motorola/phy-cpcap-usb.c676
-rw-r--r--drivers/phy/qualcomm/Kconfig58
-rw-r--r--drivers/phy/qualcomm/Makefile9
-rw-r--r--drivers/phy/qualcomm/phy-qcom-apq8064-sata.c (renamed from drivers/phy/phy-qcom-apq8064-sata.c)0
-rw-r--r--drivers/phy/qualcomm/phy-qcom-ipq806x-sata.c (renamed from drivers/phy/phy-qcom-ipq806x-sata.c)0
-rw-r--r--drivers/phy/qualcomm/phy-qcom-qmp.c (renamed from drivers/phy/phy-qcom-qmp.c)14
-rw-r--r--drivers/phy/qualcomm/phy-qcom-qusb2.c (renamed from drivers/phy/phy-qcom-qusb2.c)0
-rw-r--r--drivers/phy/qualcomm/phy-qcom-ufs-i.h (renamed from drivers/phy/phy-qcom-ufs-i.h)0
-rw-r--r--drivers/phy/qualcomm/phy-qcom-ufs-qmp-14nm.c (renamed from drivers/phy/phy-qcom-ufs-qmp-14nm.c)0
-rw-r--r--drivers/phy/qualcomm/phy-qcom-ufs-qmp-14nm.h (renamed from drivers/phy/phy-qcom-ufs-qmp-14nm.h)0
-rw-r--r--drivers/phy/qualcomm/phy-qcom-ufs-qmp-20nm.c (renamed from drivers/phy/phy-qcom-ufs-qmp-20nm.c)0
-rw-r--r--drivers/phy/qualcomm/phy-qcom-ufs-qmp-20nm.h (renamed from drivers/phy/phy-qcom-ufs-qmp-20nm.h)0
-rw-r--r--drivers/phy/qualcomm/phy-qcom-ufs.c (renamed from drivers/phy/phy-qcom-ufs.c)0
-rw-r--r--drivers/phy/qualcomm/phy-qcom-usb-hs.c (renamed from drivers/phy/phy-qcom-usb-hs.c)3
-rw-r--r--drivers/phy/qualcomm/phy-qcom-usb-hsic.c (renamed from drivers/phy/phy-qcom-usb-hsic.c)3
-rw-r--r--drivers/phy/renesas/Kconfig24
-rw-r--r--drivers/phy/renesas/Makefile3
-rw-r--r--drivers/phy/renesas/phy-rcar-gen2.c (renamed from drivers/phy/phy-rcar-gen2.c)0
-rw-r--r--drivers/phy/renesas/phy-rcar-gen3-usb2.c (renamed from drivers/phy/phy-rcar-gen3-usb2.c)0
-rw-r--r--drivers/phy/renesas/phy-rcar-gen3-usb3.c226
-rw-r--r--drivers/phy/rockchip/Kconfig51
-rw-r--r--drivers/phy/rockchip/Makefile6
-rw-r--r--drivers/phy/rockchip/phy-rockchip-dp.c (renamed from drivers/phy/phy-rockchip-dp.c)0
-rw-r--r--drivers/phy/rockchip/phy-rockchip-emmc.c (renamed from drivers/phy/phy-rockchip-emmc.c)0
-rw-r--r--drivers/phy/rockchip/phy-rockchip-inno-usb2.c (renamed from drivers/phy/phy-rockchip-inno-usb2.c)74
-rw-r--r--drivers/phy/rockchip/phy-rockchip-pcie.c (renamed from drivers/phy/phy-rockchip-pcie.c)0
-rw-r--r--drivers/phy/rockchip/phy-rockchip-typec.c (renamed from drivers/phy/phy-rockchip-typec.c)0
-rw-r--r--drivers/phy/rockchip/phy-rockchip-usb.c (renamed from drivers/phy/phy-rockchip-usb.c)0
-rw-r--r--drivers/phy/samsung/Kconfig95
-rw-r--r--drivers/phy/samsung/Makefile11
-rw-r--r--drivers/phy/samsung/phy-exynos-dp-video.c (renamed from drivers/phy/phy-exynos-dp-video.c)0
-rw-r--r--drivers/phy/samsung/phy-exynos-mipi-video.c (renamed from drivers/phy/phy-exynos-mipi-video.c)0
-rw-r--r--drivers/phy/samsung/phy-exynos-pcie.c (renamed from drivers/phy/phy-exynos-pcie.c)0
-rw-r--r--drivers/phy/samsung/phy-exynos4210-usb2.c (renamed from drivers/phy/phy-exynos4210-usb2.c)0
-rw-r--r--drivers/phy/samsung/phy-exynos4x12-usb2.c (renamed from drivers/phy/phy-exynos4x12-usb2.c)0
-rw-r--r--drivers/phy/samsung/phy-exynos5-usbdrd.c (renamed from drivers/phy/phy-exynos5-usbdrd.c)0
-rw-r--r--drivers/phy/samsung/phy-exynos5250-sata.c (renamed from drivers/phy/phy-exynos5250-sata.c)0
-rw-r--r--drivers/phy/samsung/phy-exynos5250-usb2.c (renamed from drivers/phy/phy-exynos5250-usb2.c)0
-rw-r--r--drivers/phy/samsung/phy-s5pv210-usb2.c (renamed from drivers/phy/phy-s5pv210-usb2.c)0
-rw-r--r--drivers/phy/samsung/phy-samsung-usb2.c (renamed from drivers/phy/phy-samsung-usb2.c)0
-rw-r--r--drivers/phy/samsung/phy-samsung-usb2.h (renamed from drivers/phy/phy-samsung-usb2.h)0
-rw-r--r--drivers/phy/st/Kconfig33
-rw-r--r--drivers/phy/st/Makefile4
-rw-r--r--drivers/phy/st/phy-miphy28lp.c (renamed from drivers/phy/phy-miphy28lp.c)0
-rw-r--r--drivers/phy/st/phy-spear1310-miphy.c (renamed from drivers/phy/phy-spear1310-miphy.c)0
-rw-r--r--drivers/phy/st/phy-spear1340-miphy.c (renamed from drivers/phy/phy-spear1340-miphy.c)0
-rw-r--r--drivers/phy/st/phy-stih407-usb.c (renamed from drivers/phy/phy-stih407-usb.c)0
-rw-r--r--drivers/phy/ti/Kconfig78
-rw-r--r--drivers/phy/ti/Makefile7
-rw-r--r--drivers/phy/ti/phy-da8xx-usb.c (renamed from drivers/phy/phy-da8xx-usb.c)0
-rw-r--r--drivers/phy/ti/phy-dm816x-usb.c (renamed from drivers/phy/phy-dm816x-usb.c)0
-rw-r--r--drivers/phy/ti/phy-omap-control.c (renamed from drivers/phy/phy-omap-control.c)0
-rw-r--r--drivers/phy/ti/phy-omap-usb2.c (renamed from drivers/phy/phy-omap-usb2.c)0
-rw-r--r--drivers/phy/ti/phy-ti-pipe3.c (renamed from drivers/phy/phy-ti-pipe3.c)0
-rw-r--r--drivers/phy/ti/phy-tusb1210.c (renamed from drivers/phy/phy-tusb1210.c)41
-rw-r--r--drivers/phy/ti/phy-twl4030-usb.c (renamed from drivers/phy/phy-twl4030-usb.c)0
-rw-r--r--drivers/phy/ulpi_phy.h31
-rw-r--r--drivers/pinctrl/core.c20
-rw-r--r--drivers/pinctrl/freescale/pinctrl-mxs.c16
-rw-r--r--drivers/pinctrl/intel/pinctrl-cherryview.c24
-rw-r--r--drivers/pinctrl/pinconf-generic.c3
-rw-r--r--drivers/pinctrl/pinctrl-amd.c91
-rw-r--r--drivers/pinctrl/pinctrl-rockchip.c44
-rw-r--r--drivers/pinctrl/pinmux.c21
-rw-r--r--drivers/pinctrl/stm32/pinctrl-stm32.c2
-rw-r--r--drivers/pinctrl/sunxi/pinctrl-sun8i-a83t.c2
-rw-r--r--drivers/platform/goldfish/goldfish_pipe.c2
-rw-r--r--drivers/platform/x86/intel_telemetry_debugfs.c16
-rw-r--r--drivers/powercap/powercap_sys.c1
-rw-r--r--drivers/ras/cec.c2
-rw-r--r--drivers/ras/ras.c2
-rw-r--r--drivers/reset/hisilicon/hi6220_reset.c2
-rw-r--r--drivers/rtc/rtc-cmos.c2
-rw-r--r--drivers/rtc/rtc-imxdi.c2
-rw-r--r--drivers/s390/block/Kconfig7
-rw-r--r--drivers/s390/block/Makefile3
-rw-r--r--drivers/s390/block/dasd.c112
-rw-r--r--drivers/s390/block/dasd_devmap.c75
-rw-r--r--drivers/s390/block/dcssblk.c2
-rw-r--r--drivers/s390/block/scm_blk.c268
-rw-r--r--drivers/s390/block/scm_blk.h64
-rw-r--r--drivers/s390/block/scm_blk_cluster.c255
-rw-r--r--drivers/s390/block/xpram.c2
-rw-r--r--drivers/s390/cio/css.c49
-rw-r--r--drivers/s390/cio/device.c42
-rw-r--r--drivers/s390/cio/eadm_sch.c6
-rw-r--r--drivers/s390/cio/scm.c2
-rw-r--r--drivers/s390/cio/vfio_ccw_drv.c58
-rw-r--r--drivers/s390/cio/vfio_ccw_ops.c12
-rw-r--r--drivers/s390/crypto/ap_bus.c59
-rw-r--r--drivers/s390/crypto/ap_card.c9
-rw-r--r--drivers/s390/crypto/ap_queue.c9
-rw-r--r--drivers/s390/crypto/pkey_api.c6
-rw-r--r--drivers/s390/crypto/zcrypt_api.c12
-rw-r--r--drivers/s390/crypto/zcrypt_cca_key.h115
-rw-r--r--drivers/s390/crypto/zcrypt_msgtype6.c4
-rw-r--r--drivers/s390/net/netiucv.c4
-rw-r--r--drivers/sbus/char/jsflash.c5
-rw-r--r--drivers/scsi/bnx2fc/bnx2fc.h1
-rw-r--r--drivers/scsi/bnx2fc/bnx2fc_fcoe.c10
-rw-r--r--drivers/scsi/csiostor/csio_hw.c5
-rw-r--r--drivers/scsi/cxgbi/cxgb4i/cxgb4i.c1
-rw-r--r--drivers/scsi/cxgbi/libcxgbi.c54
-rw-r--r--drivers/scsi/cxgbi/libcxgbi.h17
-rw-r--r--drivers/scsi/device_handler/scsi_dh_rdac.c10
-rw-r--r--drivers/scsi/dpt/dpti_i2o.h2
-rw-r--r--drivers/scsi/ibmvscsi_tgt/ibmvscsi_tgt.c27
-rw-r--r--drivers/scsi/ips.c12
-rw-r--r--drivers/scsi/ips.h4
-rw-r--r--drivers/scsi/libfc/fc_rport.c2
-rw-r--r--drivers/scsi/lpfc/lpfc.h23
-rw-r--r--drivers/scsi/lpfc/lpfc_attr.c47
-rw-r--r--drivers/scsi/lpfc/lpfc_crtn.h13
-rw-r--r--drivers/scsi/lpfc/lpfc_ct.c6
-rw-r--r--drivers/scsi/lpfc/lpfc_debugfs.c69
-rw-r--r--drivers/scsi/lpfc/lpfc_disc.h1
-rw-r--r--drivers/scsi/lpfc/lpfc_els.c26
-rw-r--r--drivers/scsi/lpfc/lpfc_hbadisc.c9
-rw-r--r--drivers/scsi/lpfc/lpfc_hw4.h16
-rw-r--r--drivers/scsi/lpfc/lpfc_init.c137
-rw-r--r--drivers/scsi/lpfc/lpfc_mem.c100
-rw-r--r--drivers/scsi/lpfc/lpfc_nportdisc.c13
-rw-r--r--drivers/scsi/lpfc/lpfc_nvmet.c418
-rw-r--r--drivers/scsi/lpfc/lpfc_nvmet.h14
-rw-r--r--drivers/scsi/lpfc/lpfc_sli.c357
-rw-r--r--drivers/scsi/lpfc/lpfc_sli4.h19
-rw-r--r--drivers/scsi/lpfc/lpfc_version.h2
-rw-r--r--drivers/scsi/osd/osd_initiator.c29
-rw-r--r--drivers/scsi/osst.c3
-rw-r--r--drivers/scsi/qedi/qedi.h3
-rw-r--r--drivers/scsi/qedi/qedi_fw.c3
-rw-r--r--drivers/scsi/qedi/qedi_iscsi.c7
-rw-r--r--drivers/scsi/qedi/qedi_main.c29
-rw-r--r--drivers/scsi/qla2xxx/qla_bsg.c9
-rw-r--r--drivers/scsi/qla2xxx/qla_dbg.c4
-rw-r--r--drivers/scsi/qla2xxx/qla_def.h1
-rw-r--r--drivers/scsi/qla2xxx/qla_init.c5
-rw-r--r--drivers/scsi/qla2xxx/qla_inline.h26
-rw-r--r--drivers/scsi/qla2xxx/qla_isr.c2
-rw-r--r--drivers/scsi/qla2xxx/qla_mbx.c13
-rw-r--r--drivers/scsi/qla2xxx/qla_os.c46
-rw-r--r--drivers/scsi/qla2xxx/qla_target.c8
-rw-r--r--drivers/scsi/qla2xxx/qla_tmpl.c2
-rw-r--r--drivers/scsi/scsi_debug.c12
-rw-r--r--drivers/scsi/scsi_error.c3
-rw-r--r--drivers/scsi/scsi_lib.c106
-rw-r--r--drivers/scsi/scsi_transport_sas.c10
-rw-r--r--drivers/scsi/sd.c63
-rw-r--r--drivers/scsi/sg.c13
-rw-r--r--drivers/scsi/st.c3
-rw-r--r--drivers/scsi/ufs/ufshcd.c7
-rw-r--r--drivers/staging/android/ion/ion-ioctl.c4
-rw-r--r--drivers/staging/android/ion/ion.c30
-rw-r--r--drivers/staging/android/ion/ion.h14
-rw-r--r--drivers/staging/android/ion/ion_carveout_heap.c2
-rw-r--r--drivers/staging/android/ion/ion_system_heap.c6
-rw-r--r--drivers/staging/android/uapi/ion.h24
-rw-r--r--drivers/staging/ccree/Kconfig13
-rw-r--r--drivers/staging/ccree/Makefile2
-rw-r--r--drivers/staging/ccree/cc_bitops.h62
-rw-r--r--drivers/staging/ccree/cc_crypto_ctx.h147
-rw-r--r--drivers/staging/ccree/cc_hal.h15
-rw-r--r--drivers/staging/ccree/cc_hw_queue_defs.h896
-rw-r--r--drivers/staging/ccree/cc_lli_defs.h57
-rw-r--r--drivers/staging/ccree/cc_pal_log.h188
-rw-r--r--drivers/staging/ccree/cc_pal_log_plat.h33
-rw-r--r--drivers/staging/ccree/cc_pal_types.h97
-rw-r--r--drivers/staging/ccree/cc_pal_types_plat.h29
-rw-r--r--drivers/staging/ccree/cc_regs.h98
-rw-r--r--drivers/staging/ccree/dx_crys_kernel.h314
-rw-r--r--drivers/staging/ccree/dx_env.h224
-rw-r--r--drivers/staging/ccree/dx_host.h262
-rw-r--r--drivers/staging/ccree/dx_reg_base_host.h15
-rw-r--r--drivers/staging/ccree/dx_reg_common.h8
-rw-r--r--drivers/staging/ccree/hash_defs.h62
-rw-r--r--drivers/staging/ccree/hw_queue_defs_plat.h43
-rw-r--r--drivers/staging/ccree/ssi_aead.c1442
-rw-r--r--drivers/staging/ccree/ssi_aead.h63
-rw-r--r--drivers/staging/ccree/ssi_buffer_mgr.c824
-rw-r--r--drivers/staging/ccree/ssi_buffer_mgr.h35
-rw-r--r--drivers/staging/ccree/ssi_cipher.c616
-rw-r--r--drivers/staging/ccree/ssi_cipher.h26
-rw-r--r--drivers/staging/ccree/ssi_config.h33
-rw-r--r--drivers/staging/ccree/ssi_driver.c157
-rw-r--r--drivers/staging/ccree/ssi_driver.h84
-rw-r--r--drivers/staging/ccree/ssi_fips.c42
-rw-r--r--drivers/staging/ccree/ssi_fips.h45
-rw-r--r--drivers/staging/ccree/ssi_fips_data.h137
-rw-r--r--drivers/staging/ccree/ssi_fips_ext.c76
-rw-r--r--drivers/staging/ccree/ssi_fips_ll.c1034
-rw-r--r--drivers/staging/ccree/ssi_fips_local.c170
-rw-r--r--drivers/staging/ccree/ssi_fips_local.h34
-rw-r--r--drivers/staging/ccree/ssi_hash.c1953
-rw-r--r--drivers/staging/ccree/ssi_hash.h58
-rw-r--r--drivers/staging/ccree/ssi_ivgen.c159
-rw-r--r--drivers/staging/ccree/ssi_ivgen.h41
-rw-r--r--drivers/staging/ccree/ssi_pm.c46
-rw-r--r--drivers/staging/ccree/ssi_pm.h13
-rw-r--r--drivers/staging/ccree/ssi_pm_ext.c60
-rw-r--r--drivers/staging/ccree/ssi_pm_ext.h33
-rw-r--r--drivers/staging/ccree/ssi_request_mgr.c393
-rw-r--r--drivers/staging/ccree/ssi_request_mgr.h26
-rw-r--r--drivers/staging/ccree/ssi_sram_mgr.c50
-rw-r--r--drivers/staging/ccree/ssi_sram_mgr.h47
-rw-r--r--drivers/staging/ccree/ssi_sysfs.c119
-rw-r--r--drivers/staging/ccree/ssi_sysfs.h9
-rw-r--r--drivers/staging/comedi/comedi_fops.c42
-rw-r--r--drivers/staging/comedi/drivers/ni_labpc_isadma.h2
-rw-r--r--drivers/staging/comedi/drivers/ni_labpc_regs.h2
-rw-r--r--drivers/staging/comedi/drivers/s626.c9
-rw-r--r--drivers/staging/dgnc/dgnc_driver.c2
-rw-r--r--drivers/staging/dgnc/dgnc_driver.h13
-rw-r--r--drivers/staging/dgnc/dgnc_tty.c150
-rw-r--r--drivers/staging/emxx_udc/emxx_udc.c398
-rw-r--r--drivers/staging/emxx_udc/emxx_udc.h226
-rw-r--r--drivers/staging/fbtft/fb_agm1264k-fl.c4
-rw-r--r--drivers/staging/fbtft/fb_hx8340bn.c2
-rw-r--r--drivers/staging/fbtft/fbtft-io.c2
-rw-r--r--drivers/staging/fsl-dpaa2/ethernet/dpaa2-eth.c268
-rw-r--r--drivers/staging/fsl-dpaa2/ethernet/dpaa2-eth.h33
-rw-r--r--drivers/staging/fsl-dpaa2/ethernet/dpaa2-ethtool.c64
-rw-r--r--drivers/staging/fsl-dpaa2/ethernet/dpni.c5
-rw-r--r--drivers/staging/fsl-mc/README.txt6
-rw-r--r--drivers/staging/fsl-mc/bus/Makefile1
-rw-r--r--drivers/staging/fsl-mc/bus/dpbp-cmd.h2
-rw-r--r--drivers/staging/fsl-mc/bus/dpbp.c4
-rw-r--r--drivers/staging/fsl-mc/bus/dpcon.c4
-rw-r--r--drivers/staging/fsl-mc/bus/dpio/dpio-service.c8
-rw-r--r--drivers/staging/fsl-mc/bus/dpio/dpio.c4
-rw-r--r--drivers/staging/fsl-mc/bus/dpmcp-cmd.h2
-rw-r--r--drivers/staging/fsl-mc/bus/dpmcp.c4
-rw-r--r--drivers/staging/fsl-mc/bus/dpmng-cmd.h2
-rw-r--r--drivers/staging/fsl-mc/bus/dpmng.c74
-rw-r--r--drivers/staging/fsl-mc/bus/dprc-cmd.h2
-rw-r--r--drivers/staging/fsl-mc/bus/dprc-driver.c67
-rw-r--r--drivers/staging/fsl-mc/bus/dprc.c8
-rw-r--r--drivers/staging/fsl-mc/bus/dprc.h (renamed from drivers/staging/fsl-mc/include/dprc.h)49
-rw-r--r--drivers/staging/fsl-mc/bus/fsl-mc-allocator.c23
-rw-r--r--drivers/staging/fsl-mc/bus/fsl-mc-bus.c91
-rw-r--r--drivers/staging/fsl-mc/bus/fsl-mc-msi.c3
-rw-r--r--drivers/staging/fsl-mc/bus/fsl-mc-private.h65
-rw-r--r--drivers/staging/fsl-mc/bus/irq-gic-v3-its-fsl-mc-msi.c1
-rw-r--r--drivers/staging/fsl-mc/bus/mc-io.c3
-rw-r--r--drivers/staging/fsl-mc/bus/mc-sys.c2
-rw-r--r--drivers/staging/fsl-mc/include/dpmng.h67
-rw-r--r--drivers/staging/fsl-mc/include/mc-bus.h111
-rw-r--r--drivers/staging/fsl-mc/include/mc-cmd.h130
-rw-r--r--drivers/staging/fsl-mc/include/mc-sys.h99
-rw-r--r--drivers/staging/fsl-mc/include/mc.h204
-rw-r--r--drivers/staging/gdm724x/gdm_usb.c8
-rw-r--r--drivers/staging/greybus/Kconfig10
-rw-r--r--drivers/staging/greybus/Makefile2
-rw-r--r--drivers/staging/greybus/arche-apb-ctrl.c11
-rw-r--r--drivers/staging/greybus/arche-platform.c154
-rw-r--r--drivers/staging/greybus/arche_platform.h8
-rw-r--r--drivers/staging/greybus/light.c4
-rw-r--r--drivers/staging/greybus/power_supply.c2
-rw-r--r--drivers/staging/iio/cdc/ad7152.c6
-rw-r--r--drivers/staging/iio/frequency/ad9834.c22
-rw-r--r--drivers/staging/iio/frequency/dds.h2
-rw-r--r--drivers/staging/iio/light/Kconfig10
-rw-r--r--drivers/staging/iio/light/Makefile3
-rw-r--r--drivers/staging/iio/light/tsl2x7x.c (renamed from drivers/staging/iio/light/tsl2x7x_core.c)66
-rw-r--r--drivers/staging/iio/meter/ade7753.c101
-rw-r--r--drivers/staging/iio/meter/ade7754.c56
-rw-r--r--drivers/staging/iio/meter/ade7758_core.c50
-rw-r--r--drivers/staging/iio/meter/ade7854.c88
-rw-r--r--drivers/staging/ks7010/eap_packet.h4
-rw-r--r--drivers/staging/ks7010/ks7010_sdio.c10
-rw-r--r--drivers/staging/ks7010/ks_hostif.c105
-rw-r--r--drivers/staging/ks7010/ks_hostif.h192
-rw-r--r--drivers/staging/ks7010/ks_wlan.h8
-rw-r--r--drivers/staging/ks7010/ks_wlan_net.c22
-rw-r--r--drivers/staging/lustre/lnet/klnds/o2iblnd/o2iblnd.c4
-rw-r--r--drivers/staging/lustre/lnet/klnds/o2iblnd/o2iblnd_cb.c6
-rw-r--r--drivers/staging/lustre/lnet/klnds/socklnd/socklnd_cb.c4
-rw-r--r--drivers/staging/lustre/lnet/libcfs/debug.c2
-rw-r--r--drivers/staging/lustre/lnet/libcfs/linux/linux-tracefile.c5
-rw-r--r--drivers/staging/lustre/lnet/libcfs/tracefile.c14
-rw-r--r--drivers/staging/lustre/lnet/lnet/lib-eq.c2
-rw-r--r--drivers/staging/lustre/lnet/lnet/lib-move.c20
-rw-r--r--drivers/staging/lustre/lnet/lnet/lib-socket.c4
-rw-r--r--drivers/staging/lustre/lustre/fid/fid_request.c10
-rw-r--r--drivers/staging/lustre/lustre/fld/fld_cache.c6
-rw-r--r--drivers/staging/lustre/lustre/fld/lproc_fld.c2
-rw-r--r--drivers/staging/lustre/lustre/include/cl_object.h4
-rw-r--r--drivers/staging/lustre/lustre/include/lprocfs_status.h12
-rw-r--r--drivers/staging/lustre/lustre/include/lu_object.h4
-rw-r--r--drivers/staging/lustre/lustre/include/lustre/lustre_idl.h6
-rw-r--r--drivers/staging/lustre/lustre/include/lustre/lustre_user.h2
-rw-r--r--drivers/staging/lustre/lustre/include/lustre_fid.h2
-rw-r--r--drivers/staging/lustre/lustre/include/lustre_lib.h4
-rw-r--r--drivers/staging/lustre/lustre/ldlm/ldlm_internal.h27
-rw-r--r--drivers/staging/lustre/lustre/ldlm/ldlm_lib.c11
-rw-r--r--drivers/staging/lustre/lustre/ldlm/ldlm_request.c6
-rw-r--r--drivers/staging/lustre/lustre/ldlm/ldlm_resource.c24
-rw-r--r--drivers/staging/lustre/lustre/llite/dcache.c4
-rw-r--r--drivers/staging/lustre/lustre/llite/dir.c14
-rw-r--r--drivers/staging/lustre/lustre/llite/file.c48
-rw-r--r--drivers/staging/lustre/lustre/llite/lcommon_cl.c2
-rw-r--r--drivers/staging/lustre/lustre/llite/llite_internal.h26
-rw-r--r--drivers/staging/lustre/lustre/llite/llite_lib.c34
-rw-r--r--drivers/staging/lustre/lustre/llite/llite_mmap.c2
-rw-r--r--drivers/staging/lustre/lustre/llite/llite_nfs.c10
-rw-r--r--drivers/staging/lustre/lustre/llite/lproc_llite.c6
-rw-r--r--drivers/staging/lustre/lustre/llite/namei.c40
-rw-r--r--drivers/staging/lustre/lustre/llite/rw26.c4
-rw-r--r--drivers/staging/lustre/lustre/llite/statahead.c14
-rw-r--r--drivers/staging/lustre/lustre/llite/symlink.c4
-rw-r--r--drivers/staging/lustre/lustre/llite/vvp_dev.c6
-rw-r--r--drivers/staging/lustre/lustre/llite/vvp_io.c2
-rw-r--r--drivers/staging/lustre/lustre/llite/vvp_object.c2
-rw-r--r--drivers/staging/lustre/lustre/llite/xattr.c6
-rw-r--r--drivers/staging/lustre/lustre/llite/xattr_cache.c4
-rw-r--r--drivers/staging/lustre/lustre/lmv/lmv_fld.c2
-rw-r--r--drivers/staging/lustre/lustre/lmv/lmv_intent.c6
-rw-r--r--drivers/staging/lustre/lustre/lmv/lmv_obd.c55
-rw-r--r--drivers/staging/lustre/lustre/lov/lov_cl_internal.h2
-rw-r--r--drivers/staging/lustre/lustre/lov/lov_io.c2
-rw-r--r--drivers/staging/lustre/lustre/lov/lov_merge.c4
-rw-r--r--drivers/staging/lustre/lustre/lov/lov_object.c9
-rw-r--r--drivers/staging/lustre/lustre/lov/lov_pack.c15
-rw-r--r--drivers/staging/lustre/lustre/lov/lov_pool.c10
-rw-r--r--drivers/staging/lustre/lustre/mdc/mdc_locks.c14
-rw-r--r--drivers/staging/lustre/lustre/mdc/mdc_reint.c2
-rw-r--r--drivers/staging/lustre/lustre/mdc/mdc_request.c16
-rw-r--r--drivers/staging/lustre/lustre/mgc/mgc_request.c2
-rw-r--r--drivers/staging/lustre/lustre/obdclass/cl_lock.c2
-rw-r--r--drivers/staging/lustre/lustre/obdclass/cl_page.c2
-rw-r--r--drivers/staging/lustre/lustre/obdclass/llog_cat.c12
-rw-r--r--drivers/staging/lustre/lustre/obdclass/llog_swab.c2
-rw-r--r--drivers/staging/lustre/lustre/obdclass/lprocfs_status.c56
-rw-r--r--drivers/staging/lustre/lustre/obdclass/lu_object.c11
-rw-r--r--drivers/staging/lustre/lustre/obdecho/echo_client.c7
-rw-r--r--drivers/staging/lustre/lustre/osc/osc_cache.c17
-rw-r--r--drivers/staging/lustre/lustre/osc/osc_internal.h2
-rw-r--r--drivers/staging/lustre/lustre/osc/osc_request.c3
-rw-r--r--drivers/staging/lustre/lustre/ptlrpc/client.c4
-rw-r--r--drivers/staging/lustre/lustre/ptlrpc/import.c15
-rw-r--r--drivers/staging/lustre/lustre/ptlrpc/layout.c2
-rw-r--r--drivers/staging/lustre/lustre/ptlrpc/pack_generic.c2
-rw-r--r--drivers/staging/lustre/lustre/ptlrpc/ptlrpc_internal.h4
-rw-r--r--drivers/staging/lustre/lustre/ptlrpc/service.c2
-rw-r--r--drivers/staging/media/atomisp/i2c/Makefile2
-rw-r--r--drivers/staging/media/atomisp/i2c/imx/Makefile2
-rw-r--r--drivers/staging/media/atomisp/i2c/ov5693/Makefile2
-rw-r--r--drivers/staging/media/atomisp/pci/atomisp2/Makefile2
-rw-r--r--drivers/staging/most/aim-network/networking.c299
-rw-r--r--drivers/staging/most/aim-network/networking.h21
-rw-r--r--drivers/staging/most/hdm-dim2/Kconfig1
-rw-r--r--drivers/staging/most/hdm-dim2/dim2_hal.c17
-rw-r--r--drivers/staging/most/hdm-dim2/dim2_hdm.c18
-rw-r--r--drivers/staging/most/hdm-dim2/dim2_reg.h1
-rw-r--r--drivers/staging/most/hdm-i2c/hdm_i2c.c7
-rw-r--r--drivers/staging/most/hdm-usb/Kconfig2
-rw-r--r--drivers/staging/most/hdm-usb/hdm_usb.c15
-rw-r--r--drivers/staging/most/mostcore/mostcore.h7
-rw-r--r--drivers/staging/octeon-usb/octeon-hcd.c6
-rw-r--r--drivers/staging/octeon/ethernet-util.h2
-rw-r--r--drivers/staging/rtl8188eu/core/rtw_ap.c40
-rw-r--r--drivers/staging/rtl8188eu/core/rtw_cmd.c131
-rw-r--r--drivers/staging/rtl8188eu/core/rtw_ieee80211.c44
-rw-r--r--drivers/staging/rtl8188eu/core/rtw_mlme.c12
-rw-r--r--drivers/staging/rtl8188eu/core/rtw_recv.c83
-rw-r--r--drivers/staging/rtl8188eu/core/rtw_sta_mgt.c8
-rw-r--r--drivers/staging/rtl8188eu/hal/phy.c4
-rw-r--r--drivers/staging/rtl8188eu/hal/rtl8188e_rxdesc.c2
-rw-r--r--drivers/staging/rtl8188eu/include/ieee80211.h107
-rw-r--r--drivers/staging/rtl8188eu/os_dep/mon.c36
-rw-r--r--drivers/staging/rtl8192e/dot11d.h4
-rw-r--r--drivers/staging/rtl8192e/rtl8192e/rtl_core.c126
-rw-r--r--drivers/staging/rtl8192e/rtl8192e/rtl_core.h2
-rw-r--r--drivers/staging/rtl8192e/rtl8192e/rtl_dm.c16
-rw-r--r--drivers/staging/rtl8192e/rtl819x_HTProc.c4
-rw-r--r--drivers/staging/rtl8192e/rtllib.h54
-rw-r--r--drivers/staging/rtl8192e/rtllib_rx.c3
-rw-r--r--drivers/staging/rtl8192e/rtllib_softmac.c389
-rw-r--r--drivers/staging/rtl8192e/rtllib_wx.c2
-rw-r--r--drivers/staging/rtl8192u/ieee80211/ieee80211.h2
-rw-r--r--drivers/staging/rtl8192u/ieee80211/ieee80211_crypt.h4
-rw-r--r--drivers/staging/rtl8192u/ieee80211/ieee80211_crypt_tkip.c27
-rw-r--r--drivers/staging/rtl8192u/ieee80211/ieee80211_module.c3
-rw-r--r--drivers/staging/rtl8192u/ieee80211/rtl819x_TSProc.c171
-rw-r--r--drivers/staging/rtl8192u/r8192U.h8
-rw-r--r--drivers/staging/rtl8192u/r8192U_core.c10
-rw-r--r--drivers/staging/rtl8192u/r8192U_dm.c77
-rw-r--r--drivers/staging/rtl8712/ieee80211.c13
-rw-r--r--drivers/staging/rtl8712/os_intfs.c2
-rw-r--r--drivers/staging/rtl8712/wifi.h6
-rw-r--r--drivers/staging/rtl8723bs/core/rtw_mlme.c32
-rw-r--r--drivers/staging/rtl8723bs/hal/HalBtc8723b1Ant.c8
-rw-r--r--drivers/staging/rtl8723bs/hal/HalBtc8723b2Ant.c4
-rw-r--r--drivers/staging/rtl8723bs/hal/hal_btcoex.c2
-rw-r--r--drivers/staging/rtl8723bs/hal/hal_com.c5
-rw-r--r--drivers/staging/rtl8723bs/hal/odm.h5
-rw-r--r--drivers/staging/rtl8723bs/hal/odm_DIG.c10
-rw-r--r--drivers/staging/rtl8723bs/hal/odm_debug.h81
-rw-r--r--drivers/staging/rtl8723bs/hal/rtl8723b_hal_init.c3
-rw-r--r--drivers/staging/rtl8723bs/hal/rtl8723b_phycfg.c18
-rw-r--r--drivers/staging/rtl8723bs/hal/rtl8723b_rf6052.c12
-rw-r--r--drivers/staging/rtl8723bs/hal/rtl8723bs_xmit.c20
-rw-r--r--drivers/staging/rtl8723bs/include/ieee80211.h8
-rw-r--r--drivers/staging/rtl8723bs/include/osdep_service.h4
-rw-r--r--drivers/staging/rtl8723bs/include/osdep_service_linux.h6
-rw-r--r--drivers/staging/rtl8723bs/include/rtl8192c_rf.h23
-rw-r--r--drivers/staging/rtl8723bs/include/rtl8723b_spec.h49
-rw-r--r--drivers/staging/rtl8723bs/os_dep/ioctl_cfg80211.c3
-rw-r--r--drivers/staging/rtl8723bs/os_dep/ioctl_linux.c14
-rw-r--r--drivers/staging/rtl8723bs/os_dep/os_intfs.c2
-rw-r--r--drivers/staging/rtl8723bs/os_dep/osdep_service.c2
-rw-r--r--drivers/staging/rtl8723bs/os_dep/sdio_ops_linux.c24
-rw-r--r--drivers/staging/rtl8723bs/os_dep/wifi_regd.c46
-rw-r--r--drivers/staging/rts5208/rtsx_scsi.c2
-rw-r--r--drivers/staging/rts5208/sd.c4
-rw-r--r--drivers/staging/rts5208/xd.c2
-rw-r--r--drivers/staging/sm750fb/ddk750_chip.c7
-rw-r--r--drivers/staging/sm750fb/ddk750_dvi.c35
-rw-r--r--drivers/staging/sm750fb/ddk750_dvi.h43
-rw-r--r--drivers/staging/sm750fb/ddk750_hwi2c.c33
-rw-r--r--drivers/staging/sm750fb/ddk750_sii164.c49
-rw-r--r--drivers/staging/sm750fb/ddk750_sii164.h22
-rw-r--r--drivers/staging/sm750fb/ddk750_swi2c.c21
-rw-r--r--drivers/staging/sm750fb/ddk750_swi2c.h18
-rw-r--r--drivers/staging/sm750fb/sm750.c54
-rw-r--r--drivers/staging/sm750fb/sm750.h24
-rw-r--r--drivers/staging/sm750fb/sm750_accel.c15
-rw-r--r--drivers/staging/sm750fb/sm750_cursor.c17
-rw-r--r--drivers/staging/speakup/Makefile1
-rw-r--r--drivers/staging/speakup/main.c2
-rw-r--r--drivers/staging/speakup/serialio.c28
-rw-r--r--drivers/staging/speakup/serialio.h4
-rw-r--r--drivers/staging/speakup/speakup_acntsa.c11
-rw-r--r--drivers/staging/speakup/speakup_apollo.c13
-rw-r--r--drivers/staging/speakup/speakup_audptr.c17
-rw-r--r--drivers/staging/speakup/speakup_bns.c11
-rw-r--r--drivers/staging/speakup/speakup_decext.c28
-rw-r--r--drivers/staging/speakup/speakup_decpc.c2
-rw-r--r--drivers/staging/speakup/speakup_dectlk.c17
-rw-r--r--drivers/staging/speakup/speakup_dtlk.c2
-rw-r--r--drivers/staging/speakup/speakup_dtlk.h10
-rw-r--r--drivers/staging/speakup/speakup_dummy.c11
-rw-r--r--drivers/staging/speakup/speakup_ltlk.c16
-rw-r--r--drivers/staging/speakup/speakup_soft.c4
-rw-r--r--drivers/staging/speakup/speakup_spkout.c15
-rw-r--r--drivers/staging/speakup/speakup_txprt.c11
-rw-r--r--drivers/staging/speakup/spk_priv.h10
-rw-r--r--drivers/staging/speakup/spk_ttyio.c320
-rw-r--r--drivers/staging/speakup/spk_types.h6
-rw-r--r--drivers/staging/speakup/synth.c20
-rw-r--r--drivers/staging/typec/fusb302/fusb302.c4
-rw-r--r--drivers/staging/unisys/Documentation/overview.txt14
-rw-r--r--drivers/staging/unisys/include/channel.h60
-rw-r--r--drivers/staging/unisys/include/iochannel.h39
-rw-r--r--drivers/staging/unisys/visorbus/controlvmchannel.h56
-rw-r--r--drivers/staging/unisys/visorbus/vbuschannel.h25
-rw-r--r--drivers/staging/unisys/visorbus/visorbus_main.c125
-rw-r--r--drivers/staging/unisys/visorbus/visorbus_private.h24
-rw-r--r--drivers/staging/unisys/visorbus/visorchannel.c8
-rw-r--r--drivers/staging/unisys/visorbus/visorchipset.c226
-rw-r--r--drivers/staging/unisys/visorhba/visorhba_main.c19
-rw-r--r--drivers/staging/unisys/visorinput/ultrainputreport.h49
-rw-r--r--drivers/staging/unisys/visorinput/visorinput.c51
-rw-r--r--drivers/staging/unisys/visornic/visornic_main.c23
-rw-r--r--drivers/staging/vc04_services/interface/vchiq_arm/vchiq_2835_arm.c21
-rw-r--r--drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c14
-rw-r--r--drivers/staging/vc04_services/interface/vchiq_arm/vchiq_core.c95
-rw-r--r--drivers/staging/vme/devices/vme_pio2.h80
-rw-r--r--drivers/staging/vt6655/card.c2
-rw-r--r--drivers/staging/vt6655/card.h32
-rw-r--r--drivers/staging/vt6655/channel.h4
-rw-r--r--drivers/staging/vt6655/device_main.c19
-rw-r--r--drivers/staging/vt6655/key.c4
-rw-r--r--drivers/staging/vt6655/mac.h58
-rw-r--r--drivers/staging/vt6655/power.h16
-rw-r--r--drivers/staging/vt6655/rf.h16
-rw-r--r--drivers/staging/vt6656/card.c29
-rw-r--r--drivers/staging/vt6656/main_usb.c17
-rw-r--r--drivers/staging/vt6656/rxtx.c90
-rw-r--r--drivers/staging/wilc1000/host_interface.c90
-rw-r--r--drivers/staging/wilc1000/host_interface.h19
-rw-r--r--drivers/staging/wilc1000/linux_wlan.c37
-rw-r--r--drivers/staging/wilc1000/wilc_debugfs.c28
-rw-r--r--drivers/staging/wilc1000/wilc_wfi_cfgoperations.c36
-rw-r--r--drivers/staging/wilc1000/wilc_wfi_netdevice.h1
-rw-r--r--drivers/staging/wilc1000/wilc_wlan_if.h2
-rw-r--r--drivers/staging/wlan-ng/hfa384x.h22
-rw-r--r--drivers/staging/wlan-ng/hfa384x_usb.c18
-rw-r--r--drivers/staging/wlan-ng/prism2fw.c24
-rw-r--r--drivers/staging/wlan-ng/prism2mgmt.c4
-rw-r--r--drivers/staging/wlan-ng/prism2mib.c2
-rw-r--r--drivers/staging/wlan-ng/prism2sta.c100
-rw-r--r--drivers/staging/xgifb/vb_table.h18
-rw-r--r--drivers/target/iscsi/iscsi_target.c52
-rw-r--r--drivers/target/iscsi/iscsi_target_erl0.c6
-rw-r--r--drivers/target/iscsi/iscsi_target_erl0.h2
-rw-r--r--drivers/target/iscsi/iscsi_target_login.c4
-rw-r--r--drivers/target/iscsi/iscsi_target_nego.c194
-rw-r--r--drivers/target/target_core_iblock.c12
-rw-r--r--drivers/target/target_core_internal.h2
-rw-r--r--drivers/target/target_core_pscsi.c6
-rw-r--r--drivers/target/target_core_tmr.c16
-rw-r--r--drivers/target/target_core_transport.c32
-rw-r--r--drivers/target/target_core_user.c46
-rw-r--r--drivers/thermal/broadcom/Kconfig9
-rw-r--r--drivers/thermal/int340x_thermal/int3400_thermal.c8
-rw-r--r--drivers/thermal/max77620_thermal.c8
-rw-r--r--drivers/thermal/qoriq_thermal.c3
-rw-r--r--drivers/thermal/thermal_core.c2
-rw-r--r--drivers/thermal/ti-soc-thermal/ti-bandgap.c14
-rw-r--r--drivers/tty/Makefile3
-rw-r--r--drivers/tty/amiserial.c23
-rw-r--r--drivers/tty/cyclades.c21
-rw-r--r--drivers/tty/ehv_bytechan.c17
-rw-r--r--drivers/tty/hvc/Kconfig2
-rw-r--r--drivers/tty/hvc/hvcs.c3
-rw-r--r--drivers/tty/n_gsm.c54
-rw-r--r--drivers/tty/n_null.c80
-rw-r--r--drivers/tty/pty.c93
-rw-r--r--drivers/tty/rocket.c27
-rw-r--r--drivers/tty/serdev/core.c12
-rw-r--r--drivers/tty/serdev/serdev-ttyport.c23
-rw-r--r--drivers/tty/serial/8250/8250.h3
-rw-r--r--drivers/tty/serial/8250/8250_aspeed_vuart.c323
-rw-r--r--drivers/tty/serial/8250/8250_bcm2835aux.c2
-rw-r--r--drivers/tty/serial/8250/8250_core.c23
-rw-r--r--drivers/tty/serial/8250/8250_exar.c16
-rw-r--r--drivers/tty/serial/8250/8250_of.c10
-rw-r--r--drivers/tty/serial/8250/8250_omap.c27
-rw-r--r--drivers/tty/serial/8250/8250_port.c33
-rw-r--r--drivers/tty/serial/8250/Kconfig10
-rw-r--r--drivers/tty/serial/8250/Makefile1
-rw-r--r--drivers/tty/serial/Kconfig35
-rw-r--r--drivers/tty/serial/Makefile1
-rw-r--r--drivers/tty/serial/altera_jtaguart.c1
-rw-r--r--drivers/tty/serial/altera_uart.c1
-rw-r--r--drivers/tty/serial/amba-pl010.c31
-rw-r--r--drivers/tty/serial/atmel_serial.c164
-rw-r--r--drivers/tty/serial/efm32-uart.c11
-rw-r--r--drivers/tty/serial/fsl_lpuart.c286
-rw-r--r--drivers/tty/serial/ifx6x60.c2
-rw-r--r--drivers/tty/serial/imx.c72
-rw-r--r--drivers/tty/serial/meson_uart.c153
-rw-r--r--drivers/tty/serial/mpsc.c10
-rw-r--r--drivers/tty/serial/owl-uart.c135
-rw-r--r--drivers/tty/serial/pch_uart.c3
-rw-r--r--drivers/tty/serial/sccnxp.c15
-rw-r--r--drivers/tty/serial/serial_core.c11
-rw-r--r--drivers/tty/serial/sh-sci.c45
-rw-r--r--drivers/tty/serial/sirfsoc_uart.c2
-rw-r--r--drivers/tty/serial/xilinx_uartps.c10
-rw-r--r--drivers/tty/synclink_gt.c2
-rw-r--r--drivers/tty/tty_io.c60
-rw-r--r--drivers/tty/tty_ldisc.c46
-rw-r--r--drivers/tty/tty_port.c73
-rw-r--r--drivers/tty/vt/consolemap.c56
-rw-r--r--drivers/tty/vt/keyboard.c3
-rw-r--r--drivers/tty/vt/vt.c8
-rw-r--r--drivers/tty/vt/vt_ioctl.c8
-rw-r--r--drivers/usb/chipidea/core.c34
-rw-r--r--drivers/usb/chipidea/debug.c3
-rw-r--r--drivers/usb/chipidea/otg_fsm.c8
-rw-r--r--drivers/usb/chipidea/udc.c8
-rw-r--r--drivers/usb/chipidea/usbmisc_imx.c41
-rw-r--r--drivers/usb/class/cdc-wdm.c17
-rw-r--r--drivers/usb/core/devio.c3
-rw-r--r--drivers/usb/core/hcd.c14
-rw-r--r--drivers/usb/core/hub.c51
-rw-r--r--drivers/usb/core/ledtrig-usbport.c56
-rw-r--r--drivers/usb/core/of.c3
-rw-r--r--drivers/usb/core/quirks.c4
-rw-r--r--drivers/usb/core/usb-acpi.c26
-rw-r--r--drivers/usb/core/usb.c2
-rw-r--r--drivers/usb/dwc2/params.c2
-rw-r--r--drivers/usb/dwc3/core.c57
-rw-r--r--drivers/usb/dwc3/core.h48
-rw-r--r--drivers/usb/dwc3/debug.h247
-rw-r--r--drivers/usb/dwc3/debugfs.c9
-rw-r--r--drivers/usb/dwc3/dwc3-exynos.c13
-rw-r--r--drivers/usb/dwc3/dwc3-pci.c10
-rw-r--r--drivers/usb/dwc3/dwc3-st.c2
-rw-r--r--drivers/usb/dwc3/ep0.c8
-rw-r--r--drivers/usb/dwc3/gadget.c299
-rw-r--r--drivers/usb/dwc3/gadget.h22
-rw-r--r--drivers/usb/dwc3/trace.h28
-rw-r--r--drivers/usb/dwc3/ulpi.c12
-rw-r--r--drivers/usb/early/xhci-dbc.c1
-rw-r--r--drivers/usb/gadget/Kconfig31
-rw-r--r--drivers/usb/gadget/composite.c70
-rw-r--r--drivers/usb/gadget/configfs.c14
-rw-r--r--drivers/usb/gadget/function/Makefile5
-rw-r--r--drivers/usb/gadget/function/f_fs.c110
-rw-r--r--drivers/usb/gadget/function/f_mass_storage.c421
-rw-r--r--drivers/usb/gadget/function/f_phonet.c2
-rw-r--r--drivers/usb/gadget/function/f_uac1.c896
-rw-r--r--drivers/usb/gadget/function/f_uac1_legacy.c1021
-rw-r--r--drivers/usb/gadget/function/f_uac2.c807
-rw-r--r--drivers/usb/gadget/function/storage_common.h18
-rw-r--r--drivers/usb/gadget/function/u_audio.c662
-rw-r--r--drivers/usb/gadget/function/u_audio.h95
-rw-r--r--drivers/usb/gadget/function/u_fs.h3
-rw-r--r--drivers/usb/gadget/function/u_uac1.h87
-rw-r--r--drivers/usb/gadget/function/u_uac1_legacy.c (renamed from drivers/usb/gadget/function/u_uac1.c)7
-rw-r--r--drivers/usb/gadget/function/u_uac1_legacy.h82
-rw-r--r--drivers/usb/gadget/legacy/Kconfig15
-rw-r--r--drivers/usb/gadget/legacy/audio.c55
-rw-r--r--drivers/usb/gadget/legacy/inode.c9
-rw-r--r--drivers/usb/gadget/legacy/mass_storage.c8
-rw-r--r--drivers/usb/gadget/udc/Kconfig18
-rw-r--r--drivers/usb/gadget/udc/Makefile3
-rw-r--r--drivers/usb/gadget/udc/amd5536udc.h18
-rw-r--r--drivers/usb/gadget/udc/amd5536udc_pci.c1
-rw-r--r--drivers/usb/gadget/udc/atmel_usba_udc.c4
-rw-r--r--drivers/usb/gadget/udc/atmel_usba_udc.h27
-rw-r--r--drivers/usb/gadget/udc/bdc/bdc_core.c2
-rw-r--r--drivers/usb/gadget/udc/core.c46
-rw-r--r--drivers/usb/gadget/udc/dummy_hcd.c52
-rw-r--r--drivers/usb/gadget/udc/mv_udc_core.c9
-rw-r--r--drivers/usb/gadget/udc/net2280.c14
-rw-r--r--drivers/usb/gadget/udc/renesas_usb3.c437
-rw-r--r--drivers/usb/gadget/udc/snps_udc_core.c (renamed from drivers/usb/gadget/udc/amd5536udc.c)80
-rw-r--r--drivers/usb/gadget/udc/snps_udc_plat.c344
-rw-r--r--drivers/usb/gadget/udc/udc-xilinx.c2
-rw-r--r--drivers/usb/host/Kconfig12
-rw-r--r--drivers/usb/host/Makefile1
-rw-r--r--drivers/usb/host/ehci-exynos.c4
-rw-r--r--drivers/usb/host/ehci-sched.c2
-rw-r--r--drivers/usb/host/ehci-timer.c2
-rw-r--r--drivers/usb/host/fotg210-hcd.c2
-rw-r--r--drivers/usb/host/ohci-omap3.c211
-rw-r--r--drivers/usb/host/ohci-platform.c13
-rw-r--r--drivers/usb/host/ohci-pxa27x.c10
-rw-r--r--drivers/usb/host/uhci-hcd.c17
-rw-r--r--drivers/usb/host/uhci-hcd.h51
-rw-r--r--drivers/usb/host/uhci-platform.c22
-rw-r--r--drivers/usb/host/xhci-mem.c88
-rw-r--r--drivers/usb/host/xhci-pci.c12
-rw-r--r--drivers/usb/host/xhci-ring.c200
-rw-r--r--drivers/usb/host/xhci.c25
-rw-r--r--drivers/usb/host/xhci.h22
-rw-r--r--drivers/usb/misc/Kconfig26
-rw-r--r--drivers/usb/misc/Makefile1
-rw-r--r--drivers/usb/misc/iowarrior.c11
-rw-r--r--drivers/usb/misc/ucsi.c478
-rw-r--r--drivers/usb/misc/usbsevseg.c18
-rw-r--r--drivers/usb/mtu3/mtu3.h8
-rw-r--r--drivers/usb/mtu3/mtu3_plat.c23
-rw-r--r--drivers/usb/musb/musb_core.c3
-rw-r--r--drivers/usb/musb/musb_core.h1
-rw-r--r--drivers/usb/musb/musb_cppi41.c11
-rw-r--r--drivers/usb/musb/musb_dsps.c5
-rw-r--r--drivers/usb/musb/musb_host.c6
-rw-r--r--drivers/usb/musb/tusb6010.c21
-rw-r--r--drivers/usb/musb/tusb6010_omap.c379
-rw-r--r--drivers/usb/phy/Kconfig6
-rw-r--r--drivers/usb/phy/phy-msm-usb.c85
-rw-r--r--drivers/usb/phy/phy-qcom-8x16-usb.c20
-rw-r--r--drivers/usb/phy/phy.c57
-rw-r--r--drivers/usb/serial/cp210x.c1
-rw-r--r--drivers/usb/serial/ftdi_sio.c67
-rw-r--r--drivers/usb/serial/qcserial.c2
-rw-r--r--drivers/usb/serial/upd78f0730.c6
-rw-r--r--drivers/usb/serial/usb-serial.c243
-rw-r--r--drivers/usb/storage/ene_ub6250.c87
-rw-r--r--drivers/usb/typec/Kconfig2
-rw-r--r--drivers/usb/typec/Makefile1
-rw-r--r--drivers/usb/typec/typec.c136
-rw-r--r--drivers/usb/typec/typec_wcove.c8
-rw-r--r--drivers/usb/typec/ucsi/Kconfig39
-rw-r--r--drivers/usb/typec/ucsi/Makefile9
-rw-r--r--drivers/usb/typec/ucsi/debug.h64
-rw-r--r--drivers/usb/typec/ucsi/trace.c2
-rw-r--r--drivers/usb/typec/ucsi/trace.h143
-rw-r--r--drivers/usb/typec/ucsi/ucsi.c790
-rw-r--r--drivers/usb/typec/ucsi/ucsi.h (renamed from drivers/usb/misc/ucsi.h)194
-rw-r--r--drivers/usb/typec/ucsi/ucsi_acpi.c158
-rw-r--r--drivers/usb/usbip/stub_main.c4
-rw-r--r--drivers/usb/usbip/stub_tx.c4
-rw-r--r--drivers/usb/usbip/vhci.h36
-rw-r--r--drivers/usb/usbip/vhci_hcd.c605
-rw-r--r--drivers/usb/usbip/vhci_rx.c16
-rw-r--r--drivers/usb/usbip/vhci_sysfs.c138
-rw-r--r--drivers/uwb/i1480/dfu/phy.c1
-rw-r--r--drivers/vfio/virqfd.c2
-rw-r--r--drivers/vhost/vhost.c2
-rw-r--r--drivers/vhost/vhost.h2
-rw-r--r--drivers/video/fbdev/core/fbmon.c2
-rw-r--r--drivers/video/fbdev/smscufx.c5
-rw-r--r--drivers/video/fbdev/udlfb.c9
-rw-r--r--drivers/video/fbdev/via/viafbdev.c8
-rw-r--r--drivers/virtio/virtio_balloon.c7
-rw-r--r--drivers/xen/events/events_base.c6
-rw-r--r--drivers/xen/manage.c1
-rw-r--r--drivers/xen/mcelog.c2
-rw-r--r--drivers/xen/privcmd.c4
-rw-r--r--drivers/xen/tmem.c6
1588 files changed, 37035 insertions, 29608 deletions
diff --git a/drivers/acpi/acpi_extlog.c b/drivers/acpi/acpi_extlog.c
index 502ea4dc2080..560fdae8cc59 100644
--- a/drivers/acpi/acpi_extlog.c
+++ b/drivers/acpi/acpi_extlog.c
@@ -141,9 +141,9 @@ static int extlog_print(struct notifier_block *nb, unsigned long val,
int cpu = mce->extcpu;
struct acpi_hest_generic_status *estatus, *tmp;
struct acpi_hest_generic_data *gdata;
- const uuid_le *fru_id = &NULL_UUID_LE;
+ const guid_t *fru_id = &guid_null;
char *fru_text = "";
- uuid_le *sec_type;
+ guid_t *sec_type;
static u32 err_seq;
estatus = extlog_elog_entry_check(cpu, bank);
@@ -165,11 +165,11 @@ static int extlog_print(struct notifier_block *nb, unsigned long val,
err_seq++;
gdata = (struct acpi_hest_generic_data *)(tmp + 1);
if (gdata->validation_bits & CPER_SEC_VALID_FRU_ID)
- fru_id = (uuid_le *)gdata->fru_id;
+ fru_id = (guid_t *)gdata->fru_id;
if (gdata->validation_bits & CPER_SEC_VALID_FRU_TEXT)
fru_text = gdata->fru_text;
- sec_type = (uuid_le *)gdata->section_type;
- if (!uuid_le_cmp(*sec_type, CPER_SEC_PLATFORM_MEM)) {
+ sec_type = (guid_t *)gdata->section_type;
+ if (guid_equal(sec_type, &CPER_SEC_PLATFORM_MEM)) {
struct cper_sec_mem_err *mem = (void *)(gdata + 1);
if (gdata->error_data_length >= sizeof(*mem))
trace_extlog_mem_event(mem, err_seq, fru_id, fru_text,
@@ -182,17 +182,17 @@ out:
static bool __init extlog_get_l1addr(void)
{
- u8 uuid[16];
+ guid_t guid;
acpi_handle handle;
union acpi_object *obj;
- acpi_str_to_uuid(extlog_dsm_uuid, uuid);
-
+ if (guid_parse(extlog_dsm_uuid, &guid))
+ return false;
if (ACPI_FAILURE(acpi_get_handle(NULL, "\\_SB", &handle)))
return false;
- if (!acpi_check_dsm(handle, uuid, EXTLOG_DSM_REV, 1 << EXTLOG_FN_ADDR))
+ if (!acpi_check_dsm(handle, &guid, EXTLOG_DSM_REV, 1 << EXTLOG_FN_ADDR))
return false;
- obj = acpi_evaluate_dsm_typed(handle, uuid, EXTLOG_DSM_REV,
+ obj = acpi_evaluate_dsm_typed(handle, &guid, EXTLOG_DSM_REV,
EXTLOG_FN_ADDR, NULL, ACPI_TYPE_INTEGER);
if (!obj) {
return false;
diff --git a/drivers/acpi/acpica/tbutils.c b/drivers/acpi/acpica/tbutils.c
index 5a968a78652b..0d2e98920069 100644
--- a/drivers/acpi/acpica/tbutils.c
+++ b/drivers/acpi/acpica/tbutils.c
@@ -416,13 +416,18 @@ acpi_tb_get_table(struct acpi_table_desc *table_desc,
}
}
- table_desc->validation_count++;
- if (table_desc->validation_count == 0) {
- ACPI_ERROR((AE_INFO,
- "Table %p, Validation count is zero after increment\n",
- table_desc));
- table_desc->validation_count--;
- return_ACPI_STATUS(AE_LIMIT);
+ if (table_desc->validation_count < ACPI_MAX_TABLE_VALIDATIONS) {
+ table_desc->validation_count++;
+
+ /*
+ * Detect validation_count overflows to ensure that the warning
+ * message will only be printed once.
+ */
+ if (table_desc->validation_count >= ACPI_MAX_TABLE_VALIDATIONS) {
+ ACPI_WARNING((AE_INFO,
+ "Table %p, Validation count overflows\n",
+ table_desc));
+ }
}
*out_table = table_desc->pointer;
@@ -449,13 +454,20 @@ void acpi_tb_put_table(struct acpi_table_desc *table_desc)
ACPI_FUNCTION_TRACE(acpi_tb_put_table);
- if (table_desc->validation_count == 0) {
- ACPI_WARNING((AE_INFO,
- "Table %p, Validation count is zero before decrement\n",
- table_desc));
- return_VOID;
+ if (table_desc->validation_count < ACPI_MAX_TABLE_VALIDATIONS) {
+ table_desc->validation_count--;
+
+ /*
+ * Detect validation_count underflows to ensure that the warning
+ * message will only be printed once.
+ */
+ if (table_desc->validation_count >= ACPI_MAX_TABLE_VALIDATIONS) {
+ ACPI_WARNING((AE_INFO,
+ "Table %p, Validation count underflows\n",
+ table_desc));
+ return_VOID;
+ }
}
- table_desc->validation_count--;
if (table_desc->validation_count == 0) {
diff --git a/drivers/acpi/acpica/utresrc.c b/drivers/acpi/acpica/utresrc.c
index e0587c85bafd..ff096d9755b9 100644
--- a/drivers/acpi/acpica/utresrc.c
+++ b/drivers/acpi/acpica/utresrc.c
@@ -474,15 +474,6 @@ acpi_ut_walk_aml_resources(struct acpi_walk_state *walk_state,
return_ACPI_STATUS(AE_AML_NO_RESOURCE_END_TAG);
}
- /*
- * The end_tag opcode must be followed by a zero byte.
- * Although this byte is technically defined to be a checksum,
- * in practice, all ASL compilers set this byte to zero.
- */
- if (*(aml + 1) != 0) {
- return_ACPI_STATUS(AE_AML_NO_RESOURCE_END_TAG);
- }
-
/* Return the pointer to the end_tag if requested */
if (!user_function) {
diff --git a/drivers/acpi/apei/ghes.c b/drivers/acpi/apei/ghes.c
index d0855c09f32f..0968816f5755 100644
--- a/drivers/acpi/apei/ghes.c
+++ b/drivers/acpi/apei/ghes.c
@@ -89,14 +89,14 @@ bool ghes_disable;
module_param_named(disable, ghes_disable, bool, 0);
/*
- * All error sources notified with SCI shares one notifier function,
- * so they need to be linked and checked one by one. This is applied
- * to NMI too.
+ * All error sources notified with HED (Hardware Error Device) share a
+ * single notifier callback, so they need to be linked and checked one
+ * by one. This holds true for NMI too.
*
* RCU is used for these lists, so ghes_list_mutex is only used for
* list changing, not for traversing.
*/
-static LIST_HEAD(ghes_sci);
+static LIST_HEAD(ghes_hed);
static DEFINE_MUTEX(ghes_list_mutex);
/*
@@ -431,12 +431,13 @@ static void ghes_do_proc(struct ghes *ghes,
{
int sev, sec_sev;
struct acpi_hest_generic_data *gdata;
+ guid_t *sec_type;
sev = ghes_severity(estatus->error_severity);
apei_estatus_for_each_section(estatus, gdata) {
+ sec_type = (guid_t *)gdata->section_type;
sec_sev = ghes_severity(gdata->error_severity);
- if (!uuid_le_cmp(*(uuid_le *)gdata->section_type,
- CPER_SEC_PLATFORM_MEM)) {
+ if (guid_equal(sec_type, &CPER_SEC_PLATFORM_MEM)) {
struct cper_sec_mem_err *mem_err;
mem_err = (struct cper_sec_mem_err *)(gdata+1);
ghes_edac_report_mem_error(ghes, sev, mem_err);
@@ -445,8 +446,7 @@ static void ghes_do_proc(struct ghes *ghes,
ghes_handle_memory_failure(gdata, sev);
}
#ifdef CONFIG_ACPI_APEI_PCIEAER
- else if (!uuid_le_cmp(*(uuid_le *)gdata->section_type,
- CPER_SEC_PCIE)) {
+ else if (guid_equal(sec_type, &CPER_SEC_PCIE)) {
struct cper_sec_pcie *pcie_err;
pcie_err = (struct cper_sec_pcie *)(gdata+1);
if (sev == GHES_SEV_RECOVERABLE &&
@@ -702,14 +702,14 @@ static irqreturn_t ghes_irq_func(int irq, void *data)
return IRQ_HANDLED;
}
-static int ghes_notify_sci(struct notifier_block *this,
- unsigned long event, void *data)
+static int ghes_notify_hed(struct notifier_block *this, unsigned long event,
+ void *data)
{
struct ghes *ghes;
int ret = NOTIFY_DONE;
rcu_read_lock();
- list_for_each_entry_rcu(ghes, &ghes_sci, list) {
+ list_for_each_entry_rcu(ghes, &ghes_hed, list) {
if (!ghes_proc(ghes))
ret = NOTIFY_OK;
}
@@ -718,8 +718,8 @@ static int ghes_notify_sci(struct notifier_block *this,
return ret;
}
-static struct notifier_block ghes_notifier_sci = {
- .notifier_call = ghes_notify_sci,
+static struct notifier_block ghes_notifier_hed = {
+ .notifier_call = ghes_notify_hed,
};
#ifdef CONFIG_HAVE_ACPI_APEI_NMI
@@ -966,7 +966,10 @@ static int ghes_probe(struct platform_device *ghes_dev)
case ACPI_HEST_NOTIFY_POLLED:
case ACPI_HEST_NOTIFY_EXTERNAL:
case ACPI_HEST_NOTIFY_SCI:
+ case ACPI_HEST_NOTIFY_GSIV:
+ case ACPI_HEST_NOTIFY_GPIO:
break;
+
case ACPI_HEST_NOTIFY_NMI:
if (!IS_ENABLED(CONFIG_HAVE_ACPI_APEI_NMI)) {
pr_warn(GHES_PFX "Generic hardware error source: %d notified via NMI interrupt is not supported!\n",
@@ -1024,13 +1027,17 @@ static int ghes_probe(struct platform_device *ghes_dev)
goto err_edac_unreg;
}
break;
+
case ACPI_HEST_NOTIFY_SCI:
+ case ACPI_HEST_NOTIFY_GSIV:
+ case ACPI_HEST_NOTIFY_GPIO:
mutex_lock(&ghes_list_mutex);
- if (list_empty(&ghes_sci))
- register_acpi_hed_notifier(&ghes_notifier_sci);
- list_add_rcu(&ghes->list, &ghes_sci);
+ if (list_empty(&ghes_hed))
+ register_acpi_hed_notifier(&ghes_notifier_hed);
+ list_add_rcu(&ghes->list, &ghes_hed);
mutex_unlock(&ghes_list_mutex);
break;
+
case ACPI_HEST_NOTIFY_NMI:
ghes_nmi_add(ghes);
break;
@@ -1066,14 +1073,18 @@ static int ghes_remove(struct platform_device *ghes_dev)
case ACPI_HEST_NOTIFY_EXTERNAL:
free_irq(ghes->irq, ghes);
break;
+
case ACPI_HEST_NOTIFY_SCI:
+ case ACPI_HEST_NOTIFY_GSIV:
+ case ACPI_HEST_NOTIFY_GPIO:
mutex_lock(&ghes_list_mutex);
list_del_rcu(&ghes->list);
- if (list_empty(&ghes_sci))
- unregister_acpi_hed_notifier(&ghes_notifier_sci);
+ if (list_empty(&ghes_hed))
+ unregister_acpi_hed_notifier(&ghes_notifier_hed);
mutex_unlock(&ghes_list_mutex);
synchronize_rcu();
break;
+
case ACPI_HEST_NOTIFY_NMI:
ghes_nmi_remove(ghes);
break;
diff --git a/drivers/acpi/arm64/iort.c b/drivers/acpi/arm64/iort.c
index c5fecf97ee2f..797b28dc7b34 100644
--- a/drivers/acpi/arm64/iort.c
+++ b/drivers/acpi/arm64/iort.c
@@ -666,14 +666,6 @@ static const struct iommu_ops *iort_iommu_xlate(struct device *dev,
int ret = -ENODEV;
struct fwnode_handle *iort_fwnode;
- /*
- * If we already translated the fwspec there
- * is nothing left to do, return the iommu_ops.
- */
- ops = iort_fwspec_iommu_ops(dev->iommu_fwspec);
- if (ops)
- return ops;
-
if (node) {
iort_fwnode = iort_get_fwnode(node);
if (!iort_fwnode)
@@ -735,6 +727,14 @@ const struct iommu_ops *iort_iommu_configure(struct device *dev)
u32 streamid = 0;
int err;
+ /*
+ * If we already translated the fwspec there
+ * is nothing left to do, return the iommu_ops.
+ */
+ ops = iort_fwspec_iommu_ops(dev->iommu_fwspec);
+ if (ops)
+ return ops;
+
if (dev_is_pci(dev)) {
struct pci_bus *bus = to_pci_dev(dev)->bus;
u32 rid;
@@ -782,6 +782,12 @@ const struct iommu_ops *iort_iommu_configure(struct device *dev)
if (err)
ops = ERR_PTR(err);
+ /* Ignore all other errors apart from EPROBE_DEFER */
+ if (IS_ERR(ops) && (PTR_ERR(ops) != -EPROBE_DEFER)) {
+ dev_dbg(dev, "Adding to IOMMU failed: %ld\n", PTR_ERR(ops));
+ ops = NULL;
+ }
+
return ops;
}
diff --git a/drivers/acpi/battery.c b/drivers/acpi/battery.c
index a9a9ab3399d4..d42eeef9d928 100644
--- a/drivers/acpi/battery.c
+++ b/drivers/acpi/battery.c
@@ -782,7 +782,7 @@ static int acpi_battery_update(struct acpi_battery *battery, bool resume)
if ((battery->state & ACPI_BATTERY_STATE_CRITICAL) ||
(test_bit(ACPI_BATTERY_ALARM_PRESENT, &battery->flags) &&
(battery->capacity_now <= battery->alarm)))
- pm_wakeup_hard_event(&battery->device->dev);
+ pm_wakeup_event(&battery->device->dev, 0);
return result;
}
diff --git a/drivers/acpi/bus.c b/drivers/acpi/bus.c
index 784bda663d16..5a6fbe0fcaf2 100644
--- a/drivers/acpi/bus.c
+++ b/drivers/acpi/bus.c
@@ -196,42 +196,19 @@ static void acpi_print_osc_error(acpi_handle handle,
pr_debug("\n");
}
-acpi_status acpi_str_to_uuid(char *str, u8 *uuid)
-{
- int i;
- static int opc_map_to_uuid[16] = {6, 4, 2, 0, 11, 9, 16, 14, 19, 21,
- 24, 26, 28, 30, 32, 34};
-
- if (strlen(str) != 36)
- return AE_BAD_PARAMETER;
- for (i = 0; i < 36; i++) {
- if (i == 8 || i == 13 || i == 18 || i == 23) {
- if (str[i] != '-')
- return AE_BAD_PARAMETER;
- } else if (!isxdigit(str[i]))
- return AE_BAD_PARAMETER;
- }
- for (i = 0; i < 16; i++) {
- uuid[i] = hex_to_bin(str[opc_map_to_uuid[i]]) << 4;
- uuid[i] |= hex_to_bin(str[opc_map_to_uuid[i] + 1]);
- }
- return AE_OK;
-}
-EXPORT_SYMBOL_GPL(acpi_str_to_uuid);
-
acpi_status acpi_run_osc(acpi_handle handle, struct acpi_osc_context *context)
{
acpi_status status;
struct acpi_object_list input;
union acpi_object in_params[4];
union acpi_object *out_obj;
- u8 uuid[16];
+ guid_t guid;
u32 errors;
struct acpi_buffer output = {ACPI_ALLOCATE_BUFFER, NULL};
if (!context)
return AE_ERROR;
- if (ACPI_FAILURE(acpi_str_to_uuid(context->uuid_str, uuid)))
+ if (guid_parse(context->uuid_str, &guid))
return AE_ERROR;
context->ret.length = ACPI_ALLOCATE_BUFFER;
context->ret.pointer = NULL;
@@ -241,7 +218,7 @@ acpi_status acpi_run_osc(acpi_handle handle, struct acpi_osc_context *context)
input.pointer = in_params;
in_params[0].type = ACPI_TYPE_BUFFER;
in_params[0].buffer.length = 16;
- in_params[0].buffer.pointer = uuid;
+ in_params[0].buffer.pointer = (u8 *)&guid;
in_params[1].type = ACPI_TYPE_INTEGER;
in_params[1].integer.value = context->rev;
in_params[2].type = ACPI_TYPE_INTEGER;
diff --git a/drivers/acpi/button.c b/drivers/acpi/button.c
index b7c2a06963d6..e19f530f1083 100644
--- a/drivers/acpi/button.c
+++ b/drivers/acpi/button.c
@@ -57,6 +57,7 @@
#define ACPI_BUTTON_LID_INIT_IGNORE 0x00
#define ACPI_BUTTON_LID_INIT_OPEN 0x01
+#define ACPI_BUTTON_LID_INIT_METHOD 0x02
#define _COMPONENT ACPI_BUTTON_COMPONENT
ACPI_MODULE_NAME("button");
@@ -112,7 +113,7 @@ struct acpi_button {
static BLOCKING_NOTIFIER_HEAD(acpi_lid_notifier);
static struct acpi_device *lid_device;
-static u8 lid_init_state = ACPI_BUTTON_LID_INIT_OPEN;
+static u8 lid_init_state = ACPI_BUTTON_LID_INIT_METHOD;
static unsigned long lid_report_interval __read_mostly = 500;
module_param(lid_report_interval, ulong, 0644);
@@ -216,7 +217,7 @@ static int acpi_lid_notify_state(struct acpi_device *device, int state)
}
if (state)
- pm_wakeup_hard_event(&device->dev);
+ pm_wakeup_event(&device->dev, 0);
ret = blocking_notifier_call_chain(&acpi_lid_notifier, state, device);
if (ret == NOTIFY_DONE)
@@ -376,6 +377,9 @@ static void acpi_lid_initialize_state(struct acpi_device *device)
case ACPI_BUTTON_LID_INIT_OPEN:
(void)acpi_lid_notify_state(device, 1);
break;
+ case ACPI_BUTTON_LID_INIT_METHOD:
+ (void)acpi_lid_update_state(device);
+ break;
case ACPI_BUTTON_LID_INIT_IGNORE:
default:
break;
@@ -398,7 +402,7 @@ static void acpi_button_notify(struct acpi_device *device, u32 event)
} else {
int keycode;
- pm_wakeup_hard_event(&device->dev);
+ pm_wakeup_event(&device->dev, 0);
if (button->suspended)
break;
@@ -530,7 +534,6 @@ static int acpi_button_add(struct acpi_device *device)
lid_device = device;
}
- device_init_wakeup(&device->dev, true);
printk(KERN_INFO PREFIX "%s [%s]\n", name, acpi_device_bid(device));
return 0;
@@ -560,6 +563,9 @@ static int param_set_lid_init_state(const char *val, struct kernel_param *kp)
if (!strncmp(val, "open", sizeof("open") - 1)) {
lid_init_state = ACPI_BUTTON_LID_INIT_OPEN;
pr_info("Notify initial lid state as open\n");
+ } else if (!strncmp(val, "method", sizeof("method") - 1)) {
+ lid_init_state = ACPI_BUTTON_LID_INIT_METHOD;
+ pr_info("Notify initial lid state with _LID return value\n");
} else if (!strncmp(val, "ignore", sizeof("ignore") - 1)) {
lid_init_state = ACPI_BUTTON_LID_INIT_IGNORE;
pr_info("Do not notify initial lid state\n");
@@ -573,6 +579,8 @@ static int param_get_lid_init_state(char *buffer, struct kernel_param *kp)
switch (lid_init_state) {
case ACPI_BUTTON_LID_INIT_OPEN:
return sprintf(buffer, "open");
+ case ACPI_BUTTON_LID_INIT_METHOD:
+ return sprintf(buffer, "method");
case ACPI_BUTTON_LID_INIT_IGNORE:
return sprintf(buffer, "ignore");
default:
diff --git a/drivers/acpi/device_pm.c b/drivers/acpi/device_pm.c
index 798d5003a039..993fd31394c8 100644
--- a/drivers/acpi/device_pm.c
+++ b/drivers/acpi/device_pm.c
@@ -24,7 +24,6 @@
#include <linux/pm_qos.h>
#include <linux/pm_domain.h>
#include <linux/pm_runtime.h>
-#include <linux/suspend.h>
#include "internal.h"
@@ -400,7 +399,7 @@ static void acpi_pm_notify_handler(acpi_handle handle, u32 val, void *not_used)
mutex_lock(&acpi_pm_notifier_lock);
if (adev->wakeup.flags.notifier_present) {
- pm_wakeup_ws_event(adev->wakeup.ws, 0, true);
+ __pm_wakeup_event(adev->wakeup.ws, 0);
if (adev->wakeup.context.work.func)
queue_pm_work(&adev->wakeup.context.work);
}
diff --git a/drivers/acpi/nfit/core.c b/drivers/acpi/nfit/core.c
index 656acb5d7166..097eff0b963d 100644
--- a/drivers/acpi/nfit/core.c
+++ b/drivers/acpi/nfit/core.c
@@ -74,11 +74,11 @@ struct nfit_table_prev {
struct list_head flushes;
};
-static u8 nfit_uuid[NFIT_UUID_MAX][16];
+static guid_t nfit_uuid[NFIT_UUID_MAX];
-const u8 *to_nfit_uuid(enum nfit_uuids id)
+const guid_t *to_nfit_uuid(enum nfit_uuids id)
{
- return nfit_uuid[id];
+ return &nfit_uuid[id];
}
EXPORT_SYMBOL(to_nfit_uuid);
@@ -222,7 +222,7 @@ int acpi_nfit_ctl(struct nvdimm_bus_descriptor *nd_desc, struct nvdimm *nvdimm,
u32 offset, fw_status = 0;
acpi_handle handle;
unsigned int func;
- const u8 *uuid;
+ const guid_t *guid;
int rc, i;
func = cmd;
@@ -245,7 +245,7 @@ int acpi_nfit_ctl(struct nvdimm_bus_descriptor *nd_desc, struct nvdimm *nvdimm,
cmd_mask = nvdimm_cmd_mask(nvdimm);
dsm_mask = nfit_mem->dsm_mask;
desc = nd_cmd_dimm_desc(cmd);
- uuid = to_nfit_uuid(nfit_mem->family);
+ guid = to_nfit_uuid(nfit_mem->family);
handle = adev->handle;
} else {
struct acpi_device *adev = to_acpi_dev(acpi_desc);
@@ -254,7 +254,7 @@ int acpi_nfit_ctl(struct nvdimm_bus_descriptor *nd_desc, struct nvdimm *nvdimm,
cmd_mask = nd_desc->cmd_mask;
dsm_mask = cmd_mask;
desc = nd_cmd_bus_desc(cmd);
- uuid = to_nfit_uuid(NFIT_DEV_BUS);
+ guid = to_nfit_uuid(NFIT_DEV_BUS);
handle = adev->handle;
dimm_name = "bus";
}
@@ -289,7 +289,7 @@ int acpi_nfit_ctl(struct nvdimm_bus_descriptor *nd_desc, struct nvdimm *nvdimm,
in_buf.buffer.pointer,
min_t(u32, 256, in_buf.buffer.length), true);
- out_obj = acpi_evaluate_dsm(handle, uuid, 1, func, &in_obj);
+ out_obj = acpi_evaluate_dsm(handle, guid, 1, func, &in_obj);
if (!out_obj) {
dev_dbg(dev, "%s:%s _DSM failed cmd: %s\n", __func__, dimm_name,
cmd_name);
@@ -409,7 +409,7 @@ int nfit_spa_type(struct acpi_nfit_system_address *spa)
int i;
for (i = 0; i < NFIT_UUID_MAX; i++)
- if (memcmp(to_nfit_uuid(i), spa->range_guid, 16) == 0)
+ if (guid_equal(to_nfit_uuid(i), (guid_t *)&spa->range_guid))
return i;
return -1;
}
@@ -1415,7 +1415,7 @@ static int acpi_nfit_add_dimm(struct acpi_nfit_desc *acpi_desc,
struct acpi_device *adev, *adev_dimm;
struct device *dev = acpi_desc->dev;
unsigned long dsm_mask;
- const u8 *uuid;
+ const guid_t *guid;
int i;
int family = -1;
@@ -1444,7 +1444,7 @@ static int acpi_nfit_add_dimm(struct acpi_nfit_desc *acpi_desc,
/*
* Until standardization materializes we need to consider 4
* different command sets. Note, that checking for function0 (bit0)
- * tells us if any commands are reachable through this uuid.
+ * tells us if any commands are reachable through this GUID.
*/
for (i = NVDIMM_FAMILY_INTEL; i <= NVDIMM_FAMILY_MSFT; i++)
if (acpi_check_dsm(adev_dimm->handle, to_nfit_uuid(i), 1, 1))
@@ -1474,9 +1474,9 @@ static int acpi_nfit_add_dimm(struct acpi_nfit_desc *acpi_desc,
return 0;
}
- uuid = to_nfit_uuid(nfit_mem->family);
+ guid = to_nfit_uuid(nfit_mem->family);
for_each_set_bit(i, &dsm_mask, BITS_PER_LONG)
- if (acpi_check_dsm(adev_dimm->handle, uuid, 1, 1ULL << i))
+ if (acpi_check_dsm(adev_dimm->handle, guid, 1, 1ULL << i))
set_bit(i, &nfit_mem->dsm_mask);
return 0;
@@ -1611,7 +1611,7 @@ static int acpi_nfit_register_dimms(struct acpi_nfit_desc *acpi_desc)
static void acpi_nfit_init_dsms(struct acpi_nfit_desc *acpi_desc)
{
struct nvdimm_bus_descriptor *nd_desc = &acpi_desc->nd_desc;
- const u8 *uuid = to_nfit_uuid(NFIT_DEV_BUS);
+ const guid_t *guid = to_nfit_uuid(NFIT_DEV_BUS);
struct acpi_device *adev;
int i;
@@ -1621,7 +1621,7 @@ static void acpi_nfit_init_dsms(struct acpi_nfit_desc *acpi_desc)
return;
for (i = ND_CMD_ARS_CAP; i <= ND_CMD_CLEAR_ERROR; i++)
- if (acpi_check_dsm(adev->handle, uuid, 1, 1ULL << i))
+ if (acpi_check_dsm(adev->handle, guid, 1, 1ULL << i))
set_bit(i, &nd_desc->cmd_mask);
}
@@ -3051,19 +3051,19 @@ static __init int nfit_init(void)
BUILD_BUG_ON(sizeof(struct acpi_nfit_control_region) != 80);
BUILD_BUG_ON(sizeof(struct acpi_nfit_data_region) != 40);
- acpi_str_to_uuid(UUID_VOLATILE_MEMORY, nfit_uuid[NFIT_SPA_VOLATILE]);
- acpi_str_to_uuid(UUID_PERSISTENT_MEMORY, nfit_uuid[NFIT_SPA_PM]);
- acpi_str_to_uuid(UUID_CONTROL_REGION, nfit_uuid[NFIT_SPA_DCR]);
- acpi_str_to_uuid(UUID_DATA_REGION, nfit_uuid[NFIT_SPA_BDW]);
- acpi_str_to_uuid(UUID_VOLATILE_VIRTUAL_DISK, nfit_uuid[NFIT_SPA_VDISK]);
- acpi_str_to_uuid(UUID_VOLATILE_VIRTUAL_CD, nfit_uuid[NFIT_SPA_VCD]);
- acpi_str_to_uuid(UUID_PERSISTENT_VIRTUAL_DISK, nfit_uuid[NFIT_SPA_PDISK]);
- acpi_str_to_uuid(UUID_PERSISTENT_VIRTUAL_CD, nfit_uuid[NFIT_SPA_PCD]);
- acpi_str_to_uuid(UUID_NFIT_BUS, nfit_uuid[NFIT_DEV_BUS]);
- acpi_str_to_uuid(UUID_NFIT_DIMM, nfit_uuid[NFIT_DEV_DIMM]);
- acpi_str_to_uuid(UUID_NFIT_DIMM_N_HPE1, nfit_uuid[NFIT_DEV_DIMM_N_HPE1]);
- acpi_str_to_uuid(UUID_NFIT_DIMM_N_HPE2, nfit_uuid[NFIT_DEV_DIMM_N_HPE2]);
- acpi_str_to_uuid(UUID_NFIT_DIMM_N_MSFT, nfit_uuid[NFIT_DEV_DIMM_N_MSFT]);
+ guid_parse(UUID_VOLATILE_MEMORY, &nfit_uuid[NFIT_SPA_VOLATILE]);
+ guid_parse(UUID_PERSISTENT_MEMORY, &nfit_uuid[NFIT_SPA_PM]);
+ guid_parse(UUID_CONTROL_REGION, &nfit_uuid[NFIT_SPA_DCR]);
+ guid_parse(UUID_DATA_REGION, &nfit_uuid[NFIT_SPA_BDW]);
+ guid_parse(UUID_VOLATILE_VIRTUAL_DISK, &nfit_uuid[NFIT_SPA_VDISK]);
+ guid_parse(UUID_VOLATILE_VIRTUAL_CD, &nfit_uuid[NFIT_SPA_VCD]);
+ guid_parse(UUID_PERSISTENT_VIRTUAL_DISK, &nfit_uuid[NFIT_SPA_PDISK]);
+ guid_parse(UUID_PERSISTENT_VIRTUAL_CD, &nfit_uuid[NFIT_SPA_PCD]);
+ guid_parse(UUID_NFIT_BUS, &nfit_uuid[NFIT_DEV_BUS]);
+ guid_parse(UUID_NFIT_DIMM, &nfit_uuid[NFIT_DEV_DIMM]);
+ guid_parse(UUID_NFIT_DIMM_N_HPE1, &nfit_uuid[NFIT_DEV_DIMM_N_HPE1]);
+ guid_parse(UUID_NFIT_DIMM_N_HPE2, &nfit_uuid[NFIT_DEV_DIMM_N_HPE2]);
+ guid_parse(UUID_NFIT_DIMM_N_MSFT, &nfit_uuid[NFIT_DEV_DIMM_N_MSFT]);
nfit_wq = create_singlethread_workqueue("nfit");
if (!nfit_wq)
diff --git a/drivers/acpi/nfit/mce.c b/drivers/acpi/nfit/mce.c
index 3ba1c3472cf9..fd86bec98dea 100644
--- a/drivers/acpi/nfit/mce.c
+++ b/drivers/acpi/nfit/mce.c
@@ -26,7 +26,7 @@ static int nfit_handle_mce(struct notifier_block *nb, unsigned long val,
struct nfit_spa *nfit_spa;
/* We only care about memory errors */
- if (!(mce->status & MCACOD))
+ if (!mce_is_memory_error(mce))
return NOTIFY_DONE;
/*
diff --git a/drivers/acpi/nfit/nfit.h b/drivers/acpi/nfit/nfit.h
index 58fb7d68e04a..29bdd959517f 100644
--- a/drivers/acpi/nfit/nfit.h
+++ b/drivers/acpi/nfit/nfit.h
@@ -18,7 +18,6 @@
#include <linux/libnvdimm.h>
#include <linux/ndctl.h>
#include <linux/types.h>
-#include <linux/uuid.h>
#include <linux/acpi.h>
#include <acpi/acuuid.h>
@@ -237,7 +236,7 @@ static inline struct acpi_nfit_desc *to_acpi_desc(
return container_of(nd_desc, struct acpi_nfit_desc, nd_desc);
}
-const u8 *to_nfit_uuid(enum nfit_uuids id);
+const guid_t *to_nfit_uuid(enum nfit_uuids id);
int acpi_nfit_init(struct acpi_nfit_desc *acpi_desc, void *nfit, acpi_size sz);
void acpi_nfit_shutdown(void *data);
void __acpi_nfit_notify(struct device *dev, acpi_handle handle, u32 event);
diff --git a/drivers/acpi/pci_root.c b/drivers/acpi/pci_root.c
index 919be0aa2578..240544253ccd 100644
--- a/drivers/acpi/pci_root.c
+++ b/drivers/acpi/pci_root.c
@@ -523,7 +523,7 @@ static int acpi_pci_root_add(struct acpi_device *device,
struct acpi_pci_root *root;
acpi_handle handle = device->handle;
int no_aspm = 0;
- bool hotadd = system_state != SYSTEM_BOOTING;
+ bool hotadd = system_state == SYSTEM_RUNNING;
root = kzalloc(sizeof(struct acpi_pci_root), GFP_KERNEL);
if (!root)
diff --git a/drivers/acpi/processor_driver.c b/drivers/acpi/processor_driver.c
index 8697a82bd465..591d1dd3f04e 100644
--- a/drivers/acpi/processor_driver.c
+++ b/drivers/acpi/processor_driver.c
@@ -268,9 +268,9 @@ static int acpi_processor_start(struct device *dev)
return -ENODEV;
/* Protect against concurrent CPU hotplug operations */
- get_online_cpus();
+ cpu_hotplug_disable();
ret = __acpi_processor_start(device);
- put_online_cpus();
+ cpu_hotplug_enable();
return ret;
}
diff --git a/drivers/acpi/processor_throttling.c b/drivers/acpi/processor_throttling.c
index 3de34633f7f9..7f9aff4b8d62 100644
--- a/drivers/acpi/processor_throttling.c
+++ b/drivers/acpi/processor_throttling.c
@@ -909,6 +909,13 @@ static long __acpi_processor_get_throttling(void *data)
return pr->throttling.acpi_processor_get_throttling(pr);
}
+static int call_on_cpu(int cpu, long (*fn)(void *), void *arg, bool direct)
+{
+ if (direct || (is_percpu_thread() && cpu == smp_processor_id()))
+ return fn(arg);
+ return work_on_cpu(cpu, fn, arg);
+}
+
static int acpi_processor_get_throttling(struct acpi_processor *pr)
{
if (!pr)
@@ -926,7 +933,7 @@ static int acpi_processor_get_throttling(struct acpi_processor *pr)
if (!cpu_online(pr->id))
return -ENODEV;
- return work_on_cpu(pr->id, __acpi_processor_get_throttling, pr);
+ return call_on_cpu(pr->id, __acpi_processor_get_throttling, pr, false);
}
static int acpi_processor_get_fadt_info(struct acpi_processor *pr)
@@ -1076,13 +1083,6 @@ static long acpi_processor_throttling_fn(void *data)
arg->target_state, arg->force);
}
-static int call_on_cpu(int cpu, long (*fn)(void *), void *arg, bool direct)
-{
- if (direct)
- return fn(arg);
- return work_on_cpu(cpu, fn, arg);
-}
-
static int __acpi_processor_set_throttling(struct acpi_processor *pr,
int state, bool force, bool direct)
{
diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c
index e39ec7b7cb67..d53162997f32 100644
--- a/drivers/acpi/scan.c
+++ b/drivers/acpi/scan.c
@@ -1371,8 +1371,8 @@ int acpi_dma_configure(struct device *dev, enum dev_dma_attr attr)
iort_set_dma_mask(dev);
iommu = iort_iommu_configure(dev);
- if (IS_ERR(iommu))
- return PTR_ERR(iommu);
+ if (IS_ERR(iommu) && PTR_ERR(iommu) == -EPROBE_DEFER)
+ return -EPROBE_DEFER;
size = max(dev->coherent_dma_mask, dev->coherent_dma_mask + 1);
/*
@@ -1428,6 +1428,37 @@ static void acpi_init_coherency(struct acpi_device *adev)
adev->flags.coherent_dma = cca;
}
+static int acpi_check_spi_i2c_slave(struct acpi_resource *ares, void *data)
+{
+ bool *is_spi_i2c_slave_p = data;
+
+ if (ares->type != ACPI_RESOURCE_TYPE_SERIAL_BUS)
+ return 1;
+
+ /*
+ * devices that are connected to UART still need to be enumerated to
+ * platform bus
+ */
+ if (ares->data.common_serial_bus.type != ACPI_RESOURCE_SERIAL_TYPE_UART)
+ *is_spi_i2c_slave_p = true;
+
+ /* no need to do more checking */
+ return -1;
+}
+
+static bool acpi_is_spi_i2c_slave(struct acpi_device *device)
+{
+ struct list_head resource_list;
+ bool is_spi_i2c_slave = false;
+
+ INIT_LIST_HEAD(&resource_list);
+ acpi_dev_get_resources(device, &resource_list, acpi_check_spi_i2c_slave,
+ &is_spi_i2c_slave);
+ acpi_dev_free_resource_list(&resource_list);
+
+ return is_spi_i2c_slave;
+}
+
void acpi_init_device_object(struct acpi_device *device, acpi_handle handle,
int type, unsigned long long sta)
{
@@ -1443,6 +1474,7 @@ void acpi_init_device_object(struct acpi_device *device, acpi_handle handle,
acpi_bus_get_flags(device);
device->flags.match_driver = false;
device->flags.initialized = true;
+ device->flags.spi_i2c_slave = acpi_is_spi_i2c_slave(device);
acpi_device_clear_enumerated(device);
device_initialize(&device->dev);
dev_set_uevent_suppress(&device->dev, true);
@@ -1727,38 +1759,13 @@ static acpi_status acpi_bus_check_add(acpi_handle handle, u32 lvl_not_used,
return AE_OK;
}
-static int acpi_check_spi_i2c_slave(struct acpi_resource *ares, void *data)
-{
- bool *is_spi_i2c_slave_p = data;
-
- if (ares->type != ACPI_RESOURCE_TYPE_SERIAL_BUS)
- return 1;
-
- /*
- * devices that are connected to UART still need to be enumerated to
- * platform bus
- */
- if (ares->data.common_serial_bus.type != ACPI_RESOURCE_SERIAL_TYPE_UART)
- *is_spi_i2c_slave_p = true;
-
- /* no need to do more checking */
- return -1;
-}
-
static void acpi_default_enumeration(struct acpi_device *device)
{
- struct list_head resource_list;
- bool is_spi_i2c_slave = false;
-
/*
* Do not enumerate SPI/I2C slaves as they will be enumerated by their
* respective parents.
*/
- INIT_LIST_HEAD(&resource_list);
- acpi_dev_get_resources(device, &resource_list, acpi_check_spi_i2c_slave,
- &is_spi_i2c_slave);
- acpi_dev_free_resource_list(&resource_list);
- if (!is_spi_i2c_slave) {
+ if (!device->flags.spi_i2c_slave) {
acpi_create_platform_device(device, NULL);
acpi_device_set_enumerated(device);
} else {
@@ -1854,7 +1861,7 @@ static void acpi_bus_attach(struct acpi_device *device)
return;
device->flags.match_driver = true;
- if (ret > 0) {
+ if (ret > 0 && !device->flags.spi_i2c_slave) {
acpi_device_set_enumerated(device);
goto ok;
}
@@ -1863,10 +1870,10 @@ static void acpi_bus_attach(struct acpi_device *device)
if (ret < 0)
return;
- if (device->pnp.type.platform_id)
- acpi_default_enumeration(device);
- else
+ if (!device->pnp.type.platform_id && !device->flags.spi_i2c_slave)
acpi_device_set_enumerated(device);
+ else
+ acpi_default_enumeration(device);
ok:
list_for_each_entry(child, &device->children, node)
diff --git a/drivers/acpi/sleep.c b/drivers/acpi/sleep.c
index a6574d626340..097d630ab886 100644
--- a/drivers/acpi/sleep.c
+++ b/drivers/acpi/sleep.c
@@ -663,40 +663,14 @@ static int acpi_freeze_prepare(void)
acpi_os_wait_events_complete();
if (acpi_sci_irq_valid())
enable_irq_wake(acpi_sci_irq);
-
return 0;
}
-static void acpi_freeze_wake(void)
-{
- /*
- * If IRQD_WAKEUP_ARMED is not set for the SCI at this point, it means
- * that the SCI has triggered while suspended, so cancel the wakeup in
- * case it has not been a wakeup event (the GPEs will be checked later).
- */
- if (acpi_sci_irq_valid() &&
- !irqd_is_wakeup_armed(irq_get_irq_data(acpi_sci_irq)))
- pm_system_cancel_wakeup();
-}
-
-static void acpi_freeze_sync(void)
-{
- /*
- * Process all pending events in case there are any wakeup ones.
- *
- * The EC driver uses the system workqueue, so that one needs to be
- * flushed too.
- */
- acpi_os_wait_events_complete();
- flush_scheduled_work();
-}
-
static void acpi_freeze_restore(void)
{
acpi_disable_wakeup_devices(ACPI_STATE_S0);
if (acpi_sci_irq_valid())
disable_irq_wake(acpi_sci_irq);
-
acpi_enable_all_runtime_gpes();
}
@@ -708,8 +682,6 @@ static void acpi_freeze_end(void)
static const struct platform_freeze_ops acpi_freeze_ops = {
.begin = acpi_freeze_begin,
.prepare = acpi_freeze_prepare,
- .wake = acpi_freeze_wake,
- .sync = acpi_freeze_sync,
.restore = acpi_freeze_restore,
.end = acpi_freeze_end,
};
diff --git a/drivers/acpi/sysfs.c b/drivers/acpi/sysfs.c
index 1b5ee1e0e5a3..e414fabf7315 100644
--- a/drivers/acpi/sysfs.c
+++ b/drivers/acpi/sysfs.c
@@ -333,14 +333,17 @@ static ssize_t acpi_table_show(struct file *filp, struct kobject *kobj,
container_of(bin_attr, struct acpi_table_attr, attr);
struct acpi_table_header *table_header = NULL;
acpi_status status;
+ ssize_t rc;
status = acpi_get_table(table_attr->name, table_attr->instance,
&table_header);
if (ACPI_FAILURE(status))
return -ENODEV;
- return memory_read_from_buffer(buf, count, &offset,
- table_header, table_header->length);
+ rc = memory_read_from_buffer(buf, count, &offset, table_header,
+ table_header->length);
+ acpi_put_table(table_header);
+ return rc;
}
static int acpi_table_attr_init(struct kobject *tables_obj,
diff --git a/drivers/acpi/utils.c b/drivers/acpi/utils.c
index 27d0dcfcf47d..b9d956c916f5 100644
--- a/drivers/acpi/utils.c
+++ b/drivers/acpi/utils.c
@@ -613,19 +613,19 @@ acpi_status acpi_evaluate_lck(acpi_handle handle, int lock)
/**
* acpi_evaluate_dsm - evaluate device's _DSM method
* @handle: ACPI device handle
- * @uuid: UUID of requested functions, should be 16 bytes
+ * @guid: GUID of requested functions, should be 16 bytes
* @rev: revision number of requested function
* @func: requested function number
* @argv4: the function specific parameter
*
- * Evaluate device's _DSM method with specified UUID, revision id and
+ * Evaluate device's _DSM method with specified GUID, revision id and
* function number. Caller needs to free the returned object.
*
* Though ACPI defines the fourth parameter for _DSM should be a package,
* some old BIOSes do expect a buffer or an integer etc.
*/
union acpi_object *
-acpi_evaluate_dsm(acpi_handle handle, const u8 *uuid, u64 rev, u64 func,
+acpi_evaluate_dsm(acpi_handle handle, const guid_t *guid, u64 rev, u64 func,
union acpi_object *argv4)
{
acpi_status ret;
@@ -638,7 +638,7 @@ acpi_evaluate_dsm(acpi_handle handle, const u8 *uuid, u64 rev, u64 func,
params[0].type = ACPI_TYPE_BUFFER;
params[0].buffer.length = 16;
- params[0].buffer.pointer = (char *)uuid;
+ params[0].buffer.pointer = (u8 *)guid;
params[1].type = ACPI_TYPE_INTEGER;
params[1].integer.value = rev;
params[2].type = ACPI_TYPE_INTEGER;
@@ -666,7 +666,7 @@ EXPORT_SYMBOL(acpi_evaluate_dsm);
/**
* acpi_check_dsm - check if _DSM method supports requested functions.
* @handle: ACPI device handle
- * @uuid: UUID of requested functions, should be 16 bytes at least
+ * @guid: GUID of requested functions, should be 16 bytes at least
* @rev: revision number of requested functions
* @funcs: bitmap of requested functions
*
@@ -674,7 +674,7 @@ EXPORT_SYMBOL(acpi_evaluate_dsm);
* functions. Currently only support 64 functions at maximum, should be
* enough for now.
*/
-bool acpi_check_dsm(acpi_handle handle, const u8 *uuid, u64 rev, u64 funcs)
+bool acpi_check_dsm(acpi_handle handle, const guid_t *guid, u64 rev, u64 funcs)
{
int i;
u64 mask = 0;
@@ -683,7 +683,7 @@ bool acpi_check_dsm(acpi_handle handle, const u8 *uuid, u64 rev, u64 funcs)
if (funcs == 0)
return false;
- obj = acpi_evaluate_dsm(handle, uuid, rev, 0, NULL);
+ obj = acpi_evaluate_dsm(handle, guid, rev, 0, NULL);
if (!obj)
return false;
@@ -697,7 +697,7 @@ bool acpi_check_dsm(acpi_handle handle, const u8 *uuid, u64 rev, u64 funcs)
/*
* Bit 0 indicates whether there's support for any functions other than
- * function 0 for the specified UUID and revision.
+ * function 0 for the specified GUID and revision.
*/
if ((mask & 0x1) && (mask & funcs) == funcs)
return true;
diff --git a/drivers/ata/ahci.c b/drivers/ata/ahci.c
index 2fc52407306c..c69954023c2e 100644
--- a/drivers/ata/ahci.c
+++ b/drivers/ata/ahci.c
@@ -1364,6 +1364,40 @@ static inline void ahci_gtf_filter_workaround(struct ata_host *host)
{}
#endif
+/*
+ * On the Acer Aspire Switch Alpha 12, sometimes all SATA ports are detected
+ * as DUMMY, or detected but eventually get a "link down" and never get up
+ * again. When this happens, CAP.NP may hold a value of 0x00 or 0x01, and the
+ * port_map may hold a value of 0x00.
+ *
+ * Overriding CAP.NP to 0x02 and the port_map to 0x7 will reveal all 3 ports
+ * and can significantly reduce the occurrence of the problem.
+ *
+ * https://bugzilla.kernel.org/show_bug.cgi?id=189471
+ */
+static void acer_sa5_271_workaround(struct ahci_host_priv *hpriv,
+ struct pci_dev *pdev)
+{
+ static const struct dmi_system_id sysids[] = {
+ {
+ .ident = "Acer Switch Alpha 12",
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "Switch SA5-271")
+ },
+ },
+ { }
+ };
+
+ if (dmi_check_system(sysids)) {
+ dev_info(&pdev->dev, "enabling Acer Switch Alpha 12 workaround\n");
+ if ((hpriv->saved_cap & 0xC734FF00) == 0xC734FF00) {
+ hpriv->port_map = 0x7;
+ hpriv->cap = 0xC734FF02;
+ }
+ }
+}
+
#ifdef CONFIG_ARM64
/*
* Due to ERRATA#22536, ThunderX needs to handle HOST_IRQ_STAT differently.
@@ -1636,6 +1670,10 @@ static int ahci_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
"online status unreliable, applying workaround\n");
}
+
+ /* Acer SA5-271 workaround modifies private_data */
+ acer_sa5_271_workaround(hpriv, pdev);
+
/* CAP.NP sometimes indicate the index of the last enabled
* port, at other times, that of the last possible port, so
* determining the maximum port number requires looking at
diff --git a/drivers/ata/libahci_platform.c b/drivers/ata/libahci_platform.c
index aaa761b9081c..cd2eab6aa92e 100644
--- a/drivers/ata/libahci_platform.c
+++ b/drivers/ata/libahci_platform.c
@@ -514,8 +514,9 @@ int ahci_platform_init_host(struct platform_device *pdev,
irq = platform_get_irq(pdev, 0);
if (irq <= 0) {
- dev_err(dev, "no irq\n");
- return -EINVAL;
+ if (irq != -EPROBE_DEFER)
+ dev_err(dev, "no irq\n");
+ return irq;
}
hpriv->irq = irq;
diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c
index 2d83b8c75965..e157a0e44419 100644
--- a/drivers/ata/libata-core.c
+++ b/drivers/ata/libata-core.c
@@ -6800,7 +6800,7 @@ static int __init ata_parse_force_one(char **cur,
}
force_ent->port = simple_strtoul(id, &endp, 10);
- if (p == endp || *endp != '\0') {
+ if (id == endp || *endp != '\0') {
*reason = "invalid port/link";
return -EINVAL;
}
diff --git a/drivers/ata/sata_mv.c b/drivers/ata/sata_mv.c
index b66bcda88320..3b2246dded74 100644
--- a/drivers/ata/sata_mv.c
+++ b/drivers/ata/sata_mv.c
@@ -4067,7 +4067,6 @@ static int mv_platform_probe(struct platform_device *pdev)
struct ata_host *host;
struct mv_host_priv *hpriv;
struct resource *res;
- void __iomem *mmio;
int n_ports = 0, irq = 0;
int rc;
int port;
@@ -4086,9 +4085,8 @@ static int mv_platform_probe(struct platform_device *pdev)
* Get the register base first
*/
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- mmio = devm_ioremap_resource(&pdev->dev, res);
- if (IS_ERR(mmio))
- return PTR_ERR(mmio);
+ if (res == NULL)
+ return -EINVAL;
/* allocate host */
if (pdev->dev.of_node) {
@@ -4132,7 +4130,12 @@ static int mv_platform_probe(struct platform_device *pdev)
hpriv->board_idx = chip_soc;
host->iomap = NULL;
- hpriv->base = mmio - SATAHC0_REG_BASE;
+ hpriv->base = devm_ioremap(&pdev->dev, res->start,
+ resource_size(res));
+ if (!hpriv->base)
+ return -ENOMEM;
+
+ hpriv->base -= SATAHC0_REG_BASE;
hpriv->clk = clk_get(&pdev->dev, NULL);
if (IS_ERR(hpriv->clk))
diff --git a/drivers/ata/sata_rcar.c b/drivers/ata/sata_rcar.c
index 5d38245a7a73..b7939a2c1fab 100644
--- a/drivers/ata/sata_rcar.c
+++ b/drivers/ata/sata_rcar.c
@@ -890,7 +890,10 @@ static int sata_rcar_probe(struct platform_device *pdev)
dev_err(&pdev->dev, "failed to get access to sata clock\n");
return PTR_ERR(priv->clk);
}
- clk_prepare_enable(priv->clk);
+
+ ret = clk_prepare_enable(priv->clk);
+ if (ret)
+ return ret;
host = ata_host_alloc(&pdev->dev, 1);
if (!host) {
@@ -970,8 +973,11 @@ static int sata_rcar_resume(struct device *dev)
struct ata_host *host = dev_get_drvdata(dev);
struct sata_rcar_priv *priv = host->private_data;
void __iomem *base = priv->base;
+ int ret;
- clk_prepare_enable(priv->clk);
+ ret = clk_prepare_enable(priv->clk);
+ if (ret)
+ return ret;
/* ack and mask */
iowrite32(0, base + SATAINTSTAT_REG);
@@ -988,8 +994,11 @@ static int sata_rcar_restore(struct device *dev)
{
struct ata_host *host = dev_get_drvdata(dev);
struct sata_rcar_priv *priv = host->private_data;
+ int ret;
- clk_prepare_enable(priv->clk);
+ ret = clk_prepare_enable(priv->clk);
+ if (ret)
+ return ret;
sata_rcar_setup_port(host);
diff --git a/drivers/base/core.c b/drivers/base/core.c
index 6564339d7f59..8dde934f8d15 100644
--- a/drivers/base/core.c
+++ b/drivers/base/core.c
@@ -2881,3 +2881,19 @@ void set_secondary_fwnode(struct device *dev, struct fwnode_handle *fwnode)
else
dev->fwnode = fwnode;
}
+
+/**
+ * device_set_of_node_from_dev - reuse device-tree node of another device
+ * @dev: device whose device-tree node is being set
+ * @dev2: device whose device-tree node is being reused
+ *
+ * Takes another reference to the new device-tree node after first dropping
+ * any reference held to the old node.
+ */
+void device_set_of_node_from_dev(struct device *dev, const struct device *dev2)
+{
+ of_node_put(dev->of_node);
+ dev->of_node = of_node_get(dev2->of_node);
+ dev->of_node_reused = true;
+}
+EXPORT_SYMBOL_GPL(device_set_of_node_from_dev);
diff --git a/drivers/base/node.c b/drivers/base/node.c
index 5548f9686016..0440d95c9b5b 100644
--- a/drivers/base/node.c
+++ b/drivers/base/node.c
@@ -377,7 +377,7 @@ static int __ref get_nid_for_pfn(unsigned long pfn)
if (!pfn_valid_within(pfn))
return -1;
#ifdef CONFIG_DEFERRED_STRUCT_PAGE_INIT
- if (system_state == SYSTEM_BOOTING)
+ if (system_state < SYSTEM_RUNNING)
return early_pfn_to_nid(pfn);
#endif
page = pfn_to_page(pfn);
diff --git a/drivers/base/pinctrl.c b/drivers/base/pinctrl.c
index 5917b4b5fb99..eb929dd6ef1e 100644
--- a/drivers/base/pinctrl.c
+++ b/drivers/base/pinctrl.c
@@ -23,6 +23,9 @@ int pinctrl_bind_pins(struct device *dev)
{
int ret;
+ if (dev->of_node_reused)
+ return 0;
+
dev->pins = devm_kzalloc(dev, sizeof(*(dev->pins)), GFP_KERNEL);
if (!dev->pins)
return -ENOMEM;
diff --git a/drivers/base/platform-msi.c b/drivers/base/platform-msi.c
index d35e9a20caf7..e5473525e7b2 100644
--- a/drivers/base/platform-msi.c
+++ b/drivers/base/platform-msi.c
@@ -195,7 +195,7 @@ struct irq_domain *platform_msi_create_irq_domain(struct fwnode_handle *fwnode,
domain = msi_create_irq_domain(fwnode, info, parent);
if (domain)
- domain->bus_token = DOMAIN_BUS_PLATFORM_MSI;
+ irq_domain_update_bus_token(domain, DOMAIN_BUS_PLATFORM_MSI);
return domain;
}
diff --git a/drivers/base/power/main.c b/drivers/base/power/main.c
index e987a6f55d36..9faee1c893e5 100644
--- a/drivers/base/power/main.c
+++ b/drivers/base/power/main.c
@@ -1091,6 +1091,11 @@ static int __device_suspend_noirq(struct device *dev, pm_message_t state, bool a
if (async_error)
goto Complete;
+ if (pm_wakeup_pending()) {
+ async_error = -EBUSY;
+ goto Complete;
+ }
+
if (dev->power.syscore || dev->power.direct_complete)
goto Complete;
diff --git a/drivers/base/power/wakeup.c b/drivers/base/power/wakeup.c
index f62082fdd670..c313b600d356 100644
--- a/drivers/base/power/wakeup.c
+++ b/drivers/base/power/wakeup.c
@@ -28,8 +28,8 @@ bool events_check_enabled __read_mostly;
/* First wakeup IRQ seen by the kernel in the last cycle. */
unsigned int pm_wakeup_irq __read_mostly;
-/* If greater than 0 and the system is suspending, terminate the suspend. */
-static atomic_t pm_abort_suspend __read_mostly;
+/* If set and the system is suspending, terminate the suspend. */
+static bool pm_abort_suspend __read_mostly;
/*
* Combined counters of registered wakeup events and wakeup events in progress.
@@ -512,13 +512,12 @@ static bool wakeup_source_not_registered(struct wakeup_source *ws)
/**
* wakup_source_activate - Mark given wakeup source as active.
* @ws: Wakeup source to handle.
- * @hard: If set, abort suspends in progress and wake up from suspend-to-idle.
*
* Update the @ws' statistics and, if @ws has just been activated, notify the PM
* core of the event by incrementing the counter of of wakeup events being
* processed.
*/
-static void wakeup_source_activate(struct wakeup_source *ws, bool hard)
+static void wakeup_source_activate(struct wakeup_source *ws)
{
unsigned int cec;
@@ -526,9 +525,6 @@ static void wakeup_source_activate(struct wakeup_source *ws, bool hard)
"unregistered wakeup source\n"))
return;
- if (hard)
- pm_system_wakeup();
-
ws->active = true;
ws->active_count++;
ws->last_time = ktime_get();
@@ -554,7 +550,10 @@ static void wakeup_source_report_event(struct wakeup_source *ws, bool hard)
ws->wakeup_count++;
if (!ws->active)
- wakeup_source_activate(ws, hard);
+ wakeup_source_activate(ws);
+
+ if (hard)
+ pm_system_wakeup();
}
/**
@@ -856,26 +855,20 @@ bool pm_wakeup_pending(void)
pm_print_active_wakeup_sources();
}
- return ret || atomic_read(&pm_abort_suspend) > 0;
+ return ret || pm_abort_suspend;
}
void pm_system_wakeup(void)
{
- atomic_inc(&pm_abort_suspend);
+ pm_abort_suspend = true;
freeze_wake();
}
EXPORT_SYMBOL_GPL(pm_system_wakeup);
-void pm_system_cancel_wakeup(void)
-{
- atomic_dec(&pm_abort_suspend);
-}
-
-void pm_wakeup_clear(bool reset)
+void pm_wakeup_clear(void)
{
+ pm_abort_suspend = false;
pm_wakeup_irq = 0;
- if (reset)
- atomic_set(&pm_abort_suspend, 0);
}
void pm_system_irq_wakeup(unsigned int irq_number)
diff --git a/drivers/block/DAC960.c b/drivers/block/DAC960.c
index 26a51be77227..245a879b036e 100644
--- a/drivers/block/DAC960.c
+++ b/drivers/block/DAC960.c
@@ -3464,7 +3464,7 @@ static inline bool DAC960_ProcessCompletedRequest(DAC960_Command_T *Command,
bool SuccessfulIO)
{
struct request *Request = Command->Request;
- int Error = SuccessfulIO ? 0 : -EIO;
+ blk_status_t Error = SuccessfulIO ? BLK_STS_OK : BLK_STS_IOERR;
pci_unmap_sg(Command->Controller->PCIDevice, Command->cmd_sglist,
Command->SegmentCount, Command->DmaDirection);
diff --git a/drivers/block/amiflop.c b/drivers/block/amiflop.c
index a328f673adfe..49908c74bfcb 100644
--- a/drivers/block/amiflop.c
+++ b/drivers/block/amiflop.c
@@ -1378,7 +1378,7 @@ static void redo_fd_request(void)
struct amiga_floppy_struct *floppy;
char *data;
unsigned long flags;
- int err;
+ blk_status_t err;
next_req:
rq = set_next_request();
@@ -1392,7 +1392,7 @@ next_req:
next_segment:
/* Here someone could investigate to be more efficient */
- for (cnt = 0, err = 0; cnt < blk_rq_cur_sectors(rq); cnt++) {
+ for (cnt = 0, err = BLK_STS_OK; cnt < blk_rq_cur_sectors(rq); cnt++) {
#ifdef DEBUG
printk("fd: sector %ld + %d requested for %s\n",
blk_rq_pos(rq), cnt,
@@ -1400,7 +1400,7 @@ next_segment:
#endif
block = blk_rq_pos(rq) + cnt;
if ((int)block > floppy->blocks) {
- err = -EIO;
+ err = BLK_STS_IOERR;
break;
}
@@ -1413,7 +1413,7 @@ next_segment:
#endif
if (get_track(drive, track) == -1) {
- err = -EIO;
+ err = BLK_STS_IOERR;
break;
}
@@ -1424,7 +1424,7 @@ next_segment:
/* keep the drive spinning while writes are scheduled */
if (!fd_motor_on(drive)) {
- err = -EIO;
+ err = BLK_STS_IOERR;
break;
}
/*
diff --git a/drivers/block/aoe/aoeblk.c b/drivers/block/aoe/aoeblk.c
index 027b876370bc..6797e6c23c8a 100644
--- a/drivers/block/aoe/aoeblk.c
+++ b/drivers/block/aoe/aoeblk.c
@@ -388,6 +388,7 @@ aoeblk_gdalloc(void *vp)
d->aoemajor, d->aoeminor);
goto err_mempool;
}
+ blk_queue_bounce_limit(q, BLK_BOUNCE_HIGH);
spin_lock_irqsave(&d->lock, flags);
WARN_ON(!(d->flags & DEVFL_GD_NOW));
diff --git a/drivers/block/aoe/aoecmd.c b/drivers/block/aoe/aoecmd.c
index 3c606c09fd5a..dc43254e05a4 100644
--- a/drivers/block/aoe/aoecmd.c
+++ b/drivers/block/aoe/aoecmd.c
@@ -1070,8 +1070,8 @@ aoe_end_request(struct aoedev *d, struct request *rq, int fastfail)
d->ip.rq = NULL;
do {
bio = rq->bio;
- bok = !fastfail && !bio->bi_error;
- } while (__blk_end_request(rq, bok ? 0 : -EIO, bio->bi_iter.bi_size));
+ bok = !fastfail && !bio->bi_status;
+ } while (__blk_end_request(rq, bok ? BLK_STS_OK : BLK_STS_IOERR, bio->bi_iter.bi_size));
/* cf. http://lkml.org/lkml/2006/10/31/28 */
if (!fastfail)
@@ -1131,7 +1131,7 @@ ktiocomplete(struct frame *f)
ahout->cmdstat, ahin->cmdstat,
d->aoemajor, d->aoeminor);
noskb: if (buf)
- buf->bio->bi_error = -EIO;
+ buf->bio->bi_status = BLK_STS_IOERR;
goto out;
}
@@ -1144,7 +1144,7 @@ noskb: if (buf)
"aoe: runt data size in read from",
(long) d->aoemajor, d->aoeminor,
skb->len, n);
- buf->bio->bi_error = -EIO;
+ buf->bio->bi_status = BLK_STS_IOERR;
break;
}
if (n > f->iter.bi_size) {
@@ -1152,7 +1152,7 @@ noskb: if (buf)
"aoe: too-large data size in read from",
(long) d->aoemajor, d->aoeminor,
n, f->iter.bi_size);
- buf->bio->bi_error = -EIO;
+ buf->bio->bi_status = BLK_STS_IOERR;
break;
}
bvcpy(skb, f->buf->bio, f->iter, n);
@@ -1654,7 +1654,7 @@ aoe_failbuf(struct aoedev *d, struct buf *buf)
if (buf == NULL)
return;
buf->iter.bi_size = 0;
- buf->bio->bi_error = -EIO;
+ buf->bio->bi_status = BLK_STS_IOERR;
if (buf->nframesout == 0)
aoe_end_buf(d, buf);
}
diff --git a/drivers/block/aoe/aoedev.c b/drivers/block/aoe/aoedev.c
index ffd1947500c6..b28fefb90391 100644
--- a/drivers/block/aoe/aoedev.c
+++ b/drivers/block/aoe/aoedev.c
@@ -170,7 +170,7 @@ aoe_failip(struct aoedev *d)
if (rq == NULL)
return;
while ((bio = d->ip.nxbio)) {
- bio->bi_error = -EIO;
+ bio->bi_status = BLK_STS_IOERR;
d->ip.nxbio = bio->bi_next;
n = (unsigned long) rq->special;
rq->special = (void *) --n;
diff --git a/drivers/block/ataflop.c b/drivers/block/ataflop.c
index fa69ecd52cb5..92da886180aa 100644
--- a/drivers/block/ataflop.c
+++ b/drivers/block/ataflop.c
@@ -378,7 +378,7 @@ static DEFINE_TIMER(readtrack_timer, fd_readtrack_check, 0, 0);
static DEFINE_TIMER(timeout_timer, fd_times_out, 0, 0);
static DEFINE_TIMER(fd_timer, check_change, 0, 0);
-static void fd_end_request_cur(int err)
+static void fd_end_request_cur(blk_status_t err)
{
if (!__blk_end_request_cur(fd_request, err))
fd_request = NULL;
@@ -620,7 +620,7 @@ static void fd_error( void )
fd_request->error_count++;
if (fd_request->error_count >= MAX_ERRORS) {
printk(KERN_ERR "fd%d: too many errors.\n", SelectedDrive );
- fd_end_request_cur(-EIO);
+ fd_end_request_cur(BLK_STS_IOERR);
}
else if (fd_request->error_count == RECALIBRATE_ERRORS) {
printk(KERN_WARNING "fd%d: recalibrating\n", SelectedDrive );
@@ -739,7 +739,7 @@ static void do_fd_action( int drive )
}
else {
/* all sectors finished */
- fd_end_request_cur(0);
+ fd_end_request_cur(BLK_STS_OK);
redo_fd_request();
return;
}
@@ -1144,7 +1144,7 @@ static void fd_rwsec_done1(int status)
}
else {
/* all sectors finished */
- fd_end_request_cur(0);
+ fd_end_request_cur(BLK_STS_OK);
redo_fd_request();
}
return;
@@ -1445,7 +1445,7 @@ repeat:
if (!UD.connected) {
/* drive not connected */
printk(KERN_ERR "Unknown Device: fd%d\n", drive );
- fd_end_request_cur(-EIO);
+ fd_end_request_cur(BLK_STS_IOERR);
goto repeat;
}
@@ -1461,12 +1461,12 @@ repeat:
/* user supplied disk type */
if (--type >= NUM_DISK_MINORS) {
printk(KERN_WARNING "fd%d: invalid disk format", drive );
- fd_end_request_cur(-EIO);
+ fd_end_request_cur(BLK_STS_IOERR);
goto repeat;
}
if (minor2disktype[type].drive_types > DriveType) {
printk(KERN_WARNING "fd%d: unsupported disk format", drive );
- fd_end_request_cur(-EIO);
+ fd_end_request_cur(BLK_STS_IOERR);
goto repeat;
}
type = minor2disktype[type].index;
@@ -1476,7 +1476,7 @@ repeat:
}
if (blk_rq_pos(fd_request) + 1 > UDT->blocks) {
- fd_end_request_cur(-EIO);
+ fd_end_request_cur(BLK_STS_IOERR);
goto repeat;
}
diff --git a/drivers/block/brd.c b/drivers/block/brd.c
index 57b574f2f66a..6112e99bedf7 100644
--- a/drivers/block/brd.c
+++ b/drivers/block/brd.c
@@ -418,7 +418,6 @@ static struct brd_device *brd_alloc(int i)
blk_queue_make_request(brd->brd_queue, brd_make_request);
blk_queue_max_hw_sectors(brd->brd_queue, 1024);
- blk_queue_bounce_limit(brd->brd_queue, BLK_BOUNCE_ANY);
/* This is so fdisk will align partitions on 4k, because of
* direct_access API needing 4k alignment, returning a PFN
diff --git a/drivers/block/cciss.c b/drivers/block/cciss.c
index cd375503f7b0..02a611993bb4 100644
--- a/drivers/block/cciss.c
+++ b/drivers/block/cciss.c
@@ -1864,7 +1864,8 @@ static void cciss_softirq_done(struct request *rq)
/* set the residual count for pc requests */
if (blk_rq_is_passthrough(rq))
scsi_req(rq)->resid_len = c->err_info->ResidualCnt;
- blk_end_request_all(rq, scsi_req(rq)->result ? -EIO : 0);
+ blk_end_request_all(rq, scsi_req(rq)->result ?
+ BLK_STS_IOERR : BLK_STS_OK);
spin_lock_irqsave(&h->lock, flags);
cmd_free(h, c);
@@ -1956,6 +1957,7 @@ static int cciss_add_disk(ctlr_info_t *h, struct gendisk *disk,
disk->queue->cmd_size = sizeof(struct scsi_request);
disk->queue->request_fn = do_cciss_request;
disk->queue->queue_lock = &h->lock;
+ queue_flag_set_unlocked(QUEUE_FLAG_SCSI_PASSTHROUGH, disk->queue);
if (blk_init_allocated_queue(disk->queue) < 0)
goto cleanup_queue;
diff --git a/drivers/block/drbd/drbd_actlog.c b/drivers/block/drbd/drbd_actlog.c
index 8d7bcfa49c12..e02c45cd3c5a 100644
--- a/drivers/block/drbd/drbd_actlog.c
+++ b/drivers/block/drbd/drbd_actlog.c
@@ -178,7 +178,7 @@ static int _drbd_md_sync_page_io(struct drbd_device *device,
else
submit_bio(bio);
wait_until_done_or_force_detached(device, bdev, &device->md_io.done);
- if (!bio->bi_error)
+ if (!bio->bi_status)
err = device->md_io.error;
out:
diff --git a/drivers/block/drbd/drbd_bitmap.c b/drivers/block/drbd/drbd_bitmap.c
index a804a4107fbc..809fd245c3dc 100644
--- a/drivers/block/drbd/drbd_bitmap.c
+++ b/drivers/block/drbd/drbd_bitmap.c
@@ -959,16 +959,16 @@ static void drbd_bm_endio(struct bio *bio)
!bm_test_page_unchanged(b->bm_pages[idx]))
drbd_warn(device, "bitmap page idx %u changed during IO!\n", idx);
- if (bio->bi_error) {
+ if (bio->bi_status) {
/* ctx error will hold the completed-last non-zero error code,
* in case error codes differ. */
- ctx->error = bio->bi_error;
+ ctx->error = blk_status_to_errno(bio->bi_status);
bm_set_page_io_err(b->bm_pages[idx]);
/* Not identical to on disk version of it.
* Is BM_PAGE_IO_ERROR enough? */
if (__ratelimit(&drbd_ratelimit_state))
drbd_err(device, "IO ERROR %d on bitmap page idx %u\n",
- bio->bi_error, idx);
+ bio->bi_status, idx);
} else {
bm_clear_page_io_err(b->bm_pages[idx]);
dynamic_drbd_dbg(device, "bitmap page idx %u completed\n", idx);
diff --git a/drivers/block/drbd/drbd_int.h b/drivers/block/drbd/drbd_int.h
index d5da45bb03a6..d17b6e6393c7 100644
--- a/drivers/block/drbd/drbd_int.h
+++ b/drivers/block/drbd/drbd_int.h
@@ -1441,6 +1441,9 @@ extern struct bio_set *drbd_md_io_bio_set;
/* to allocate from that set */
extern struct bio *bio_alloc_drbd(gfp_t gfp_mask);
+/* And a bio_set for cloning */
+extern struct bio_set *drbd_io_bio_set;
+
extern struct mutex resources_mutex;
extern int conn_lowest_minor(struct drbd_connection *connection);
@@ -1627,7 +1630,7 @@ static inline void drbd_generic_make_request(struct drbd_device *device,
__release(local);
if (!bio->bi_bdev) {
drbd_err(device, "drbd_generic_make_request: bio->bi_bdev == NULL\n");
- bio->bi_error = -ENODEV;
+ bio->bi_status = BLK_STS_IOERR;
bio_endio(bio);
return;
}
diff --git a/drivers/block/drbd/drbd_main.c b/drivers/block/drbd/drbd_main.c
index 84455c365f57..5fb99e06ebe4 100644
--- a/drivers/block/drbd/drbd_main.c
+++ b/drivers/block/drbd/drbd_main.c
@@ -128,6 +128,7 @@ mempool_t *drbd_request_mempool;
mempool_t *drbd_ee_mempool;
mempool_t *drbd_md_io_page_pool;
struct bio_set *drbd_md_io_bio_set;
+struct bio_set *drbd_io_bio_set;
/* I do not use a standard mempool, because:
1) I want to hand out the pre-allocated objects first.
@@ -2098,6 +2099,8 @@ static void drbd_destroy_mempools(void)
/* D_ASSERT(device, atomic_read(&drbd_pp_vacant)==0); */
+ if (drbd_io_bio_set)
+ bioset_free(drbd_io_bio_set);
if (drbd_md_io_bio_set)
bioset_free(drbd_md_io_bio_set);
if (drbd_md_io_page_pool)
@@ -2115,6 +2118,7 @@ static void drbd_destroy_mempools(void)
if (drbd_al_ext_cache)
kmem_cache_destroy(drbd_al_ext_cache);
+ drbd_io_bio_set = NULL;
drbd_md_io_bio_set = NULL;
drbd_md_io_page_pool = NULL;
drbd_ee_mempool = NULL;
@@ -2142,6 +2146,7 @@ static int drbd_create_mempools(void)
drbd_pp_pool = NULL;
drbd_md_io_page_pool = NULL;
drbd_md_io_bio_set = NULL;
+ drbd_io_bio_set = NULL;
/* caches */
drbd_request_cache = kmem_cache_create(
@@ -2165,7 +2170,13 @@ static int drbd_create_mempools(void)
goto Enomem;
/* mempools */
- drbd_md_io_bio_set = bioset_create(DRBD_MIN_POOL_PAGES, 0);
+ drbd_io_bio_set = bioset_create(BIO_POOL_SIZE, 0, BIOSET_NEED_RESCUER);
+ if (drbd_io_bio_set == NULL)
+ goto Enomem;
+
+ drbd_md_io_bio_set = bioset_create(DRBD_MIN_POOL_PAGES, 0,
+ BIOSET_NEED_BVECS |
+ BIOSET_NEED_RESCUER);
if (drbd_md_io_bio_set == NULL)
goto Enomem;
@@ -2839,7 +2850,6 @@ enum drbd_ret_code drbd_create_device(struct drbd_config_context *adm_ctx, unsig
/* Setting the max_hw_sectors to an odd value of 8kibyte here
This triggers a max_bio_size message upon first attach or connect */
blk_queue_max_hw_sectors(q, DRBD_MAX_BIO_SIZE_SAFE >> 8);
- blk_queue_bounce_limit(q, BLK_BOUNCE_ANY);
q->queue_lock = &resource->req_lock;
device->md_io.page = alloc_page(GFP_KERNEL);
diff --git a/drivers/block/drbd/drbd_nl.c b/drivers/block/drbd/drbd_nl.c
index 02255a0d68b9..ad0fcb43e45c 100644
--- a/drivers/block/drbd/drbd_nl.c
+++ b/drivers/block/drbd/drbd_nl.c
@@ -2294,7 +2294,7 @@ _check_net_options(struct drbd_connection *connection, struct net_conf *old_net_
static enum drbd_ret_code
check_net_options(struct drbd_connection *connection, struct net_conf *new_net_conf)
{
- static enum drbd_ret_code rv;
+ enum drbd_ret_code rv;
struct drbd_peer_device *peer_device;
int i;
diff --git a/drivers/block/drbd/drbd_receiver.c b/drivers/block/drbd/drbd_receiver.c
index 1b0a2be24f39..c7e95e6380fb 100644
--- a/drivers/block/drbd/drbd_receiver.c
+++ b/drivers/block/drbd/drbd_receiver.c
@@ -1229,9 +1229,9 @@ void one_flush_endio(struct bio *bio)
struct drbd_device *device = octx->device;
struct issue_flush_context *ctx = octx->ctx;
- if (bio->bi_error) {
- ctx->error = bio->bi_error;
- drbd_info(device, "local disk FLUSH FAILED with status %d\n", bio->bi_error);
+ if (bio->bi_status) {
+ ctx->error = blk_status_to_errno(bio->bi_status);
+ drbd_info(device, "local disk FLUSH FAILED with status %d\n", bio->bi_status);
}
kfree(octx);
bio_put(bio);
diff --git a/drivers/block/drbd/drbd_req.c b/drivers/block/drbd/drbd_req.c
index 656624314f0d..f6e865b2d543 100644
--- a/drivers/block/drbd/drbd_req.c
+++ b/drivers/block/drbd/drbd_req.c
@@ -203,7 +203,7 @@ void start_new_tl_epoch(struct drbd_connection *connection)
void complete_master_bio(struct drbd_device *device,
struct bio_and_error *m)
{
- m->bio->bi_error = m->error;
+ m->bio->bi_status = errno_to_blk_status(m->error);
bio_endio(m->bio);
dec_ap_bio(device);
}
@@ -1157,7 +1157,7 @@ static void drbd_process_discard_req(struct drbd_request *req)
if (blkdev_issue_zeroout(bdev, req->i.sector, req->i.size >> 9,
GFP_NOIO, 0))
- req->private_bio->bi_error = -EIO;
+ req->private_bio->bi_status = BLK_STS_IOERR;
bio_endio(req->private_bio);
}
@@ -1225,7 +1225,7 @@ drbd_request_prepare(struct drbd_device *device, struct bio *bio, unsigned long
/* only pass the error to the upper layers.
* if user cannot handle io errors, that's not our business. */
drbd_err(device, "could not kmalloc() req\n");
- bio->bi_error = -ENOMEM;
+ bio->bi_status = BLK_STS_RESOURCE;
bio_endio(bio);
return ERR_PTR(-ENOMEM);
}
@@ -1560,7 +1560,7 @@ blk_qc_t drbd_make_request(struct request_queue *q, struct bio *bio)
struct drbd_device *device = (struct drbd_device *) q->queuedata;
unsigned long start_jif;
- blk_queue_split(q, &bio, q->bio_split);
+ blk_queue_split(q, &bio);
start_jif = jiffies;
diff --git a/drivers/block/drbd/drbd_req.h b/drivers/block/drbd/drbd_req.h
index eb49e7f2da91..9e1866ab238f 100644
--- a/drivers/block/drbd/drbd_req.h
+++ b/drivers/block/drbd/drbd_req.h
@@ -263,7 +263,7 @@ enum drbd_req_state_bits {
static inline void drbd_req_make_private_bio(struct drbd_request *req, struct bio *bio_src)
{
struct bio *bio;
- bio = bio_clone(bio_src, GFP_NOIO); /* XXX cannot fail?? */
+ bio = bio_clone_fast(bio_src, GFP_NOIO, drbd_io_bio_set);
req->private_bio = bio;
diff --git a/drivers/block/drbd/drbd_worker.c b/drivers/block/drbd/drbd_worker.c
index 1afcb4e02d8d..1d8726a8df34 100644
--- a/drivers/block/drbd/drbd_worker.c
+++ b/drivers/block/drbd/drbd_worker.c
@@ -63,7 +63,7 @@ void drbd_md_endio(struct bio *bio)
struct drbd_device *device;
device = bio->bi_private;
- device->md_io.error = bio->bi_error;
+ device->md_io.error = blk_status_to_errno(bio->bi_status);
/* We grabbed an extra reference in _drbd_md_sync_page_io() to be able
* to timeout on the lower level device, and eventually detach from it.
@@ -177,13 +177,13 @@ void drbd_peer_request_endio(struct bio *bio)
bool is_discard = bio_op(bio) == REQ_OP_WRITE_ZEROES ||
bio_op(bio) == REQ_OP_DISCARD;
- if (bio->bi_error && __ratelimit(&drbd_ratelimit_state))
+ if (bio->bi_status && __ratelimit(&drbd_ratelimit_state))
drbd_warn(device, "%s: error=%d s=%llus\n",
is_write ? (is_discard ? "discard" : "write")
- : "read", bio->bi_error,
+ : "read", bio->bi_status,
(unsigned long long)peer_req->i.sector);
- if (bio->bi_error)
+ if (bio->bi_status)
set_bit(__EE_WAS_ERROR, &peer_req->flags);
bio_put(bio); /* no need for the bio anymore */
@@ -243,16 +243,16 @@ void drbd_request_endio(struct bio *bio)
if (__ratelimit(&drbd_ratelimit_state))
drbd_emerg(device, "delayed completion of aborted local request; disk-timeout may be too aggressive\n");
- if (!bio->bi_error)
+ if (!bio->bi_status)
drbd_panic_after_delayed_completion_of_aborted_request(device);
}
/* to avoid recursion in __req_mod */
- if (unlikely(bio->bi_error)) {
+ if (unlikely(bio->bi_status)) {
switch (bio_op(bio)) {
case REQ_OP_WRITE_ZEROES:
case REQ_OP_DISCARD:
- if (bio->bi_error == -EOPNOTSUPP)
+ if (bio->bi_status == BLK_STS_NOTSUPP)
what = DISCARD_COMPLETED_NOTSUPP;
else
what = DISCARD_COMPLETED_WITH_ERROR;
@@ -272,7 +272,7 @@ void drbd_request_endio(struct bio *bio)
}
bio_put(req->private_bio);
- req->private_bio = ERR_PTR(bio->bi_error);
+ req->private_bio = ERR_PTR(blk_status_to_errno(bio->bi_status));
/* not req_mod(), we need irqsave here! */
spin_lock_irqsave(&device->resource->req_lock, flags);
diff --git a/drivers/block/floppy.c b/drivers/block/floppy.c
index 60d4c7653178..ce823647a9c4 100644
--- a/drivers/block/floppy.c
+++ b/drivers/block/floppy.c
@@ -2202,7 +2202,7 @@ static int do_format(int drive, struct format_descr *tmp_format_req)
* =============================
*/
-static void floppy_end_request(struct request *req, int error)
+static void floppy_end_request(struct request *req, blk_status_t error)
{
unsigned int nr_sectors = current_count_sectors;
unsigned int drive = (unsigned long)req->rq_disk->private_data;
@@ -2263,7 +2263,7 @@ static void request_done(int uptodate)
DRWE->last_error_generation = DRS->generation;
}
spin_lock_irqsave(q->queue_lock, flags);
- floppy_end_request(req, -EIO);
+ floppy_end_request(req, BLK_STS_IOERR);
spin_unlock_irqrestore(q->queue_lock, flags);
}
}
@@ -3780,9 +3780,9 @@ static void floppy_rb0_cb(struct bio *bio)
struct rb0_cbdata *cbdata = (struct rb0_cbdata *)bio->bi_private;
int drive = cbdata->drive;
- if (bio->bi_error) {
+ if (bio->bi_status) {
pr_info("floppy: error %d while reading block 0\n",
- bio->bi_error);
+ bio->bi_status);
set_bit(FD_OPEN_SHOULD_FAIL_BIT, &UDRS->flags);
}
complete(&cbdata->complete);
@@ -4203,6 +4203,7 @@ static int __init do_floppy_init(void)
goto out_put_disk;
}
+ blk_queue_bounce_limit(disks[drive]->queue, BLK_BOUNCE_HIGH);
blk_queue_max_hw_sectors(disks[drive]->queue, 64);
disks[drive]->major = FLOPPY_MAJOR;
disks[drive]->first_minor = TOMINOR(drive);
diff --git a/drivers/block/loop.c b/drivers/block/loop.c
index 28d932906f24..0de11444e317 100644
--- a/drivers/block/loop.c
+++ b/drivers/block/loop.c
@@ -221,7 +221,8 @@ static void __loop_update_dio(struct loop_device *lo, bool dio)
}
static int
-figure_loop_size(struct loop_device *lo, loff_t offset, loff_t sizelimit)
+figure_loop_size(struct loop_device *lo, loff_t offset, loff_t sizelimit,
+ loff_t logical_blocksize)
{
loff_t size = get_size(offset, sizelimit, lo->lo_backing_file);
sector_t x = (sector_t)size;
@@ -233,6 +234,12 @@ figure_loop_size(struct loop_device *lo, loff_t offset, loff_t sizelimit)
lo->lo_offset = offset;
if (lo->lo_sizelimit != sizelimit)
lo->lo_sizelimit = sizelimit;
+ if (lo->lo_flags & LO_FLAGS_BLOCKSIZE) {
+ lo->lo_logical_blocksize = logical_blocksize;
+ blk_queue_physical_block_size(lo->lo_queue, lo->lo_blocksize);
+ blk_queue_logical_block_size(lo->lo_queue,
+ lo->lo_logical_blocksize);
+ }
set_capacity(lo->lo_disk, x);
bd_set_size(bdev, (loff_t)get_capacity(bdev->bd_disk) << 9);
/* let user-space know about the new size */
@@ -457,7 +464,7 @@ static void lo_complete_rq(struct request *rq)
zero_fill_bio(bio);
}
- blk_mq_end_request(rq, cmd->ret < 0 ? -EIO : 0);
+ blk_mq_end_request(rq, cmd->ret < 0 ? BLK_STS_IOERR : BLK_STS_OK);
}
static void lo_rw_aio_complete(struct kiocb *iocb, long ret, long ret2)
@@ -608,6 +615,9 @@ static int loop_switch(struct loop_device *lo, struct file *file)
*/
static int loop_flush(struct loop_device *lo)
{
+ /* loop not yet configured, no running thread, nothing to flush */
+ if (lo->lo_state != Lo_bound)
+ return 0;
return loop_switch(lo, NULL);
}
@@ -810,6 +820,7 @@ static void loop_config_discard(struct loop_device *lo)
struct file *file = lo->lo_backing_file;
struct inode *inode = file->f_mapping->host;
struct request_queue *q = lo->lo_queue;
+ int lo_bits = 9;
/*
* We use punch hole to reclaim the free space used by the
@@ -829,8 +840,11 @@ static void loop_config_discard(struct loop_device *lo)
q->limits.discard_granularity = inode->i_sb->s_blocksize;
q->limits.discard_alignment = 0;
- blk_queue_max_discard_sectors(q, UINT_MAX >> 9);
- blk_queue_max_write_zeroes_sectors(q, UINT_MAX >> 9);
+ if (lo->lo_flags & LO_FLAGS_BLOCKSIZE)
+ lo_bits = blksize_bits(lo->lo_logical_blocksize);
+
+ blk_queue_max_discard_sectors(q, UINT_MAX >> lo_bits);
+ blk_queue_max_write_zeroes_sectors(q, UINT_MAX >> lo_bits);
queue_flag_set_unlocked(QUEUE_FLAG_DISCARD, q);
}
@@ -840,10 +854,16 @@ static void loop_unprepare_queue(struct loop_device *lo)
kthread_stop(lo->worker_task);
}
+static int loop_kthread_worker_fn(void *worker_ptr)
+{
+ current->flags |= PF_LESS_THROTTLE;
+ return kthread_worker_fn(worker_ptr);
+}
+
static int loop_prepare_queue(struct loop_device *lo)
{
kthread_init_worker(&lo->worker);
- lo->worker_task = kthread_run(kthread_worker_fn,
+ lo->worker_task = kthread_run(loop_kthread_worker_fn,
&lo->worker, "loop%d", lo->lo_number);
if (IS_ERR(lo->worker_task))
return -ENOMEM;
@@ -918,6 +938,7 @@ static int loop_set_fd(struct loop_device *lo, fmode_t mode,
lo->use_dio = false;
lo->lo_blocksize = lo_blocksize;
+ lo->lo_logical_blocksize = 512;
lo->lo_device = bdev;
lo->lo_flags = lo_flags;
lo->lo_backing_file = file;
@@ -1083,6 +1104,7 @@ loop_set_status(struct loop_device *lo, const struct loop_info64 *info)
int err;
struct loop_func_table *xfer;
kuid_t uid = current_uid();
+ int lo_flags = lo->lo_flags;
if (lo->lo_encrypt_key_size &&
!uid_eq(lo->lo_key_owner, uid) &&
@@ -1115,12 +1137,30 @@ loop_set_status(struct loop_device *lo, const struct loop_info64 *info)
if (err)
goto exit;
+ if (info->lo_flags & LO_FLAGS_BLOCKSIZE) {
+ if (!(lo->lo_flags & LO_FLAGS_BLOCKSIZE))
+ lo->lo_logical_blocksize = 512;
+ lo->lo_flags |= LO_FLAGS_BLOCKSIZE;
+ if (LO_INFO_BLOCKSIZE(info) != 512 &&
+ LO_INFO_BLOCKSIZE(info) != 1024 &&
+ LO_INFO_BLOCKSIZE(info) != 2048 &&
+ LO_INFO_BLOCKSIZE(info) != 4096)
+ return -EINVAL;
+ if (LO_INFO_BLOCKSIZE(info) > lo->lo_blocksize)
+ return -EINVAL;
+ }
+
if (lo->lo_offset != info->lo_offset ||
- lo->lo_sizelimit != info->lo_sizelimit)
- if (figure_loop_size(lo, info->lo_offset, info->lo_sizelimit)) {
+ lo->lo_sizelimit != info->lo_sizelimit ||
+ lo->lo_flags != lo_flags ||
+ ((lo->lo_flags & LO_FLAGS_BLOCKSIZE) &&
+ lo->lo_logical_blocksize != LO_INFO_BLOCKSIZE(info))) {
+ if (figure_loop_size(lo, info->lo_offset, info->lo_sizelimit,
+ LO_INFO_BLOCKSIZE(info))) {
err = -EFBIG;
goto exit;
}
+ }
loop_config_discard(lo);
@@ -1303,12 +1343,13 @@ loop_get_status64(struct loop_device *lo, struct loop_info64 __user *arg) {
return err;
}
-static int loop_set_capacity(struct loop_device *lo, struct block_device *bdev)
+static int loop_set_capacity(struct loop_device *lo)
{
if (unlikely(lo->lo_state != Lo_bound))
return -ENXIO;
- return figure_loop_size(lo, lo->lo_offset, lo->lo_sizelimit);
+ return figure_loop_size(lo, lo->lo_offset, lo->lo_sizelimit,
+ lo->lo_logical_blocksize);
}
static int loop_set_dio(struct loop_device *lo, unsigned long arg)
@@ -1366,7 +1407,7 @@ static int lo_ioctl(struct block_device *bdev, fmode_t mode,
case LOOP_SET_CAPACITY:
err = -EPERM;
if ((mode & FMODE_WRITE) || capable(CAP_SYS_ADMIN))
- err = loop_set_capacity(lo, bdev);
+ err = loop_set_capacity(lo);
break;
case LOOP_SET_DIRECT_IO:
err = -EPERM;
@@ -1642,7 +1683,7 @@ int loop_unregister_transfer(int number)
EXPORT_SYMBOL(loop_register_transfer);
EXPORT_SYMBOL(loop_unregister_transfer);
-static int loop_queue_rq(struct blk_mq_hw_ctx *hctx,
+static blk_status_t loop_queue_rq(struct blk_mq_hw_ctx *hctx,
const struct blk_mq_queue_data *bd)
{
struct loop_cmd *cmd = blk_mq_rq_to_pdu(bd->rq);
@@ -1651,7 +1692,7 @@ static int loop_queue_rq(struct blk_mq_hw_ctx *hctx,
blk_mq_start_request(bd->rq);
if (lo->lo_state != Lo_bound)
- return BLK_MQ_RQ_QUEUE_ERROR;
+ return BLK_STS_IOERR;
switch (req_op(cmd->rq)) {
case REQ_OP_FLUSH:
@@ -1666,7 +1707,7 @@ static int loop_queue_rq(struct blk_mq_hw_ctx *hctx,
kthread_queue_work(&lo->worker, &cmd->work);
- return BLK_MQ_RQ_QUEUE_OK;
+ return BLK_STS_OK;
}
static void loop_handle_cmd(struct loop_cmd *cmd)
diff --git a/drivers/block/loop.h b/drivers/block/loop.h
index fecd3f97ef8c..2c096b9a17b8 100644
--- a/drivers/block/loop.h
+++ b/drivers/block/loop.h
@@ -49,6 +49,7 @@ struct loop_device {
struct file * lo_backing_file;
struct block_device *lo_device;
unsigned lo_blocksize;
+ unsigned lo_logical_blocksize;
void *key_data;
gfp_t old_gfp_mask;
diff --git a/drivers/block/mtip32xx/mtip32xx.c b/drivers/block/mtip32xx/mtip32xx.c
index 3a779a4f5653..61b046f256ca 100644
--- a/drivers/block/mtip32xx/mtip32xx.c
+++ b/drivers/block/mtip32xx/mtip32xx.c
@@ -532,7 +532,7 @@ static int mtip_read_log_page(struct mtip_port *port, u8 page, u16 *buffer,
static int mtip_get_smart_attr(struct mtip_port *port, unsigned int id,
struct smart_attr *attrib);
-static void mtip_complete_command(struct mtip_cmd *cmd, int status)
+static void mtip_complete_command(struct mtip_cmd *cmd, blk_status_t status)
{
struct request *req = blk_mq_rq_from_pdu(cmd);
@@ -568,7 +568,7 @@ static void mtip_handle_tfe(struct driver_data *dd)
if (test_bit(MTIP_PF_IC_ACTIVE_BIT, &port->flags)) {
cmd = mtip_cmd_from_tag(dd, MTIP_TAG_INTERNAL);
dbg_printk(MTIP_DRV_NAME " TFE for the internal command\n");
- mtip_complete_command(cmd, -EIO);
+ mtip_complete_command(cmd, BLK_STS_IOERR);
return;
}
@@ -667,7 +667,7 @@ static void mtip_handle_tfe(struct driver_data *dd)
tag,
fail_reason != NULL ?
fail_reason : "unknown");
- mtip_complete_command(cmd, -ENODATA);
+ mtip_complete_command(cmd, BLK_STS_MEDIUM);
continue;
}
}
@@ -690,7 +690,7 @@ static void mtip_handle_tfe(struct driver_data *dd)
dev_warn(&port->dd->pdev->dev,
"retiring tag %d\n", tag);
- mtip_complete_command(cmd, -EIO);
+ mtip_complete_command(cmd, BLK_STS_IOERR);
}
}
print_tags(dd, "reissued (TFE)", tagaccum, cmd_cnt);
@@ -1063,23 +1063,10 @@ static int mtip_exec_internal_command(struct mtip_port *port,
/* insert request and run queue */
blk_execute_rq(rq->q, NULL, rq, true);
- rv = int_cmd->status;
- if (rv < 0) {
- if (rv == -ERESTARTSYS) { /* interrupted */
- dev_err(&dd->pdev->dev,
- "Internal command [%02X] was interrupted after %u ms\n",
- fis->command,
- jiffies_to_msecs(jiffies - start));
- rv = -EINTR;
- goto exec_ic_exit;
- } else if (rv == 0) /* timeout */
- dev_err(&dd->pdev->dev,
- "Internal command did not complete [%02X] within timeout of %lu ms\n",
- fis->command, timeout);
- else
- dev_err(&dd->pdev->dev,
- "Internal command [%02X] wait returned code [%d] after %lu ms - unhandled\n",
- fis->command, rv, timeout);
+ if (int_cmd->status) {
+ dev_err(&dd->pdev->dev, "Internal command [%02X] failed %d\n",
+ fis->command, int_cmd->status);
+ rv = -EIO;
if (mtip_check_surprise_removal(dd->pdev) ||
test_bit(MTIP_DDF_REMOVE_PENDING_BIT,
@@ -2753,7 +2740,7 @@ static void mtip_abort_cmd(struct request *req, void *data,
dbg_printk(MTIP_DRV_NAME " Aborting request, tag = %d\n", req->tag);
clear_bit(req->tag, dd->port->cmds_to_issue);
- cmd->status = -EIO;
+ cmd->status = BLK_STS_IOERR;
mtip_softirq_done_fn(req);
}
@@ -3597,7 +3584,7 @@ static int mtip_submit_request(struct blk_mq_hw_ctx *hctx, struct request *rq)
int err;
err = mtip_send_trim(dd, blk_rq_pos(rq), blk_rq_sectors(rq));
- blk_mq_end_request(rq, err);
+ blk_mq_end_request(rq, err ? BLK_STS_IOERR : BLK_STS_OK);
return 0;
}
@@ -3633,8 +3620,8 @@ static bool mtip_check_unal_depth(struct blk_mq_hw_ctx *hctx,
return false;
}
-static int mtip_issue_reserved_cmd(struct blk_mq_hw_ctx *hctx,
- struct request *rq)
+static blk_status_t mtip_issue_reserved_cmd(struct blk_mq_hw_ctx *hctx,
+ struct request *rq)
{
struct driver_data *dd = hctx->queue->queuedata;
struct mtip_int_cmd *icmd = rq->special;
@@ -3642,7 +3629,7 @@ static int mtip_issue_reserved_cmd(struct blk_mq_hw_ctx *hctx,
struct mtip_cmd_sg *command_sg;
if (mtip_commands_active(dd->port))
- return BLK_MQ_RQ_QUEUE_BUSY;
+ return BLK_STS_RESOURCE;
/* Populate the SG list */
cmd->command_header->opts =
@@ -3666,10 +3653,10 @@ static int mtip_issue_reserved_cmd(struct blk_mq_hw_ctx *hctx,
blk_mq_start_request(rq);
mtip_issue_non_ncq_command(dd->port, rq->tag);
- return BLK_MQ_RQ_QUEUE_OK;
+ return 0;
}
-static int mtip_queue_rq(struct blk_mq_hw_ctx *hctx,
+static blk_status_t mtip_queue_rq(struct blk_mq_hw_ctx *hctx,
const struct blk_mq_queue_data *bd)
{
struct request *rq = bd->rq;
@@ -3681,15 +3668,14 @@ static int mtip_queue_rq(struct blk_mq_hw_ctx *hctx,
return mtip_issue_reserved_cmd(hctx, rq);
if (unlikely(mtip_check_unal_depth(hctx, rq)))
- return BLK_MQ_RQ_QUEUE_BUSY;
+ return BLK_STS_RESOURCE;
blk_mq_start_request(rq);
ret = mtip_submit_request(hctx, rq);
if (likely(!ret))
- return BLK_MQ_RQ_QUEUE_OK;
-
- return BLK_MQ_RQ_QUEUE_ERROR;
+ return BLK_STS_OK;
+ return BLK_STS_IOERR;
}
static void mtip_free_cmd(struct blk_mq_tag_set *set, struct request *rq,
@@ -3730,7 +3716,7 @@ static enum blk_eh_timer_return mtip_cmd_timeout(struct request *req,
if (reserved) {
struct mtip_cmd *cmd = blk_mq_rq_to_pdu(req);
- cmd->status = -ETIME;
+ cmd->status = BLK_STS_TIMEOUT;
return BLK_EH_HANDLED;
}
@@ -3961,7 +3947,7 @@ static void mtip_no_dev_cleanup(struct request *rq, void *data, bool reserv)
{
struct mtip_cmd *cmd = blk_mq_rq_to_pdu(rq);
- cmd->status = -ENODEV;
+ cmd->status = BLK_STS_IOERR;
blk_mq_complete_request(rq);
}
diff --git a/drivers/block/mtip32xx/mtip32xx.h b/drivers/block/mtip32xx/mtip32xx.h
index 37b8e3e0bb78..e8286af50e16 100644
--- a/drivers/block/mtip32xx/mtip32xx.h
+++ b/drivers/block/mtip32xx/mtip32xx.h
@@ -342,7 +342,7 @@ struct mtip_cmd {
int retries; /* The number of retries left for this command. */
int direction; /* Data transfer direction */
- int status;
+ blk_status_t status;
};
/* Structure used to describe a port. */
diff --git a/drivers/block/nbd.c b/drivers/block/nbd.c
index 9a7bb2c29447..977ec960dd2f 100644
--- a/drivers/block/nbd.c
+++ b/drivers/block/nbd.c
@@ -116,7 +116,7 @@ struct nbd_cmd {
int index;
int cookie;
struct completion send_complete;
- int status;
+ blk_status_t status;
};
#if IS_ENABLED(CONFIG_DEBUG_FS)
@@ -286,7 +286,7 @@ static enum blk_eh_timer_return nbd_xmit_timeout(struct request *req,
struct nbd_config *config;
if (!refcount_inc_not_zero(&nbd->config_refs)) {
- cmd->status = -EIO;
+ cmd->status = BLK_STS_TIMEOUT;
return BLK_EH_HANDLED;
}
@@ -331,7 +331,7 @@ static enum blk_eh_timer_return nbd_xmit_timeout(struct request *req,
"Connection timed out\n");
}
set_bit(NBD_TIMEDOUT, &config->runtime_flags);
- cmd->status = -EIO;
+ cmd->status = BLK_STS_IOERR;
sock_shutdown(nbd);
nbd_config_put(nbd);
@@ -400,6 +400,7 @@ static int nbd_send_cmd(struct nbd_device *nbd, struct nbd_cmd *cmd, int index)
unsigned long size = blk_rq_bytes(req);
struct bio *bio;
u32 type;
+ u32 nbd_cmd_flags = 0;
u32 tag = blk_mq_unique_tag(req);
int sent = nsock->sent, skip = 0;
@@ -429,6 +430,9 @@ static int nbd_send_cmd(struct nbd_device *nbd, struct nbd_cmd *cmd, int index)
return -EIO;
}
+ if (req->cmd_flags & REQ_FUA)
+ nbd_cmd_flags |= NBD_CMD_FLAG_FUA;
+
/* We did a partial send previously, and we at least sent the whole
* request struct, so just go and send the rest of the pages in the
* request.
@@ -442,7 +446,7 @@ static int nbd_send_cmd(struct nbd_device *nbd, struct nbd_cmd *cmd, int index)
}
cmd->index = index;
cmd->cookie = nsock->cookie;
- request.type = htonl(type);
+ request.type = htonl(type | nbd_cmd_flags);
if (type != NBD_CMD_FLUSH) {
request.from = cpu_to_be64((u64)blk_rq_pos(req) << 9);
request.len = htonl(size);
@@ -465,7 +469,7 @@ static int nbd_send_cmd(struct nbd_device *nbd, struct nbd_cmd *cmd, int index)
nsock->pending = req;
nsock->sent = sent;
}
- return BLK_MQ_RQ_QUEUE_BUSY;
+ return BLK_STS_RESOURCE;
}
dev_err_ratelimited(disk_to_dev(nbd->disk),
"Send control failed (result %d)\n", result);
@@ -506,7 +510,7 @@ send_pages:
*/
nsock->pending = req;
nsock->sent = sent;
- return BLK_MQ_RQ_QUEUE_BUSY;
+ return BLK_STS_RESOURCE;
}
dev_err(disk_to_dev(nbd->disk),
"Send data failed (result %d)\n",
@@ -574,7 +578,7 @@ static struct nbd_cmd *nbd_read_stat(struct nbd_device *nbd, int index)
if (ntohl(reply.error)) {
dev_err(disk_to_dev(nbd->disk), "Other side returned error (%d)\n",
ntohl(reply.error));
- cmd->status = -EIO;
+ cmd->status = BLK_STS_IOERR;
return cmd;
}
@@ -599,7 +603,7 @@ static struct nbd_cmd *nbd_read_stat(struct nbd_device *nbd, int index)
*/
if (nbd_disconnected(config) ||
config->num_connections <= 1) {
- cmd->status = -EIO;
+ cmd->status = BLK_STS_IOERR;
return cmd;
}
return ERR_PTR(-EIO);
@@ -651,7 +655,7 @@ static void nbd_clear_req(struct request *req, void *data, bool reserved)
if (!blk_mq_request_started(req))
return;
cmd = blk_mq_rq_to_pdu(req);
- cmd->status = -EIO;
+ cmd->status = BLK_STS_IOERR;
blk_mq_complete_request(req);
}
@@ -740,7 +744,7 @@ static int nbd_handle_cmd(struct nbd_cmd *cmd, int index)
nbd_config_put(nbd);
return -EINVAL;
}
- cmd->status = 0;
+ cmd->status = BLK_STS_OK;
again:
nsock = config->socks[index];
mutex_lock(&nsock->tx_lock);
@@ -794,7 +798,7 @@ out:
return ret;
}
-static int nbd_queue_rq(struct blk_mq_hw_ctx *hctx,
+static blk_status_t nbd_queue_rq(struct blk_mq_hw_ctx *hctx,
const struct blk_mq_queue_data *bd)
{
struct nbd_cmd *cmd = blk_mq_rq_to_pdu(bd->rq);
@@ -818,13 +822,9 @@ static int nbd_queue_rq(struct blk_mq_hw_ctx *hctx,
* appropriate.
*/
ret = nbd_handle_cmd(cmd, hctx->queue_num);
- if (ret < 0)
- ret = BLK_MQ_RQ_QUEUE_ERROR;
- if (!ret)
- ret = BLK_MQ_RQ_QUEUE_OK;
complete(&cmd->send_complete);
- return ret;
+ return ret < 0 ? BLK_STS_IOERR : BLK_STS_OK;
}
static int nbd_add_socket(struct nbd_device *nbd, unsigned long arg,
@@ -910,6 +910,7 @@ static int nbd_reconnect_socket(struct nbd_device *nbd, unsigned long arg)
continue;
}
sk_set_memalloc(sock->sk);
+ sock->sk->sk_sndtimeo = nbd->tag_set.timeout;
atomic_inc(&config->recv_threads);
refcount_inc(&nbd->config_refs);
old = nsock->sock;
@@ -937,14 +938,6 @@ static int nbd_reconnect_socket(struct nbd_device *nbd, unsigned long arg)
return -ENOSPC;
}
-/* Reset all properties of an NBD device */
-static void nbd_reset(struct nbd_device *nbd)
-{
- nbd->config = NULL;
- nbd->tag_set.timeout = 0;
- queue_flag_clear_unlocked(QUEUE_FLAG_DISCARD, nbd->disk->queue);
-}
-
static void nbd_bdev_reset(struct block_device *bdev)
{
if (bdev->bd_openers > 1)
@@ -965,8 +958,12 @@ static void nbd_parse_flags(struct nbd_device *nbd)
set_disk_ro(nbd->disk, false);
if (config->flags & NBD_FLAG_SEND_TRIM)
queue_flag_set_unlocked(QUEUE_FLAG_DISCARD, nbd->disk->queue);
- if (config->flags & NBD_FLAG_SEND_FLUSH)
- blk_queue_write_cache(nbd->disk->queue, true, false);
+ if (config->flags & NBD_FLAG_SEND_FLUSH) {
+ if (config->flags & NBD_FLAG_SEND_FUA)
+ blk_queue_write_cache(nbd->disk->queue, true, true);
+ else
+ blk_queue_write_cache(nbd->disk->queue, true, false);
+ }
else
blk_queue_write_cache(nbd->disk->queue, false, false);
}
@@ -1029,7 +1026,11 @@ static void nbd_config_put(struct nbd_device *nbd)
}
kfree(config->socks);
}
- nbd_reset(nbd);
+ kfree(nbd->config);
+ nbd->config = NULL;
+
+ nbd->tag_set.timeout = 0;
+ queue_flag_clear_unlocked(QUEUE_FLAG_DISCARD, nbd->disk->queue);
mutex_unlock(&nbd->config_lock);
nbd_put(nbd);
@@ -1075,6 +1076,7 @@ static int nbd_start_device(struct nbd_device *nbd)
return -ENOMEM;
}
sk_set_memalloc(config->socks[i]->sock->sk);
+ config->socks[i]->sock->sk->sk_sndtimeo = nbd->tag_set.timeout;
atomic_inc(&config->recv_threads);
refcount_inc(&nbd->config_refs);
INIT_WORK(&args->work, recv_work);
@@ -1309,6 +1311,8 @@ static int nbd_dbg_flags_show(struct seq_file *s, void *unused)
seq_puts(s, "NBD_FLAG_READ_ONLY\n");
if (flags & NBD_FLAG_SEND_FLUSH)
seq_puts(s, "NBD_FLAG_SEND_FLUSH\n");
+ if (flags & NBD_FLAG_SEND_FUA)
+ seq_puts(s, "NBD_FLAG_SEND_FUA\n");
if (flags & NBD_FLAG_SEND_TRIM)
seq_puts(s, "NBD_FLAG_SEND_TRIM\n");
@@ -1483,7 +1487,6 @@ static int nbd_dev_add(int index)
disk->fops = &nbd_fops;
disk->private_data = nbd;
sprintf(disk->disk_name, "nbd%d", index);
- nbd_reset(nbd);
add_disk(disk);
nbd_total_devices++;
return index;
diff --git a/drivers/block/null_blk.c b/drivers/block/null_blk.c
index d946e1eeac8e..71f4422eba81 100644
--- a/drivers/block/null_blk.c
+++ b/drivers/block/null_blk.c
@@ -35,7 +35,8 @@ struct nullb {
struct request_queue *q;
struct gendisk *disk;
struct nvm_dev *ndev;
- struct blk_mq_tag_set tag_set;
+ struct blk_mq_tag_set *tag_set;
+ struct blk_mq_tag_set __tag_set;
struct hrtimer timer;
unsigned int queue_depth;
spinlock_t lock;
@@ -50,6 +51,7 @@ static struct mutex lock;
static int null_major;
static int nullb_indexes;
static struct kmem_cache *ppa_cache;
+static struct blk_mq_tag_set tag_set;
enum {
NULL_IRQ_NONE = 0,
@@ -109,7 +111,7 @@ static int bs = 512;
module_param(bs, int, S_IRUGO);
MODULE_PARM_DESC(bs, "Block size (in bytes)");
-static int nr_devices = 2;
+static int nr_devices = 1;
module_param(nr_devices, int, S_IRUGO);
MODULE_PARM_DESC(nr_devices, "Number of devices to register");
@@ -121,6 +123,10 @@ static bool blocking;
module_param(blocking, bool, S_IRUGO);
MODULE_PARM_DESC(blocking, "Register as a blocking blk-mq driver device");
+static bool shared_tags;
+module_param(shared_tags, bool, S_IRUGO);
+MODULE_PARM_DESC(shared_tags, "Share tag set between devices for blk-mq");
+
static int irqmode = NULL_IRQ_SOFTIRQ;
static int null_set_irqmode(const char *str, const struct kernel_param *kp)
@@ -229,11 +235,11 @@ static void end_cmd(struct nullb_cmd *cmd)
switch (queue_mode) {
case NULL_Q_MQ:
- blk_mq_end_request(cmd->rq, 0);
+ blk_mq_end_request(cmd->rq, BLK_STS_OK);
return;
case NULL_Q_RQ:
INIT_LIST_HEAD(&cmd->rq->queuelist);
- blk_end_request_all(cmd->rq, 0);
+ blk_end_request_all(cmd->rq, BLK_STS_OK);
break;
case NULL_Q_BIO:
bio_endio(cmd->bio);
@@ -356,7 +362,7 @@ static void null_request_fn(struct request_queue *q)
}
}
-static int null_queue_rq(struct blk_mq_hw_ctx *hctx,
+static blk_status_t null_queue_rq(struct blk_mq_hw_ctx *hctx,
const struct blk_mq_queue_data *bd)
{
struct nullb_cmd *cmd = blk_mq_rq_to_pdu(bd->rq);
@@ -373,34 +379,11 @@ static int null_queue_rq(struct blk_mq_hw_ctx *hctx,
blk_mq_start_request(bd->rq);
null_handle_cmd(cmd);
- return BLK_MQ_RQ_QUEUE_OK;
-}
-
-static void null_init_queue(struct nullb *nullb, struct nullb_queue *nq)
-{
- BUG_ON(!nullb);
- BUG_ON(!nq);
-
- init_waitqueue_head(&nq->wait);
- nq->queue_depth = nullb->queue_depth;
-}
-
-static int null_init_hctx(struct blk_mq_hw_ctx *hctx, void *data,
- unsigned int index)
-{
- struct nullb *nullb = data;
- struct nullb_queue *nq = &nullb->queues[index];
-
- hctx->driver_data = nq;
- null_init_queue(nullb, nq);
- nullb->nr_queues++;
-
- return 0;
+ return BLK_STS_OK;
}
static const struct blk_mq_ops null_mq_ops = {
.queue_rq = null_queue_rq,
- .init_hctx = null_init_hctx,
.complete = null_softirq_done_fn,
};
@@ -422,11 +405,12 @@ static void cleanup_queues(struct nullb *nullb)
#ifdef CONFIG_NVM
-static void null_lnvm_end_io(struct request *rq, int error)
+static void null_lnvm_end_io(struct request *rq, blk_status_t status)
{
struct nvm_rq *rqd = rq->end_io_data;
- rqd->error = error;
+ /* XXX: lighnvm core seems to expect NVM_RSP_* values here.. */
+ rqd->error = status ? -EIO : 0;
nvm_end_io(rqd);
blk_put_request(rq);
@@ -591,8 +575,8 @@ static void null_del_dev(struct nullb *nullb)
else
del_gendisk(nullb->disk);
blk_cleanup_queue(nullb->q);
- if (queue_mode == NULL_Q_MQ)
- blk_mq_free_tag_set(&nullb->tag_set);
+ if (queue_mode == NULL_Q_MQ && nullb->tag_set == &nullb->__tag_set)
+ blk_mq_free_tag_set(nullb->tag_set);
if (!use_lightnvm)
put_disk(nullb->disk);
cleanup_queues(nullb);
@@ -614,6 +598,32 @@ static const struct block_device_operations null_fops = {
.release = null_release,
};
+static void null_init_queue(struct nullb *nullb, struct nullb_queue *nq)
+{
+ BUG_ON(!nullb);
+ BUG_ON(!nq);
+
+ init_waitqueue_head(&nq->wait);
+ nq->queue_depth = nullb->queue_depth;
+}
+
+static void null_init_queues(struct nullb *nullb)
+{
+ struct request_queue *q = nullb->q;
+ struct blk_mq_hw_ctx *hctx;
+ struct nullb_queue *nq;
+ int i;
+
+ queue_for_each_hw_ctx(q, hctx, i) {
+ if (!hctx->nr_ctx || !hctx->tags)
+ continue;
+ nq = &nullb->queues[i];
+ hctx->driver_data = nq;
+ null_init_queue(nullb, nq);
+ nullb->nr_queues++;
+ }
+}
+
static int setup_commands(struct nullb_queue *nq)
{
struct nullb_cmd *cmd;
@@ -694,6 +704,22 @@ static int null_gendisk_register(struct nullb *nullb)
return 0;
}
+static int null_init_tag_set(struct blk_mq_tag_set *set)
+{
+ set->ops = &null_mq_ops;
+ set->nr_hw_queues = submit_queues;
+ set->queue_depth = hw_queue_depth;
+ set->numa_node = home_node;
+ set->cmd_size = sizeof(struct nullb_cmd);
+ set->flags = BLK_MQ_F_SHOULD_MERGE;
+ set->driver_data = NULL;
+
+ if (blocking)
+ set->flags |= BLK_MQ_F_BLOCKING;
+
+ return blk_mq_alloc_tag_set(set);
+}
+
static int null_add_dev(void)
{
struct nullb *nullb;
@@ -715,26 +741,23 @@ static int null_add_dev(void)
goto out_free_nullb;
if (queue_mode == NULL_Q_MQ) {
- nullb->tag_set.ops = &null_mq_ops;
- nullb->tag_set.nr_hw_queues = submit_queues;
- nullb->tag_set.queue_depth = hw_queue_depth;
- nullb->tag_set.numa_node = home_node;
- nullb->tag_set.cmd_size = sizeof(struct nullb_cmd);
- nullb->tag_set.flags = BLK_MQ_F_SHOULD_MERGE;
- nullb->tag_set.driver_data = nullb;
-
- if (blocking)
- nullb->tag_set.flags |= BLK_MQ_F_BLOCKING;
-
- rv = blk_mq_alloc_tag_set(&nullb->tag_set);
+ if (shared_tags) {
+ nullb->tag_set = &tag_set;
+ rv = 0;
+ } else {
+ nullb->tag_set = &nullb->__tag_set;
+ rv = null_init_tag_set(nullb->tag_set);
+ }
+
if (rv)
goto out_cleanup_queues;
- nullb->q = blk_mq_init_queue(&nullb->tag_set);
+ nullb->q = blk_mq_init_queue(nullb->tag_set);
if (IS_ERR(nullb->q)) {
rv = -ENOMEM;
goto out_cleanup_tags;
}
+ null_init_queues(nullb);
} else if (queue_mode == NULL_Q_BIO) {
nullb->q = blk_alloc_queue_node(GFP_KERNEL, home_node);
if (!nullb->q) {
@@ -787,8 +810,8 @@ static int null_add_dev(void)
out_cleanup_blk_queue:
blk_cleanup_queue(nullb->q);
out_cleanup_tags:
- if (queue_mode == NULL_Q_MQ)
- blk_mq_free_tag_set(&nullb->tag_set);
+ if (queue_mode == NULL_Q_MQ && nullb->tag_set == &nullb->__tag_set)
+ blk_mq_free_tag_set(nullb->tag_set);
out_cleanup_queues:
cleanup_queues(nullb);
out_free_nullb:
@@ -821,6 +844,9 @@ static int __init null_init(void)
queue_mode = NULL_Q_MQ;
}
+ if (queue_mode == NULL_Q_MQ && shared_tags)
+ null_init_tag_set(&tag_set);
+
if (queue_mode == NULL_Q_MQ && use_per_node_hctx) {
if (submit_queues < nr_online_nodes) {
pr_warn("null_blk: submit_queues param is set to %u.",
@@ -881,6 +907,9 @@ static void __exit null_exit(void)
}
mutex_unlock(&lock);
+ if (queue_mode == NULL_Q_MQ && shared_tags)
+ blk_mq_free_tag_set(&tag_set);
+
kmem_cache_destroy(ppa_cache);
}
diff --git a/drivers/block/paride/pcd.c b/drivers/block/paride/pcd.c
index b1267ef34d5a..7b8c6368beb7 100644
--- a/drivers/block/paride/pcd.c
+++ b/drivers/block/paride/pcd.c
@@ -305,6 +305,7 @@ static void pcd_init_units(void)
put_disk(disk);
continue;
}
+ blk_queue_bounce_limit(disk->queue, BLK_BOUNCE_HIGH);
cd->disk = disk;
cd->pi = &cd->pia;
cd->present = 0;
@@ -783,7 +784,7 @@ static void pcd_request(void)
ps_set_intr(do_pcd_read, NULL, 0, nice);
return;
} else {
- __blk_end_request_all(pcd_req, -EIO);
+ __blk_end_request_all(pcd_req, BLK_STS_IOERR);
pcd_req = NULL;
}
}
@@ -794,7 +795,7 @@ static void do_pcd_request(struct request_queue *q)
pcd_request();
}
-static inline void next_request(int err)
+static inline void next_request(blk_status_t err)
{
unsigned long saved_flags;
@@ -837,7 +838,7 @@ static void pcd_start(void)
if (pcd_command(pcd_current, rd_cmd, 2048, "read block")) {
pcd_bufblk = -1;
- next_request(-EIO);
+ next_request(BLK_STS_IOERR);
return;
}
@@ -871,7 +872,7 @@ static void do_pcd_read_drq(void)
return;
}
pcd_bufblk = -1;
- next_request(-EIO);
+ next_request(BLK_STS_IOERR);
return;
}
diff --git a/drivers/block/paride/pd.c b/drivers/block/paride/pd.c
index 7d2402f90978..27a44b97393a 100644
--- a/drivers/block/paride/pd.c
+++ b/drivers/block/paride/pd.c
@@ -438,7 +438,7 @@ static void run_fsm(void)
phase = NULL;
spin_lock_irqsave(&pd_lock, saved_flags);
if (!__blk_end_request_cur(pd_req,
- res == Ok ? 0 : -EIO)) {
+ res == Ok ? 0 : BLK_STS_IOERR)) {
if (!set_next_request())
stop = 1;
}
@@ -863,6 +863,7 @@ static void pd_probe_drive(struct pd_unit *disk)
return;
}
blk_queue_max_hw_sectors(p->queue, cluster);
+ blk_queue_bounce_limit(p->queue, BLK_BOUNCE_HIGH);
if (disk->drive == -1) {
for (disk->drive = 0; disk->drive <= 1; disk->drive++)
diff --git a/drivers/block/paride/pf.c b/drivers/block/paride/pf.c
index f24ca7315ddc..eef7a91f667d 100644
--- a/drivers/block/paride/pf.c
+++ b/drivers/block/paride/pf.c
@@ -293,6 +293,7 @@ static void __init pf_init_units(void)
return;
}
blk_queue_max_segments(disk->queue, cluster);
+ blk_queue_bounce_limit(disk->queue, BLK_BOUNCE_HIGH);
pf->disk = disk;
pf->pi = &pf->pia;
pf->media_status = PF_NM;
@@ -801,7 +802,7 @@ static int set_next_request(void)
return pf_req != NULL;
}
-static void pf_end_request(int err)
+static void pf_end_request(blk_status_t err)
{
if (pf_req && !__blk_end_request_cur(pf_req, err))
pf_req = NULL;
@@ -821,7 +822,7 @@ repeat:
pf_count = blk_rq_cur_sectors(pf_req);
if (pf_block + pf_count > get_capacity(pf_req->rq_disk)) {
- pf_end_request(-EIO);
+ pf_end_request(BLK_STS_IOERR);
goto repeat;
}
@@ -836,7 +837,7 @@ repeat:
pi_do_claimed(pf_current->pi, do_pf_write);
else {
pf_busy = 0;
- pf_end_request(-EIO);
+ pf_end_request(BLK_STS_IOERR);
goto repeat;
}
}
@@ -868,7 +869,7 @@ static int pf_next_buf(void)
return 0;
}
-static inline void next_request(int err)
+static inline void next_request(blk_status_t err)
{
unsigned long saved_flags;
@@ -896,7 +897,7 @@ static void do_pf_read_start(void)
pi_do_claimed(pf_current->pi, do_pf_read_start);
return;
}
- next_request(-EIO);
+ next_request(BLK_STS_IOERR);
return;
}
pf_mask = STAT_DRQ;
@@ -915,7 +916,7 @@ static void do_pf_read_drq(void)
pi_do_claimed(pf_current->pi, do_pf_read_start);
return;
}
- next_request(-EIO);
+ next_request(BLK_STS_IOERR);
return;
}
pi_read_block(pf_current->pi, pf_buf, 512);
@@ -942,7 +943,7 @@ static void do_pf_write_start(void)
pi_do_claimed(pf_current->pi, do_pf_write_start);
return;
}
- next_request(-EIO);
+ next_request(BLK_STS_IOERR);
return;
}
@@ -955,7 +956,7 @@ static void do_pf_write_start(void)
pi_do_claimed(pf_current->pi, do_pf_write_start);
return;
}
- next_request(-EIO);
+ next_request(BLK_STS_IOERR);
return;
}
pi_write_block(pf_current->pi, pf_buf, 512);
@@ -975,7 +976,7 @@ static void do_pf_write_done(void)
pi_do_claimed(pf_current->pi, do_pf_write_start);
return;
}
- next_request(-EIO);
+ next_request(BLK_STS_IOERR);
return;
}
pi_disconnect(pf_current->pi);
diff --git a/drivers/block/pktcdvd.c b/drivers/block/pktcdvd.c
index 98939ee97476..6b8b097abbb9 100644
--- a/drivers/block/pktcdvd.c
+++ b/drivers/block/pktcdvd.c
@@ -98,6 +98,7 @@ static int write_congestion_on = PKT_WRITE_CONGESTION_ON;
static int write_congestion_off = PKT_WRITE_CONGESTION_OFF;
static struct mutex ctl_mutex; /* Serialize open/close/setup/teardown */
static mempool_t *psd_pool;
+static struct bio_set *pkt_bio_set;
static struct class *class_pktcdvd = NULL; /* /sys/class/pktcdvd */
static struct dentry *pkt_debugfs_root = NULL; /* /sys/kernel/debug/pktcdvd */
@@ -706,7 +707,6 @@ static int pkt_generic_packet(struct pktcdvd_device *pd, struct packet_command *
REQ_OP_SCSI_OUT : REQ_OP_SCSI_IN, __GFP_RECLAIM);
if (IS_ERR(rq))
return PTR_ERR(rq);
- scsi_req_init(rq);
if (cgc->buflen) {
ret = blk_rq_map_kern(q, rq, cgc->buffer, cgc->buflen,
@@ -951,9 +951,9 @@ static void pkt_end_io_read(struct bio *bio)
pkt_dbg(2, pd, "bio=%p sec0=%llx sec=%llx err=%d\n",
bio, (unsigned long long)pkt->sector,
- (unsigned long long)bio->bi_iter.bi_sector, bio->bi_error);
+ (unsigned long long)bio->bi_iter.bi_sector, bio->bi_status);
- if (bio->bi_error)
+ if (bio->bi_status)
atomic_inc(&pkt->io_errors);
if (atomic_dec_and_test(&pkt->io_wait)) {
atomic_inc(&pkt->run_sm);
@@ -968,7 +968,7 @@ static void pkt_end_io_packet_write(struct bio *bio)
struct pktcdvd_device *pd = pkt->pd;
BUG_ON(!pd);
- pkt_dbg(2, pd, "id=%d, err=%d\n", pkt->id, bio->bi_error);
+ pkt_dbg(2, pd, "id=%d, err=%d\n", pkt->id, bio->bi_status);
pd->stats.pkt_ended++;
@@ -1304,16 +1304,16 @@ static void pkt_start_write(struct pktcdvd_device *pd, struct packet_data *pkt)
pkt_queue_bio(pd, pkt->w_bio);
}
-static void pkt_finish_packet(struct packet_data *pkt, int error)
+static void pkt_finish_packet(struct packet_data *pkt, blk_status_t status)
{
struct bio *bio;
- if (error)
+ if (status)
pkt->cache_valid = 0;
/* Finish all bios corresponding to this packet */
while ((bio = bio_list_pop(&pkt->orig_bios))) {
- bio->bi_error = error;
+ bio->bi_status = status;
bio_endio(bio);
}
}
@@ -1348,7 +1348,7 @@ static void pkt_run_state_machine(struct pktcdvd_device *pd, struct packet_data
if (atomic_read(&pkt->io_wait) > 0)
return;
- if (!pkt->w_bio->bi_error) {
+ if (!pkt->w_bio->bi_status) {
pkt_set_state(pkt, PACKET_FINISHED_STATE);
} else {
pkt_set_state(pkt, PACKET_RECOVERY_STATE);
@@ -1365,7 +1365,7 @@ static void pkt_run_state_machine(struct pktcdvd_device *pd, struct packet_data
break;
case PACKET_FINISHED_STATE:
- pkt_finish_packet(pkt, pkt->w_bio->bi_error);
+ pkt_finish_packet(pkt, pkt->w_bio->bi_status);
return;
default:
@@ -2300,7 +2300,7 @@ static void pkt_end_io_read_cloned(struct bio *bio)
struct packet_stacked_data *psd = bio->bi_private;
struct pktcdvd_device *pd = psd->pd;
- psd->bio->bi_error = bio->bi_error;
+ psd->bio->bi_status = bio->bi_status;
bio_put(bio);
bio_endio(psd->bio);
mempool_free(psd, psd_pool);
@@ -2309,7 +2309,7 @@ static void pkt_end_io_read_cloned(struct bio *bio)
static void pkt_make_request_read(struct pktcdvd_device *pd, struct bio *bio)
{
- struct bio *cloned_bio = bio_clone(bio, GFP_NOIO);
+ struct bio *cloned_bio = bio_clone_fast(bio, GFP_NOIO, pkt_bio_set);
struct packet_stacked_data *psd = mempool_alloc(psd_pool, GFP_NOIO);
psd->pd = pd;
@@ -2411,9 +2411,7 @@ static blk_qc_t pkt_make_request(struct request_queue *q, struct bio *bio)
char b[BDEVNAME_SIZE];
struct bio *split;
- blk_queue_bounce(q, &bio);
-
- blk_queue_split(q, &bio, q->bio_split);
+ blk_queue_split(q, &bio);
pd = q->queuedata;
if (!pd) {
@@ -2454,7 +2452,7 @@ static blk_qc_t pkt_make_request(struct request_queue *q, struct bio *bio)
split = bio_split(bio, last_zone -
bio->bi_iter.bi_sector,
- GFP_NOIO, fs_bio_set);
+ GFP_NOIO, pkt_bio_set);
bio_chain(split, bio);
} else {
split = bio;
@@ -2582,6 +2580,11 @@ static int pkt_new_dev(struct pktcdvd_device *pd, dev_t dev)
bdev = bdget(dev);
if (!bdev)
return -ENOMEM;
+ if (!blk_queue_scsi_passthrough(bdev_get_queue(bdev))) {
+ WARN_ONCE(true, "Attempt to register a non-SCSI queue\n");
+ bdput(bdev);
+ return -EINVAL;
+ }
ret = blkdev_get(bdev, FMODE_READ | FMODE_NDELAY, NULL);
if (ret)
return ret;
@@ -2918,6 +2921,11 @@ static int __init pkt_init(void)
sizeof(struct packet_stacked_data));
if (!psd_pool)
return -ENOMEM;
+ pkt_bio_set = bioset_create(BIO_POOL_SIZE, 0, 0);
+ if (!pkt_bio_set) {
+ mempool_destroy(psd_pool);
+ return -ENOMEM;
+ }
ret = register_blkdev(pktdev_major, DRIVER_NAME);
if (ret < 0) {
@@ -2950,6 +2958,7 @@ out:
unregister_blkdev(pktdev_major, DRIVER_NAME);
out2:
mempool_destroy(psd_pool);
+ bioset_free(pkt_bio_set);
return ret;
}
@@ -2963,6 +2972,7 @@ static void __exit pkt_exit(void)
unregister_blkdev(pktdev_major, DRIVER_NAME);
mempool_destroy(psd_pool);
+ bioset_free(pkt_bio_set);
}
MODULE_DESCRIPTION("Packet writing layer for CD/DVD drives");
diff --git a/drivers/block/ps3disk.c b/drivers/block/ps3disk.c
index a809e3e9feb8..075662f2cf46 100644
--- a/drivers/block/ps3disk.c
+++ b/drivers/block/ps3disk.c
@@ -158,7 +158,7 @@ static int ps3disk_submit_request_sg(struct ps3_storage_device *dev,
if (res) {
dev_err(&dev->sbd.core, "%s:%u: %s failed %d\n", __func__,
__LINE__, op, res);
- __blk_end_request_all(req, -EIO);
+ __blk_end_request_all(req, BLK_STS_IOERR);
return 0;
}
@@ -180,7 +180,7 @@ static int ps3disk_submit_flush_request(struct ps3_storage_device *dev,
if (res) {
dev_err(&dev->sbd.core, "%s:%u: sync cache failed 0x%llx\n",
__func__, __LINE__, res);
- __blk_end_request_all(req, -EIO);
+ __blk_end_request_all(req, BLK_STS_IOERR);
return 0;
}
@@ -208,7 +208,7 @@ static void ps3disk_do_request(struct ps3_storage_device *dev,
break;
default:
blk_dump_rq_flags(req, DEVICE_NAME " bad request");
- __blk_end_request_all(req, -EIO);
+ __blk_end_request_all(req, BLK_STS_IOERR);
}
}
}
@@ -231,7 +231,8 @@ static irqreturn_t ps3disk_interrupt(int irq, void *data)
struct ps3_storage_device *dev = data;
struct ps3disk_private *priv;
struct request *req;
- int res, read, error;
+ int res, read;
+ blk_status_t error;
u64 tag, status;
const char *op;
@@ -269,7 +270,7 @@ static irqreturn_t ps3disk_interrupt(int irq, void *data)
if (status) {
dev_dbg(&dev->sbd.core, "%s:%u: %s failed 0x%llx\n", __func__,
__LINE__, op, status);
- error = -EIO;
+ error = BLK_STS_IOERR;
} else {
dev_dbg(&dev->sbd.core, "%s:%u: %s completed\n", __func__,
__LINE__, op);
diff --git a/drivers/block/ps3vram.c b/drivers/block/ps3vram.c
index 456b4fe21559..e0e81cacd781 100644
--- a/drivers/block/ps3vram.c
+++ b/drivers/block/ps3vram.c
@@ -428,7 +428,7 @@ static void ps3vram_cache_cleanup(struct ps3_system_bus_device *dev)
kfree(priv->cache.tags);
}
-static int ps3vram_read(struct ps3_system_bus_device *dev, loff_t from,
+static blk_status_t ps3vram_read(struct ps3_system_bus_device *dev, loff_t from,
size_t len, size_t *retlen, u_char *buf)
{
struct ps3vram_priv *priv = ps3_system_bus_get_drvdata(dev);
@@ -438,7 +438,7 @@ static int ps3vram_read(struct ps3_system_bus_device *dev, loff_t from,
(unsigned int)from, len);
if (from >= priv->size)
- return -EIO;
+ return BLK_STS_IOERR;
if (len > priv->size - from)
len = priv->size - from;
@@ -472,14 +472,14 @@ static int ps3vram_read(struct ps3_system_bus_device *dev, loff_t from,
return 0;
}
-static int ps3vram_write(struct ps3_system_bus_device *dev, loff_t to,
+static blk_status_t ps3vram_write(struct ps3_system_bus_device *dev, loff_t to,
size_t len, size_t *retlen, const u_char *buf)
{
struct ps3vram_priv *priv = ps3_system_bus_get_drvdata(dev);
unsigned int cached, count;
if (to >= priv->size)
- return -EIO;
+ return BLK_STS_IOERR;
if (len > priv->size - to)
len = priv->size - to;
@@ -554,7 +554,7 @@ static struct bio *ps3vram_do_bio(struct ps3_system_bus_device *dev,
int write = bio_data_dir(bio) == WRITE;
const char *op = write ? "write" : "read";
loff_t offset = bio->bi_iter.bi_sector << 9;
- int error = 0;
+ blk_status_t error = 0;
struct bio_vec bvec;
struct bvec_iter iter;
struct bio *next;
@@ -578,7 +578,7 @@ static struct bio *ps3vram_do_bio(struct ps3_system_bus_device *dev,
if (retlen != len) {
dev_err(&dev->core, "Short %s\n", op);
- error = -EIO;
+ error = BLK_STS_IOERR;
goto out;
}
@@ -593,7 +593,7 @@ out:
next = bio_list_peek(&priv->list);
spin_unlock_irq(&priv->lock);
- bio->bi_error = error;
+ bio->bi_status = error;
bio_endio(bio);
return next;
}
@@ -606,7 +606,7 @@ static blk_qc_t ps3vram_make_request(struct request_queue *q, struct bio *bio)
dev_dbg(&dev->core, "%s\n", __func__);
- blk_queue_split(q, &bio, q->bio_split);
+ blk_queue_split(q, &bio);
spin_lock_irq(&priv->lock);
busy = !bio_list_empty(&priv->list);
diff --git a/drivers/block/rbd.c b/drivers/block/rbd.c
index 454bf9c34882..b008b6a98098 100644
--- a/drivers/block/rbd.c
+++ b/drivers/block/rbd.c
@@ -442,6 +442,8 @@ static DEFINE_SPINLOCK(rbd_client_list_lock);
static struct kmem_cache *rbd_img_request_cache;
static struct kmem_cache *rbd_obj_request_cache;
+static struct bio_set *rbd_bio_clone;
+
static int rbd_major;
static DEFINE_IDA(rbd_dev_id_ida);
@@ -1363,7 +1365,7 @@ static struct bio *bio_clone_range(struct bio *bio_src,
{
struct bio *bio;
- bio = bio_clone(bio_src, gfpmask);
+ bio = bio_clone_fast(bio_src, gfpmask, rbd_bio_clone);
if (!bio)
return NULL; /* ENOMEM */
@@ -2293,11 +2295,13 @@ static bool rbd_img_obj_end_request(struct rbd_obj_request *obj_request)
rbd_assert(img_request->obj_request != NULL);
more = obj_request->which < img_request->obj_request_count - 1;
} else {
+ blk_status_t status = errno_to_blk_status(result);
+
rbd_assert(img_request->rq != NULL);
- more = blk_update_request(img_request->rq, result, xferred);
+ more = blk_update_request(img_request->rq, status, xferred);
if (!more)
- __blk_mq_end_request(img_request->rq, result);
+ __blk_mq_end_request(img_request->rq, status);
}
return more;
@@ -4023,6 +4027,7 @@ static void rbd_queue_workfn(struct work_struct *work)
switch (req_op(rq)) {
case REQ_OP_DISCARD:
+ case REQ_OP_WRITE_ZEROES:
op_type = OBJ_OP_DISCARD;
break;
case REQ_OP_WRITE:
@@ -4149,17 +4154,17 @@ err_rq:
obj_op_name(op_type), length, offset, result);
ceph_put_snap_context(snapc);
err:
- blk_mq_end_request(rq, result);
+ blk_mq_end_request(rq, errno_to_blk_status(result));
}
-static int rbd_queue_rq(struct blk_mq_hw_ctx *hctx,
+static blk_status_t rbd_queue_rq(struct blk_mq_hw_ctx *hctx,
const struct blk_mq_queue_data *bd)
{
struct request *rq = bd->rq;
struct work_struct *work = blk_mq_rq_to_pdu(rq);
queue_work(rbd_wq, work);
- return BLK_MQ_RQ_QUEUE_OK;
+ return BLK_STS_OK;
}
static void rbd_free_disk(struct rbd_device *rbd_dev)
@@ -4420,6 +4425,7 @@ static int rbd_init_disk(struct rbd_device *rbd_dev)
q->limits.discard_granularity = segment_size;
q->limits.discard_alignment = segment_size;
blk_queue_max_discard_sectors(q, segment_size / SECTOR_SIZE);
+ blk_queue_max_write_zeroes_sectors(q, segment_size / SECTOR_SIZE);
if (!ceph_test_opt(rbd_dev->rbd_client->client, NOCRC))
q->backing_dev_info->capabilities |= BDI_CAP_STABLE_WRITES;
@@ -6412,8 +6418,16 @@ static int rbd_slab_init(void)
if (!rbd_obj_request_cache)
goto out_err;
+ rbd_assert(!rbd_bio_clone);
+ rbd_bio_clone = bioset_create(BIO_POOL_SIZE, 0, 0);
+ if (!rbd_bio_clone)
+ goto out_err_clone;
+
return 0;
+out_err_clone:
+ kmem_cache_destroy(rbd_obj_request_cache);
+ rbd_obj_request_cache = NULL;
out_err:
kmem_cache_destroy(rbd_img_request_cache);
rbd_img_request_cache = NULL;
@@ -6429,6 +6443,10 @@ static void rbd_slab_exit(void)
rbd_assert(rbd_img_request_cache);
kmem_cache_destroy(rbd_img_request_cache);
rbd_img_request_cache = NULL;
+
+ rbd_assert(rbd_bio_clone);
+ bioset_free(rbd_bio_clone);
+ rbd_bio_clone = NULL;
}
static int __init rbd_init(void)
diff --git a/drivers/block/rsxx/dev.c b/drivers/block/rsxx/dev.c
index 9c566364ac9c..7f4acebf4657 100644
--- a/drivers/block/rsxx/dev.c
+++ b/drivers/block/rsxx/dev.c
@@ -149,9 +149,9 @@ static blk_qc_t rsxx_make_request(struct request_queue *q, struct bio *bio)
{
struct rsxx_cardinfo *card = q->queuedata;
struct rsxx_bio_meta *bio_meta;
- int st = -EINVAL;
+ blk_status_t st = BLK_STS_IOERR;
- blk_queue_split(q, &bio, q->bio_split);
+ blk_queue_split(q, &bio);
might_sleep();
@@ -161,15 +161,11 @@ static blk_qc_t rsxx_make_request(struct request_queue *q, struct bio *bio)
if (bio_end_sector(bio) > get_capacity(card->gendisk))
goto req_err;
- if (unlikely(card->halt)) {
- st = -EFAULT;
+ if (unlikely(card->halt))
goto req_err;
- }
- if (unlikely(card->dma_fault)) {
- st = (-EFAULT);
+ if (unlikely(card->dma_fault))
goto req_err;
- }
if (bio->bi_iter.bi_size == 0) {
dev_err(CARD_TO_DEV(card), "size zero BIO!\n");
@@ -178,7 +174,7 @@ static blk_qc_t rsxx_make_request(struct request_queue *q, struct bio *bio)
bio_meta = kmem_cache_alloc(bio_meta_pool, GFP_KERNEL);
if (!bio_meta) {
- st = -ENOMEM;
+ st = BLK_STS_RESOURCE;
goto req_err;
}
@@ -205,7 +201,7 @@ queue_err:
kmem_cache_free(bio_meta_pool, bio_meta);
req_err:
if (st)
- bio->bi_error = st;
+ bio->bi_status = st;
bio_endio(bio);
return BLK_QC_T_NONE;
}
@@ -288,7 +284,6 @@ int rsxx_setup_dev(struct rsxx_cardinfo *card)
}
blk_queue_make_request(card->queue, rsxx_make_request);
- blk_queue_bounce_limit(card->queue, BLK_BOUNCE_ANY);
blk_queue_max_hw_sectors(card->queue, blkdev_max_hw_sectors);
blk_queue_physical_block_size(card->queue, RSXX_HW_BLK_SIZE);
diff --git a/drivers/block/rsxx/dma.c b/drivers/block/rsxx/dma.c
index 5a20385f87d0..6a1b2177951c 100644
--- a/drivers/block/rsxx/dma.c
+++ b/drivers/block/rsxx/dma.c
@@ -611,7 +611,7 @@ static void rsxx_schedule_done(struct work_struct *work)
mutex_unlock(&ctrl->work_lock);
}
-static int rsxx_queue_discard(struct rsxx_cardinfo *card,
+static blk_status_t rsxx_queue_discard(struct rsxx_cardinfo *card,
struct list_head *q,
unsigned int laddr,
rsxx_dma_cb cb,
@@ -621,7 +621,7 @@ static int rsxx_queue_discard(struct rsxx_cardinfo *card,
dma = kmem_cache_alloc(rsxx_dma_pool, GFP_KERNEL);
if (!dma)
- return -ENOMEM;
+ return BLK_STS_RESOURCE;
dma->cmd = HW_CMD_BLK_DISCARD;
dma->laddr = laddr;
@@ -640,7 +640,7 @@ static int rsxx_queue_discard(struct rsxx_cardinfo *card,
return 0;
}
-static int rsxx_queue_dma(struct rsxx_cardinfo *card,
+static blk_status_t rsxx_queue_dma(struct rsxx_cardinfo *card,
struct list_head *q,
int dir,
unsigned int dma_off,
@@ -655,7 +655,7 @@ static int rsxx_queue_dma(struct rsxx_cardinfo *card,
dma = kmem_cache_alloc(rsxx_dma_pool, GFP_KERNEL);
if (!dma)
- return -ENOMEM;
+ return BLK_STS_RESOURCE;
dma->cmd = dir ? HW_CMD_BLK_WRITE : HW_CMD_BLK_READ;
dma->laddr = laddr;
@@ -677,7 +677,7 @@ static int rsxx_queue_dma(struct rsxx_cardinfo *card,
return 0;
}
-int rsxx_dma_queue_bio(struct rsxx_cardinfo *card,
+blk_status_t rsxx_dma_queue_bio(struct rsxx_cardinfo *card,
struct bio *bio,
atomic_t *n_dmas,
rsxx_dma_cb cb,
@@ -694,7 +694,7 @@ int rsxx_dma_queue_bio(struct rsxx_cardinfo *card,
unsigned int dma_len;
int dma_cnt[RSXX_MAX_TARGETS];
int tgt;
- int st;
+ blk_status_t st;
int i;
addr8 = bio->bi_iter.bi_sector << 9; /* sectors are 512 bytes */
@@ -769,7 +769,6 @@ bvec_err:
for (i = 0; i < card->n_targets; i++)
rsxx_cleanup_dma_queue(&card->ctrl[i], &dma_list[i],
FREE_DMA);
-
return st;
}
diff --git a/drivers/block/rsxx/rsxx_priv.h b/drivers/block/rsxx/rsxx_priv.h
index 6bbc64d0f690..277f27e673a2 100644
--- a/drivers/block/rsxx/rsxx_priv.h
+++ b/drivers/block/rsxx/rsxx_priv.h
@@ -391,7 +391,7 @@ int rsxx_dma_cancel(struct rsxx_dma_ctrl *ctrl);
void rsxx_dma_cleanup(void);
void rsxx_dma_queue_reset(struct rsxx_cardinfo *card);
int rsxx_dma_configure(struct rsxx_cardinfo *card);
-int rsxx_dma_queue_bio(struct rsxx_cardinfo *card,
+blk_status_t rsxx_dma_queue_bio(struct rsxx_cardinfo *card,
struct bio *bio,
atomic_t *n_dmas,
rsxx_dma_cb cb,
diff --git a/drivers/block/skd_main.c b/drivers/block/skd_main.c
index 27833e4dae2a..d0368682bd43 100644
--- a/drivers/block/skd_main.c
+++ b/drivers/block/skd_main.c
@@ -451,8 +451,8 @@ static void skd_send_special_fitmsg(struct skd_device *skdev,
struct skd_special_context *skspcl);
static void skd_request_fn(struct request_queue *rq);
static void skd_end_request(struct skd_device *skdev,
- struct skd_request_context *skreq, int error);
-static int skd_preop_sg_list(struct skd_device *skdev,
+ struct skd_request_context *skreq, blk_status_t status);
+static bool skd_preop_sg_list(struct skd_device *skdev,
struct skd_request_context *skreq);
static void skd_postop_sg_list(struct skd_device *skdev,
struct skd_request_context *skreq);
@@ -491,7 +491,7 @@ static void skd_fail_all_pending(struct skd_device *skdev)
if (req == NULL)
break;
blk_start_request(req);
- __blk_end_request_all(req, -EIO);
+ __blk_end_request_all(req, BLK_STS_IOERR);
}
}
@@ -545,7 +545,6 @@ static void skd_request_fn(struct request_queue *q)
struct request *req = NULL;
struct skd_scsi_request *scsi_req;
unsigned long io_flags;
- int error;
u32 lba;
u32 count;
int data_dir;
@@ -716,9 +715,7 @@ static void skd_request_fn(struct request_queue *q)
if (!req->bio)
goto skip_sg;
- error = skd_preop_sg_list(skdev, skreq);
-
- if (error != 0) {
+ if (!skd_preop_sg_list(skdev, skreq)) {
/*
* Complete the native request with error.
* Note that the request context is still at the
@@ -730,7 +727,7 @@ static void skd_request_fn(struct request_queue *q)
*/
pr_debug("%s:%s:%d error Out\n",
skdev->name, __func__, __LINE__);
- skd_end_request(skdev, skreq, error);
+ skd_end_request(skdev, skreq, BLK_STS_RESOURCE);
continue;
}
@@ -805,7 +802,7 @@ skip_sg:
}
static void skd_end_request(struct skd_device *skdev,
- struct skd_request_context *skreq, int error)
+ struct skd_request_context *skreq, blk_status_t error)
{
if (unlikely(error)) {
struct request *req = skreq->req;
@@ -822,7 +819,7 @@ static void skd_end_request(struct skd_device *skdev,
__blk_end_request_all(skreq->req, error);
}
-static int skd_preop_sg_list(struct skd_device *skdev,
+static bool skd_preop_sg_list(struct skd_device *skdev,
struct skd_request_context *skreq)
{
struct request *req = skreq->req;
@@ -839,7 +836,7 @@ static int skd_preop_sg_list(struct skd_device *skdev,
n_sg = blk_rq_map_sg(skdev->queue, req, sg);
if (n_sg <= 0)
- return -EINVAL;
+ return false;
/*
* Map scatterlist to PCI bus addresses.
@@ -847,7 +844,7 @@ static int skd_preop_sg_list(struct skd_device *skdev,
*/
n_sg = pci_map_sg(skdev->pdev, sg, n_sg, pci_dir);
if (n_sg <= 0)
- return -EINVAL;
+ return false;
SKD_ASSERT(n_sg <= skdev->sgs_per_request);
@@ -882,7 +879,7 @@ static int skd_preop_sg_list(struct skd_device *skdev,
}
}
- return 0;
+ return true;
}
static void skd_postop_sg_list(struct skd_device *skdev,
@@ -2333,7 +2330,7 @@ static void skd_resolve_req_exception(struct skd_device *skdev,
switch (skd_check_status(skdev, cmp_status, &skreq->err_info)) {
case SKD_CHECK_STATUS_REPORT_GOOD:
case SKD_CHECK_STATUS_REPORT_SMART_ALERT:
- skd_end_request(skdev, skreq, 0);
+ skd_end_request(skdev, skreq, BLK_STS_OK);
break;
case SKD_CHECK_STATUS_BUSY_IMMINENT:
@@ -2355,7 +2352,7 @@ static void skd_resolve_req_exception(struct skd_device *skdev,
case SKD_CHECK_STATUS_REPORT_ERROR:
default:
- skd_end_request(skdev, skreq, -EIO);
+ skd_end_request(skdev, skreq, BLK_STS_IOERR);
break;
}
}
@@ -2748,7 +2745,7 @@ static int skd_isr_completion_posted(struct skd_device *skdev,
* native request.
*/
if (likely(cmp_status == SAM_STAT_GOOD))
- skd_end_request(skdev, skreq, 0);
+ skd_end_request(skdev, skreq, BLK_STS_OK);
else
skd_resolve_req_exception(skdev, skreq);
}
@@ -3190,7 +3187,7 @@ static void skd_recover_requests(struct skd_device *skdev, int requeue)
SKD_MAX_RETRIES)
blk_requeue_request(skdev->queue, skreq->req);
else
- skd_end_request(skdev, skreq, -EIO);
+ skd_end_request(skdev, skreq, BLK_STS_IOERR);
skreq->req = NULL;
@@ -4276,6 +4273,7 @@ static int skd_cons_disk(struct skd_device *skdev)
rc = -ENOMEM;
goto err_out;
}
+ blk_queue_bounce_limit(q, BLK_BOUNCE_HIGH);
skdev->queue = q;
disk->queue = q;
diff --git a/drivers/block/sunvdc.c b/drivers/block/sunvdc.c
index 3f3a3ab3d50a..6b16ead1da58 100644
--- a/drivers/block/sunvdc.c
+++ b/drivers/block/sunvdc.c
@@ -316,7 +316,7 @@ static void vdc_end_one(struct vdc_port *port, struct vio_dring_state *dr,
rqe->req = NULL;
- __blk_end_request(req, (desc->status ? -EIO : 0), desc->size);
+ __blk_end_request(req, (desc->status ? BLK_STS_IOERR : 0), desc->size);
vdc_blk_queue_start(port);
}
@@ -1023,7 +1023,7 @@ static void vdc_queue_drain(struct vdc_port *port)
struct request *req;
while ((req = blk_fetch_request(port->disk->queue)) != NULL)
- __blk_end_request_all(req, -EIO);
+ __blk_end_request_all(req, BLK_STS_IOERR);
}
static void vdc_ldc_reset_timer(unsigned long _arg)
diff --git a/drivers/block/swim.c b/drivers/block/swim.c
index 3064be6cf375..84434d3ea19b 100644
--- a/drivers/block/swim.c
+++ b/drivers/block/swim.c
@@ -493,7 +493,7 @@ static inline int swim_read_sector(struct floppy_state *fs,
return ret;
}
-static int floppy_read_sectors(struct floppy_state *fs,
+static blk_status_t floppy_read_sectors(struct floppy_state *fs,
int req_sector, int sectors_nb,
unsigned char *buffer)
{
@@ -516,7 +516,7 @@ static int floppy_read_sectors(struct floppy_state *fs,
ret = swim_read_sector(fs, side, track, sector,
buffer);
if (try-- == 0)
- return -EIO;
+ return BLK_STS_IOERR;
} while (ret != 512);
buffer += ret;
@@ -553,7 +553,7 @@ static void do_fd_request(struct request_queue *q)
req = swim_next_request(swd);
while (req) {
- int err = -EIO;
+ blk_status_t err = BLK_STS_IOERR;
fs = req->rq_disk->private_data;
if (blk_rq_pos(req) >= fs->total_secs)
@@ -864,6 +864,8 @@ static int swim_floppy_init(struct swim_priv *swd)
put_disk(swd->unit[drive].disk);
goto exit_put_disks;
}
+ blk_queue_bounce_limit(swd->unit[drive].disk->queue,
+ BLK_BOUNCE_HIGH);
swd->unit[drive].disk->queue->queuedata = swd;
swd->unit[drive].swd = swd;
}
diff --git a/drivers/block/swim3.c b/drivers/block/swim3.c
index ba4809c9bdba..9f931f8f6b4c 100644
--- a/drivers/block/swim3.c
+++ b/drivers/block/swim3.c
@@ -257,7 +257,7 @@ static unsigned int floppy_check_events(struct gendisk *disk,
unsigned int clearing);
static int floppy_revalidate(struct gendisk *disk);
-static bool swim3_end_request(struct floppy_state *fs, int err, unsigned int nr_bytes)
+static bool swim3_end_request(struct floppy_state *fs, blk_status_t err, unsigned int nr_bytes)
{
struct request *req = fs->cur_req;
int rc;
@@ -334,7 +334,7 @@ static void start_request(struct floppy_state *fs)
if (fs->mdev->media_bay &&
check_media_bay(fs->mdev->media_bay) != MB_FD) {
swim3_dbg("%s", " media bay absent, dropping req\n");
- swim3_end_request(fs, -ENODEV, 0);
+ swim3_end_request(fs, BLK_STS_IOERR, 0);
continue;
}
@@ -350,12 +350,12 @@ static void start_request(struct floppy_state *fs)
if (blk_rq_pos(req) >= fs->total_secs) {
swim3_dbg(" pos out of bounds (%ld, max is %ld)\n",
(long)blk_rq_pos(req), (long)fs->total_secs);
- swim3_end_request(fs, -EIO, 0);
+ swim3_end_request(fs, BLK_STS_IOERR, 0);
continue;
}
if (fs->ejected) {
swim3_dbg("%s", " disk ejected\n");
- swim3_end_request(fs, -EIO, 0);
+ swim3_end_request(fs, BLK_STS_IOERR, 0);
continue;
}
@@ -364,7 +364,7 @@ static void start_request(struct floppy_state *fs)
fs->write_prot = swim3_readbit(fs, WRITE_PROT);
if (fs->write_prot) {
swim3_dbg("%s", " try to write, disk write protected\n");
- swim3_end_request(fs, -EIO, 0);
+ swim3_end_request(fs, BLK_STS_IOERR, 0);
continue;
}
}
@@ -548,7 +548,7 @@ static void act(struct floppy_state *fs)
if (fs->retries > 5) {
swim3_err("Wrong cylinder in transfer, want: %d got %d\n",
fs->req_cyl, fs->cur_cyl);
- swim3_end_request(fs, -EIO, 0);
+ swim3_end_request(fs, BLK_STS_IOERR, 0);
fs->state = idle;
return;
}
@@ -584,7 +584,7 @@ static void scan_timeout(unsigned long data)
out_8(&sw->intr_enable, 0);
fs->cur_cyl = -1;
if (fs->retries > 5) {
- swim3_end_request(fs, -EIO, 0);
+ swim3_end_request(fs, BLK_STS_IOERR, 0);
fs->state = idle;
start_request(fs);
} else {
@@ -608,7 +608,7 @@ static void seek_timeout(unsigned long data)
out_8(&sw->select, RELAX);
out_8(&sw->intr_enable, 0);
swim3_err("%s", "Seek timeout\n");
- swim3_end_request(fs, -EIO, 0);
+ swim3_end_request(fs, BLK_STS_IOERR, 0);
fs->state = idle;
start_request(fs);
spin_unlock_irqrestore(&swim3_lock, flags);
@@ -637,7 +637,7 @@ static void settle_timeout(unsigned long data)
goto unlock;
}
swim3_err("%s", "Seek settle timeout\n");
- swim3_end_request(fs, -EIO, 0);
+ swim3_end_request(fs, BLK_STS_IOERR, 0);
fs->state = idle;
start_request(fs);
unlock:
@@ -666,7 +666,7 @@ static void xfer_timeout(unsigned long data)
swim3_err("Timeout %sing sector %ld\n",
(rq_data_dir(fs->cur_req)==WRITE? "writ": "read"),
(long)blk_rq_pos(fs->cur_req));
- swim3_end_request(fs, -EIO, 0);
+ swim3_end_request(fs, BLK_STS_IOERR, 0);
fs->state = idle;
start_request(fs);
spin_unlock_irqrestore(&swim3_lock, flags);
@@ -703,7 +703,7 @@ static irqreturn_t swim3_interrupt(int irq, void *dev_id)
swim3_err("%s", "Seen sector but cyl=ff?\n");
fs->cur_cyl = -1;
if (fs->retries > 5) {
- swim3_end_request(fs, -EIO, 0);
+ swim3_end_request(fs, BLK_STS_IOERR, 0);
fs->state = idle;
start_request(fs);
} else {
@@ -786,7 +786,7 @@ static irqreturn_t swim3_interrupt(int irq, void *dev_id)
swim3_err("Error %sing block %ld (err=%x)\n",
rq_data_dir(req) == WRITE? "writ": "read",
(long)blk_rq_pos(req), err);
- swim3_end_request(fs, -EIO, 0);
+ swim3_end_request(fs, BLK_STS_IOERR, 0);
fs->state = idle;
}
} else {
@@ -795,7 +795,7 @@ static irqreturn_t swim3_interrupt(int irq, void *dev_id)
swim3_err("fd dma error: stat=%x resid=%d\n", stat, resid);
swim3_err(" state=%d, dir=%x, intr=%x, err=%x\n",
fs->state, rq_data_dir(req), intr, err);
- swim3_end_request(fs, -EIO, 0);
+ swim3_end_request(fs, BLK_STS_IOERR, 0);
fs->state = idle;
start_request(fs);
break;
@@ -1223,6 +1223,7 @@ static int swim3_attach(struct macio_dev *mdev,
put_disk(disk);
return -ENOMEM;
}
+ blk_queue_bounce_limit(disk->queue, BLK_BOUNCE_HIGH);
disk->queue->queuedata = &floppy_states[index];
if (index == 0) {
@@ -1245,7 +1246,7 @@ static int swim3_attach(struct macio_dev *mdev,
return 0;
}
-static struct of_device_id swim3_match[] =
+static const struct of_device_id swim3_match[] =
{
{
.name = "swim3",
diff --git a/drivers/block/sx8.c b/drivers/block/sx8.c
index c8e072caf56f..08586dc14e85 100644
--- a/drivers/block/sx8.c
+++ b/drivers/block/sx8.c
@@ -745,7 +745,7 @@ static unsigned int carm_fill_get_fw_ver(struct carm_host *host,
static inline void carm_end_request_queued(struct carm_host *host,
struct carm_request *crq,
- int error)
+ blk_status_t error)
{
struct request *req = crq->rq;
int rc;
@@ -791,7 +791,7 @@ static inline void carm_round_robin(struct carm_host *host)
}
static inline void carm_end_rq(struct carm_host *host, struct carm_request *crq,
- int error)
+ blk_status_t error)
{
carm_end_request_queued(host, crq, error);
if (max_queue == 1)
@@ -869,14 +869,14 @@ queue_one_request:
sg = &crq->sg[0];
n_elem = blk_rq_map_sg(q, rq, sg);
if (n_elem <= 0) {
- carm_end_rq(host, crq, -EIO);
+ carm_end_rq(host, crq, BLK_STS_IOERR);
return; /* request with no s/g entries? */
}
/* map scatterlist to PCI bus addresses */
n_elem = pci_map_sg(host->pdev, sg, n_elem, pci_dir);
if (n_elem <= 0) {
- carm_end_rq(host, crq, -EIO);
+ carm_end_rq(host, crq, BLK_STS_IOERR);
return; /* request with no s/g entries? */
}
crq->n_elem = n_elem;
@@ -937,7 +937,7 @@ queue_one_request:
static void carm_handle_array_info(struct carm_host *host,
struct carm_request *crq, u8 *mem,
- int error)
+ blk_status_t error)
{
struct carm_port *port;
u8 *msg_data = mem + sizeof(struct carm_array_info);
@@ -997,7 +997,7 @@ out:
static void carm_handle_scan_chan(struct carm_host *host,
struct carm_request *crq, u8 *mem,
- int error)
+ blk_status_t error)
{
u8 *msg_data = mem + IOC_SCAN_CHAN_OFFSET;
unsigned int i, dev_count = 0;
@@ -1029,7 +1029,7 @@ out:
}
static void carm_handle_generic(struct carm_host *host,
- struct carm_request *crq, int error,
+ struct carm_request *crq, blk_status_t error,
int cur_state, int next_state)
{
DPRINTK("ENTER\n");
@@ -1045,7 +1045,7 @@ static void carm_handle_generic(struct carm_host *host,
}
static inline void carm_handle_rw(struct carm_host *host,
- struct carm_request *crq, int error)
+ struct carm_request *crq, blk_status_t error)
{
int pci_dir;
@@ -1067,7 +1067,7 @@ static inline void carm_handle_resp(struct carm_host *host,
u32 handle = le32_to_cpu(ret_handle_le);
unsigned int msg_idx;
struct carm_request *crq;
- int error = (status == RMSG_OK) ? 0 : -EIO;
+ blk_status_t error = (status == RMSG_OK) ? 0 : BLK_STS_IOERR;
u8 *mem;
VPRINTK("ENTER, handle == 0x%x\n", handle);
@@ -1155,7 +1155,7 @@ static inline void carm_handle_resp(struct carm_host *host,
err_out:
printk(KERN_WARNING DRV_NAME "(%s): BUG: unhandled message type %d/%d\n",
pci_name(host->pdev), crq->msg_type, crq->msg_subtype);
- carm_end_rq(host, crq, -EIO);
+ carm_end_rq(host, crq, BLK_STS_IOERR);
}
static inline void carm_handle_responses(struct carm_host *host)
diff --git a/drivers/block/umem.c b/drivers/block/umem.c
index c141cc3be22b..0677d2514665 100644
--- a/drivers/block/umem.c
+++ b/drivers/block/umem.c
@@ -454,7 +454,7 @@ static void process_page(unsigned long data)
PCI_DMA_TODEVICE : PCI_DMA_FROMDEVICE);
if (control & DMASCR_HARD_ERROR) {
/* error */
- bio->bi_error = -EIO;
+ bio->bi_status = BLK_STS_IOERR;
dev_printk(KERN_WARNING, &card->dev->dev,
"I/O error on sector %d/%d\n",
le32_to_cpu(desc->local_addr)>>9,
@@ -529,7 +529,7 @@ static blk_qc_t mm_make_request(struct request_queue *q, struct bio *bio)
(unsigned long long)bio->bi_iter.bi_sector,
bio->bi_iter.bi_size);
- blk_queue_split(q, &bio, q->bio_split);
+ blk_queue_split(q, &bio);
spin_lock_irq(&card->lock);
*card->biotail = bio;
diff --git a/drivers/block/virtio_blk.c b/drivers/block/virtio_blk.c
index 553cc4c542b4..0297ad7c1452 100644
--- a/drivers/block/virtio_blk.c
+++ b/drivers/block/virtio_blk.c
@@ -64,15 +64,15 @@ struct virtblk_req {
struct scatterlist sg[];
};
-static inline int virtblk_result(struct virtblk_req *vbr)
+static inline blk_status_t virtblk_result(struct virtblk_req *vbr)
{
switch (vbr->status) {
case VIRTIO_BLK_S_OK:
- return 0;
+ return BLK_STS_OK;
case VIRTIO_BLK_S_UNSUPP:
- return -ENOTTY;
+ return BLK_STS_NOTSUPP;
default:
- return -EIO;
+ return BLK_STS_IOERR;
}
}
@@ -214,7 +214,7 @@ static void virtblk_done(struct virtqueue *vq)
spin_unlock_irqrestore(&vblk->vqs[qid].lock, flags);
}
-static int virtio_queue_rq(struct blk_mq_hw_ctx *hctx,
+static blk_status_t virtio_queue_rq(struct blk_mq_hw_ctx *hctx,
const struct blk_mq_queue_data *bd)
{
struct virtio_blk *vblk = hctx->queue->queuedata;
@@ -246,7 +246,7 @@ static int virtio_queue_rq(struct blk_mq_hw_ctx *hctx,
break;
default:
WARN_ON_ONCE(1);
- return BLK_MQ_RQ_QUEUE_ERROR;
+ return BLK_STS_IOERR;
}
vbr->out_hdr.type = cpu_to_virtio32(vblk->vdev, type);
@@ -276,8 +276,8 @@ static int virtio_queue_rq(struct blk_mq_hw_ctx *hctx,
/* Out of mem doesn't actually happen, since we fall back
* to direct descriptors */
if (err == -ENOMEM || err == -ENOSPC)
- return BLK_MQ_RQ_QUEUE_BUSY;
- return BLK_MQ_RQ_QUEUE_ERROR;
+ return BLK_STS_RESOURCE;
+ return BLK_STS_IOERR;
}
if (bd->last && virtqueue_kick_prepare(vblk->vqs[qid].vq))
@@ -286,7 +286,7 @@ static int virtio_queue_rq(struct blk_mq_hw_ctx *hctx,
if (notify)
virtqueue_notify(vblk->vqs[qid].vq);
- return BLK_MQ_RQ_QUEUE_OK;
+ return BLK_STS_OK;
}
/* return id (s/n) string for *disk to *id_str
@@ -307,7 +307,7 @@ static int virtblk_get_id(struct gendisk *disk, char *id_str)
goto out;
blk_execute_rq(vblk->disk->queue, vblk->disk, req, false);
- err = virtblk_result(blk_mq_rq_to_pdu(req));
+ err = blk_status_to_errno(virtblk_result(blk_mq_rq_to_pdu(req)));
out:
blk_put_request(req);
return err;
@@ -720,9 +720,6 @@ static int virtblk_probe(struct virtio_device *vdev)
/* We can handle whatever the host told us to handle. */
blk_queue_max_segments(q, vblk->sg_elems-2);
- /* No need to bounce any requests */
- blk_queue_bounce_limit(q, BLK_BOUNCE_ANY);
-
/* No real sector limit. */
blk_queue_max_hw_sectors(q, -1U);
diff --git a/drivers/block/xen-blkback/blkback.c b/drivers/block/xen-blkback/blkback.c
index 726c32e35db9..fe7cd58c43d0 100644
--- a/drivers/block/xen-blkback/blkback.c
+++ b/drivers/block/xen-blkback/blkback.c
@@ -609,8 +609,6 @@ int xen_blkif_schedule(void *arg)
unsigned long timeout;
int ret;
- xen_blkif_get(blkif);
-
set_freezable();
while (!kthread_should_stop()) {
if (try_to_freeze())
@@ -665,7 +663,6 @@ purge_gnt_list:
print_stats(ring);
ring->xenblkd = NULL;
- xen_blkif_put(blkif);
return 0;
}
@@ -1069,20 +1066,17 @@ static void xen_blk_drain_io(struct xen_blkif_ring *ring)
atomic_set(&blkif->drain, 0);
}
-/*
- * Completion callback on the bio's. Called as bh->b_end_io()
- */
-
-static void __end_block_io_op(struct pending_req *pending_req, int error)
+static void __end_block_io_op(struct pending_req *pending_req,
+ blk_status_t error)
{
/* An error fails the entire request. */
- if ((pending_req->operation == BLKIF_OP_FLUSH_DISKCACHE) &&
- (error == -EOPNOTSUPP)) {
+ if (pending_req->operation == BLKIF_OP_FLUSH_DISKCACHE &&
+ error == BLK_STS_NOTSUPP) {
pr_debug("flush diskcache op failed, not supported\n");
xen_blkbk_flush_diskcache(XBT_NIL, pending_req->ring->blkif->be, 0);
pending_req->status = BLKIF_RSP_EOPNOTSUPP;
- } else if ((pending_req->operation == BLKIF_OP_WRITE_BARRIER) &&
- (error == -EOPNOTSUPP)) {
+ } else if (pending_req->operation == BLKIF_OP_WRITE_BARRIER &&
+ error == BLK_STS_NOTSUPP) {
pr_debug("write barrier op failed, not supported\n");
xen_blkbk_barrier(XBT_NIL, pending_req->ring->blkif->be, 0);
pending_req->status = BLKIF_RSP_EOPNOTSUPP;
@@ -1106,7 +1100,7 @@ static void __end_block_io_op(struct pending_req *pending_req, int error)
*/
static void end_block_io_op(struct bio *bio)
{
- __end_block_io_op(bio->bi_private, bio->bi_error);
+ __end_block_io_op(bio->bi_private, bio->bi_status);
bio_put(bio);
}
@@ -1423,7 +1417,7 @@ static int dispatch_rw_block_io(struct xen_blkif_ring *ring,
for (i = 0; i < nbio; i++)
bio_put(biolist[i]);
atomic_set(&pending_req->pendcnt, 1);
- __end_block_io_op(pending_req, -EINVAL);
+ __end_block_io_op(pending_req, BLK_STS_RESOURCE);
msleep(1); /* back off a bit */
return -EIO;
}
@@ -1436,34 +1430,35 @@ static int dispatch_rw_block_io(struct xen_blkif_ring *ring,
static void make_response(struct xen_blkif_ring *ring, u64 id,
unsigned short op, int st)
{
- struct blkif_response resp;
+ struct blkif_response *resp;
unsigned long flags;
union blkif_back_rings *blk_rings;
int notify;
- resp.id = id;
- resp.operation = op;
- resp.status = st;
-
spin_lock_irqsave(&ring->blk_ring_lock, flags);
blk_rings = &ring->blk_rings;
/* Place on the response ring for the relevant domain. */
switch (ring->blkif->blk_protocol) {
case BLKIF_PROTOCOL_NATIVE:
- memcpy(RING_GET_RESPONSE(&blk_rings->native, blk_rings->native.rsp_prod_pvt),
- &resp, sizeof(resp));
+ resp = RING_GET_RESPONSE(&blk_rings->native,
+ blk_rings->native.rsp_prod_pvt);
break;
case BLKIF_PROTOCOL_X86_32:
- memcpy(RING_GET_RESPONSE(&blk_rings->x86_32, blk_rings->x86_32.rsp_prod_pvt),
- &resp, sizeof(resp));
+ resp = RING_GET_RESPONSE(&blk_rings->x86_32,
+ blk_rings->x86_32.rsp_prod_pvt);
break;
case BLKIF_PROTOCOL_X86_64:
- memcpy(RING_GET_RESPONSE(&blk_rings->x86_64, blk_rings->x86_64.rsp_prod_pvt),
- &resp, sizeof(resp));
+ resp = RING_GET_RESPONSE(&blk_rings->x86_64,
+ blk_rings->x86_64.rsp_prod_pvt);
break;
default:
BUG();
}
+
+ resp->id = id;
+ resp->operation = op;
+ resp->status = st;
+
blk_rings->common.rsp_prod_pvt++;
RING_PUSH_RESPONSES_AND_CHECK_NOTIFY(&blk_rings->common, notify);
spin_unlock_irqrestore(&ring->blk_ring_lock, flags);
diff --git a/drivers/block/xen-blkback/common.h b/drivers/block/xen-blkback/common.h
index dea61f6ab8cb..ecb35fe8ca8d 100644
--- a/drivers/block/xen-blkback/common.h
+++ b/drivers/block/xen-blkback/common.h
@@ -75,9 +75,8 @@ extern unsigned int xenblk_max_queues;
struct blkif_common_request {
char dummy;
};
-struct blkif_common_response {
- char dummy;
-};
+
+/* i386 protocol version */
struct blkif_x86_32_request_rw {
uint8_t nr_segments; /* number of segments */
@@ -129,14 +128,6 @@ struct blkif_x86_32_request {
} u;
} __attribute__((__packed__));
-/* i386 protocol version */
-#pragma pack(push, 4)
-struct blkif_x86_32_response {
- uint64_t id; /* copied from request */
- uint8_t operation; /* copied from request */
- int16_t status; /* BLKIF_RSP_??? */
-};
-#pragma pack(pop)
/* x86_64 protocol version */
struct blkif_x86_64_request_rw {
@@ -193,18 +184,12 @@ struct blkif_x86_64_request {
} u;
} __attribute__((__packed__));
-struct blkif_x86_64_response {
- uint64_t __attribute__((__aligned__(8))) id;
- uint8_t operation; /* copied from request */
- int16_t status; /* BLKIF_RSP_??? */
-};
-
DEFINE_RING_TYPES(blkif_common, struct blkif_common_request,
- struct blkif_common_response);
+ struct blkif_response);
DEFINE_RING_TYPES(blkif_x86_32, struct blkif_x86_32_request,
- struct blkif_x86_32_response);
+ struct blkif_response __packed);
DEFINE_RING_TYPES(blkif_x86_64, struct blkif_x86_64_request,
- struct blkif_x86_64_response);
+ struct blkif_response);
union blkif_back_rings {
struct blkif_back_ring native;
@@ -281,6 +266,7 @@ struct xen_blkif_ring {
wait_queue_head_t wq;
atomic_t inflight;
+ bool active;
/* One thread per blkif ring. */
struct task_struct *xenblkd;
unsigned int waiting_reqs;
diff --git a/drivers/block/xen-blkback/xenbus.c b/drivers/block/xen-blkback/xenbus.c
index 1f3dfaa54d87..792da683e70d 100644
--- a/drivers/block/xen-blkback/xenbus.c
+++ b/drivers/block/xen-blkback/xenbus.c
@@ -159,7 +159,7 @@ static int xen_blkif_alloc_rings(struct xen_blkif *blkif)
init_waitqueue_head(&ring->shutdown_wq);
ring->blkif = blkif;
ring->st_print = jiffies;
- xen_blkif_get(blkif);
+ ring->active = true;
}
return 0;
@@ -249,10 +249,12 @@ static int xen_blkif_disconnect(struct xen_blkif *blkif)
struct xen_blkif_ring *ring = &blkif->rings[r];
unsigned int i = 0;
+ if (!ring->active)
+ continue;
+
if (ring->xenblkd) {
kthread_stop(ring->xenblkd);
wake_up(&ring->shutdown_wq);
- ring->xenblkd = NULL;
}
/* The above kthread_stop() guarantees that at this point we
@@ -296,7 +298,7 @@ static int xen_blkif_disconnect(struct xen_blkif *blkif)
BUG_ON(ring->free_pages_num != 0);
BUG_ON(ring->persistent_gnt_c != 0);
WARN_ON(i != (XEN_BLKIF_REQS_PER_PAGE * blkif->nr_ring_pages));
- xen_blkif_put(blkif);
+ ring->active = false;
}
blkif->nr_ring_pages = 0;
/*
@@ -312,9 +314,10 @@ static int xen_blkif_disconnect(struct xen_blkif *blkif)
static void xen_blkif_free(struct xen_blkif *blkif)
{
-
- xen_blkif_disconnect(blkif);
+ WARN_ON(xen_blkif_disconnect(blkif));
xen_vbd_free(&blkif->vbd);
+ kfree(blkif->be->mode);
+ kfree(blkif->be);
/* Make sure everything is drained before shutting down */
kmem_cache_free(xen_blkif_cachep, blkif);
@@ -511,8 +514,6 @@ static int xen_blkbk_remove(struct xenbus_device *dev)
xen_blkif_put(be->blkif);
}
- kfree(be->mode);
- kfree(be);
return 0;
}
diff --git a/drivers/block/xen-blkfront.c b/drivers/block/xen-blkfront.c
index 39459631667c..c852ed3c01d5 100644
--- a/drivers/block/xen-blkfront.c
+++ b/drivers/block/xen-blkfront.c
@@ -110,11 +110,6 @@ struct blk_shadow {
unsigned long associated_id;
};
-struct split_bio {
- struct bio *bio;
- atomic_t pending;
-};
-
struct blkif_req {
int error;
};
@@ -881,7 +876,7 @@ static inline bool blkif_request_flush_invalid(struct request *req,
!info->feature_fua));
}
-static int blkif_queue_rq(struct blk_mq_hw_ctx *hctx,
+static blk_status_t blkif_queue_rq(struct blk_mq_hw_ctx *hctx,
const struct blk_mq_queue_data *qd)
{
unsigned long flags;
@@ -904,16 +899,16 @@ static int blkif_queue_rq(struct blk_mq_hw_ctx *hctx,
flush_requests(rinfo);
spin_unlock_irqrestore(&rinfo->ring_lock, flags);
- return BLK_MQ_RQ_QUEUE_OK;
+ return BLK_STS_OK;
out_err:
spin_unlock_irqrestore(&rinfo->ring_lock, flags);
- return BLK_MQ_RQ_QUEUE_ERROR;
+ return BLK_STS_IOERR;
out_busy:
spin_unlock_irqrestore(&rinfo->ring_lock, flags);
blk_mq_stop_hw_queue(hctx);
- return BLK_MQ_RQ_QUEUE_BUSY;
+ return BLK_STS_RESOURCE;
}
static void blkif_complete_rq(struct request *rq)
@@ -958,9 +953,6 @@ static void blkif_set_queue_limits(struct blkfront_info *info)
/* Make sure buffer addresses are sector-aligned. */
blk_queue_dma_alignment(rq, 511);
-
- /* Make sure we don't use bounce buffers. */
- blk_queue_bounce_limit(rq, BLK_BOUNCE_ANY);
}
static int xlvbd_init_blk_queue(struct gendisk *gd, u16 sector_size,
@@ -1601,14 +1593,18 @@ static irqreturn_t blkif_interrupt(int irq, void *dev_id)
continue;
}
- blkif_req(req)->error = (bret->status == BLKIF_RSP_OKAY) ? 0 : -EIO;
+ if (bret->status == BLKIF_RSP_OKAY)
+ blkif_req(req)->error = BLK_STS_OK;
+ else
+ blkif_req(req)->error = BLK_STS_IOERR;
+
switch (bret->operation) {
case BLKIF_OP_DISCARD:
if (unlikely(bret->status == BLKIF_RSP_EOPNOTSUPP)) {
struct request_queue *rq = info->rq;
printk(KERN_WARNING "blkfront: %s: %s op failed\n",
info->gd->disk_name, op_name(bret->operation));
- blkif_req(req)->error = -EOPNOTSUPP;
+ blkif_req(req)->error = BLK_STS_NOTSUPP;
info->feature_discard = 0;
info->feature_secdiscard = 0;
queue_flag_clear(QUEUE_FLAG_DISCARD, rq);
@@ -1626,11 +1622,11 @@ static irqreturn_t blkif_interrupt(int irq, void *dev_id)
rinfo->shadow[id].req.u.rw.nr_segments == 0)) {
printk(KERN_WARNING "blkfront: %s: empty %s op failed\n",
info->gd->disk_name, op_name(bret->operation));
- blkif_req(req)->error = -EOPNOTSUPP;
+ blkif_req(req)->error = BLK_STS_NOTSUPP;
}
if (unlikely(blkif_req(req)->error)) {
- if (blkif_req(req)->error == -EOPNOTSUPP)
- blkif_req(req)->error = 0;
+ if (blkif_req(req)->error == BLK_STS_NOTSUPP)
+ blkif_req(req)->error = BLK_STS_OK;
info->feature_fua = 0;
info->feature_flush = 0;
xlvbd_flush(info);
@@ -1996,28 +1992,13 @@ static int blkfront_probe(struct xenbus_device *dev,
return 0;
}
-static void split_bio_end(struct bio *bio)
-{
- struct split_bio *split_bio = bio->bi_private;
-
- if (atomic_dec_and_test(&split_bio->pending)) {
- split_bio->bio->bi_phys_segments = 0;
- split_bio->bio->bi_error = bio->bi_error;
- bio_endio(split_bio->bio);
- kfree(split_bio);
- }
- bio_put(bio);
-}
-
static int blkif_recover(struct blkfront_info *info)
{
- unsigned int i, r_index;
+ unsigned int r_index;
struct request *req, *n;
int rc;
- struct bio *bio, *cloned_bio;
- unsigned int segs, offset;
- int pending, size;
- struct split_bio *split_bio;
+ struct bio *bio;
+ unsigned int segs;
blkfront_gather_backend_features(info);
/* Reset limits changed by blk_mq_update_nr_hw_queues(). */
@@ -2056,34 +2037,6 @@ static int blkif_recover(struct blkfront_info *info)
while ((bio = bio_list_pop(&info->bio_list)) != NULL) {
/* Traverse the list of pending bios and re-queue them */
- if (bio_segments(bio) > segs) {
- /*
- * This bio has more segments than what we can
- * handle, we have to split it.
- */
- pending = (bio_segments(bio) + segs - 1) / segs;
- split_bio = kzalloc(sizeof(*split_bio), GFP_NOIO);
- BUG_ON(split_bio == NULL);
- atomic_set(&split_bio->pending, pending);
- split_bio->bio = bio;
- for (i = 0; i < pending; i++) {
- offset = (i * segs * XEN_PAGE_SIZE) >> 9;
- size = min((unsigned int)(segs * XEN_PAGE_SIZE) >> 9,
- (unsigned int)bio_sectors(bio) - offset);
- cloned_bio = bio_clone(bio, GFP_NOIO);
- BUG_ON(cloned_bio == NULL);
- bio_trim(cloned_bio, offset, size);
- cloned_bio->bi_private = split_bio;
- cloned_bio->bi_end_io = split_bio_end;
- submit_bio(cloned_bio);
- }
- /*
- * Now we have to wait for all those smaller bios to
- * end, so we can also end the "parent" bio.
- */
- continue;
- }
- /* We don't need to split this bio */
submit_bio(bio);
}
@@ -2137,7 +2090,7 @@ static int blkfront_resume(struct xenbus_device *dev)
merge_bio.tail = shadow[j].request->biotail;
bio_list_merge(&info->bio_list, &merge_bio);
shadow[j].request->bio = NULL;
- blk_mq_end_request(shadow[j].request, 0);
+ blk_mq_end_request(shadow[j].request, BLK_STS_OK);
}
}
diff --git a/drivers/block/xsysace.c b/drivers/block/xsysace.c
index 757dce2147e0..14459d66ef0c 100644
--- a/drivers/block/xsysace.c
+++ b/drivers/block/xsysace.c
@@ -471,7 +471,7 @@ static struct request *ace_get_next_request(struct request_queue *q)
if (!blk_rq_is_passthrough(req))
break;
blk_start_request(req);
- __blk_end_request_all(req, -EIO);
+ __blk_end_request_all(req, BLK_STS_IOERR);
}
return req;
}
@@ -499,11 +499,11 @@ static void ace_fsm_dostate(struct ace_device *ace)
/* Drop all in-flight and pending requests */
if (ace->req) {
- __blk_end_request_all(ace->req, -EIO);
+ __blk_end_request_all(ace->req, BLK_STS_IOERR);
ace->req = NULL;
}
while ((req = blk_fetch_request(ace->queue)) != NULL)
- __blk_end_request_all(req, -EIO);
+ __blk_end_request_all(req, BLK_STS_IOERR);
/* Drop back to IDLE state and notify waiters */
ace->fsm_state = ACE_FSM_STATE_IDLE;
@@ -728,7 +728,7 @@ static void ace_fsm_dostate(struct ace_device *ace)
}
/* bio finished; is there another one? */
- if (__blk_end_request_cur(ace->req, 0)) {
+ if (__blk_end_request_cur(ace->req, BLK_STS_OK)) {
/* dev_dbg(ace->dev, "next block; h=%u c=%u\n",
* blk_rq_sectors(ace->req),
* blk_rq_cur_sectors(ace->req));
@@ -993,6 +993,7 @@ static int ace_setup(struct ace_device *ace)
if (ace->queue == NULL)
goto err_blk_initq;
blk_queue_logical_block_size(ace->queue, 512);
+ blk_queue_bounce_limit(ace->queue, BLK_BOUNCE_HIGH);
/*
* Allocate and initialize GD structure
diff --git a/drivers/block/z2ram.c b/drivers/block/z2ram.c
index 968f9e52effa..41c95c9b2ab4 100644
--- a/drivers/block/z2ram.c
+++ b/drivers/block/z2ram.c
@@ -74,14 +74,14 @@ static void do_z2_request(struct request_queue *q)
while (req) {
unsigned long start = blk_rq_pos(req) << 9;
unsigned long len = blk_rq_cur_bytes(req);
- int err = 0;
+ blk_status_t err = BLK_STS_OK;
if (start + len > z2ram_size) {
pr_err(DEVICE_NAME ": bad access: block=%llu, "
"count=%u\n",
(unsigned long long)blk_rq_pos(req),
blk_rq_cur_sectors(req));
- err = -EIO;
+ err = BLK_STS_IOERR;
goto done;
}
while (len) {
diff --git a/drivers/bluetooth/btmrvl_main.c b/drivers/bluetooth/btmrvl_main.c
index c38cb5b91291..fe850f0567cb 100644
--- a/drivers/bluetooth/btmrvl_main.c
+++ b/drivers/bluetooth/btmrvl_main.c
@@ -602,7 +602,7 @@ static int btmrvl_service_main_thread(void *data)
struct btmrvl_thread *thread = data;
struct btmrvl_private *priv = thread->priv;
struct btmrvl_adapter *adapter = priv->adapter;
- wait_queue_t wait;
+ wait_queue_entry_t wait;
struct sk_buff *skb;
ulong flags;
diff --git a/drivers/cdrom/cdrom.c b/drivers/cdrom/cdrom.c
index 76c952fd9ab9..e36d160c458f 100644
--- a/drivers/cdrom/cdrom.c
+++ b/drivers/cdrom/cdrom.c
@@ -2178,6 +2178,12 @@ static int cdrom_read_cdda_bpc(struct cdrom_device_info *cdi, __u8 __user *ubuf,
if (!q)
return -ENXIO;
+ if (!blk_queue_scsi_passthrough(q)) {
+ WARN_ONCE(true,
+ "Attempt read CDDA info through a non-SCSI queue\n");
+ return -EINVAL;
+ }
+
cdi->last_sense = 0;
while (nframes) {
@@ -2195,7 +2201,6 @@ static int cdrom_read_cdda_bpc(struct cdrom_device_info *cdi, __u8 __user *ubuf,
break;
}
req = scsi_req(rq);
- scsi_req_init(rq);
ret = blk_rq_map_user(q, rq, NULL, ubuf, len, GFP_KERNEL);
if (ret) {
diff --git a/drivers/cdrom/gdrom.c b/drivers/cdrom/gdrom.c
index 1372763a948f..6495b03f576c 100644
--- a/drivers/cdrom/gdrom.c
+++ b/drivers/cdrom/gdrom.c
@@ -583,7 +583,8 @@ static int gdrom_set_interrupt_handlers(void)
*/
static void gdrom_readdisk_dma(struct work_struct *work)
{
- int err, block, block_cnt;
+ int block, block_cnt;
+ blk_status_t err;
struct packet_command *read_command;
struct list_head *elem, *next;
struct request *req;
@@ -641,7 +642,7 @@ static void gdrom_readdisk_dma(struct work_struct *work)
__raw_writeb(1, GDROM_DMA_STATUS_REG);
wait_event_interruptible_timeout(request_queue,
gd.transfer == 0, GDROM_DEFAULT_TIMEOUT);
- err = gd.transfer ? -EIO : 0;
+ err = gd.transfer ? BLK_STS_IOERR : BLK_STS_OK;
gd.transfer = 0;
gd.pending = 0;
/* now seek to take the request spinlock
@@ -670,11 +671,11 @@ static void gdrom_request(struct request_queue *rq)
break;
case REQ_OP_WRITE:
pr_notice("Read only device - write request ignored\n");
- __blk_end_request_all(req, -EIO);
+ __blk_end_request_all(req, BLK_STS_IOERR);
break;
default:
printk(KERN_DEBUG "gdrom: Non-fs request ignored\n");
- __blk_end_request_all(req, -EIO);
+ __blk_end_request_all(req, BLK_STS_IOERR);
break;
}
}
@@ -812,6 +813,7 @@ static int probe_gdrom(struct platform_device *devptr)
err = -ENOMEM;
goto probe_fail_requestq;
}
+ blk_queue_bounce_limit(gd.gdrom_rq, BLK_BOUNCE_HIGH);
err = probe_gdrom_setupqueue();
if (err)
diff --git a/drivers/char/Kconfig b/drivers/char/Kconfig
index 31adbebf812e..2af70014ee5a 100644
--- a/drivers/char/Kconfig
+++ b/drivers/char/Kconfig
@@ -539,15 +539,6 @@ config HANGCHECK_TIMER
out to lunch past a certain margin. It can reboot the system
or merely print a warning.
-config MMTIMER
- tristate "MMTIMER Memory mapped RTC for SGI Altix"
- depends on IA64_GENERIC || IA64_SGI_SN2
- depends on POSIX_TIMERS
- default y
- help
- The mmtimer device allows direct userspace access to the
- Altix system timer.
-
config UV_MMTIMER
tristate "UV_MMTIMER Memory mapped RTC for SGI UV"
depends on X86_UV
diff --git a/drivers/char/Makefile b/drivers/char/Makefile
index 6e6c244a66a0..53e33720818c 100644
--- a/drivers/char/Makefile
+++ b/drivers/char/Makefile
@@ -10,7 +10,6 @@ obj-$(CONFIG_VIRTIO_CONSOLE) += virtio_console.o
obj-$(CONFIG_RAW_DRIVER) += raw.o
obj-$(CONFIG_SGI_SNSC) += snsc.o snsc_event.o
obj-$(CONFIG_MSPEC) += mspec.o
-obj-$(CONFIG_MMTIMER) += mmtimer.o
obj-$(CONFIG_UV_MMTIMER) += uv_mmtimer.o
obj-$(CONFIG_IBM_BSR) += bsr.o
obj-$(CONFIG_SGI_MBCS) += mbcs.o
diff --git a/drivers/char/ipmi/ipmi_watchdog.c b/drivers/char/ipmi/ipmi_watchdog.c
index d165af8abe36..a5c6cfe71a8e 100644
--- a/drivers/char/ipmi/ipmi_watchdog.c
+++ b/drivers/char/ipmi/ipmi_watchdog.c
@@ -821,7 +821,7 @@ static ssize_t ipmi_read(struct file *file,
loff_t *ppos)
{
int rv = 0;
- wait_queue_t wait;
+ wait_queue_entry_t wait;
if (count <= 0)
return 0;
diff --git a/drivers/char/mem.c b/drivers/char/mem.c
index 6e0cbe092220..593a8818aca9 100644
--- a/drivers/char/mem.c
+++ b/drivers/char/mem.c
@@ -343,7 +343,7 @@ static int mmap_mem(struct file *file, struct vm_area_struct *vma)
phys_addr_t offset = (phys_addr_t)vma->vm_pgoff << PAGE_SHIFT;
/* It's illegal to wrap around the end of the physical address space. */
- if (offset + (phys_addr_t)size < offset)
+ if (offset + (phys_addr_t)size - 1 < offset)
return -EINVAL;
if (!valid_mmap_phys_addr_range(vma->vm_pgoff, size))
diff --git a/drivers/char/mmtimer.c b/drivers/char/mmtimer.c
deleted file mode 100644
index 0e7fcb04f01e..000000000000
--- a/drivers/char/mmtimer.c
+++ /dev/null
@@ -1,858 +0,0 @@
-/*
- * Timer device implementation for SGI SN platforms.
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License. See the file "COPYING" in the main directory of this archive
- * for more details.
- *
- * Copyright (c) 2001-2006 Silicon Graphics, Inc. All rights reserved.
- *
- * This driver exports an API that should be supportable by any HPET or IA-PC
- * multimedia timer. The code below is currently specific to the SGI Altix
- * SHub RTC, however.
- *
- * 11/01/01 - jbarnes - initial revision
- * 9/10/04 - Christoph Lameter - remove interrupt support for kernel inclusion
- * 10/1/04 - Christoph Lameter - provide posix clock CLOCK_SGI_CYCLE
- * 10/13/04 - Christoph Lameter, Dimitri Sivanich - provide timer interrupt
- * support via the posix timer interface
- */
-
-#include <linux/types.h>
-#include <linux/kernel.h>
-#include <linux/ioctl.h>
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/errno.h>
-#include <linux/mm.h>
-#include <linux/fs.h>
-#include <linux/mmtimer.h>
-#include <linux/miscdevice.h>
-#include <linux/posix-timers.h>
-#include <linux/interrupt.h>
-#include <linux/time.h>
-#include <linux/math64.h>
-#include <linux/mutex.h>
-#include <linux/slab.h>
-
-#include <linux/uaccess.h>
-#include <asm/sn/addrs.h>
-#include <asm/sn/intr.h>
-#include <asm/sn/shub_mmr.h>
-#include <asm/sn/nodepda.h>
-#include <asm/sn/shubio.h>
-
-MODULE_AUTHOR("Jesse Barnes <jbarnes@sgi.com>");
-MODULE_DESCRIPTION("SGI Altix RTC Timer");
-MODULE_LICENSE("GPL");
-
-/* name of the device, usually in /dev */
-#define MMTIMER_NAME "mmtimer"
-#define MMTIMER_DESC "SGI Altix RTC Timer"
-#define MMTIMER_VERSION "2.1"
-
-#define RTC_BITS 55 /* 55 bits for this implementation */
-
-static struct k_clock sgi_clock;
-
-extern unsigned long sn_rtc_cycles_per_second;
-
-#define RTC_COUNTER_ADDR ((long *)LOCAL_MMR_ADDR(SH_RTC))
-
-#define rtc_time() (*RTC_COUNTER_ADDR)
-
-static DEFINE_MUTEX(mmtimer_mutex);
-static long mmtimer_ioctl(struct file *file, unsigned int cmd,
- unsigned long arg);
-static int mmtimer_mmap(struct file *file, struct vm_area_struct *vma);
-
-/*
- * Period in femtoseconds (10^-15 s)
- */
-static unsigned long mmtimer_femtoperiod = 0;
-
-static const struct file_operations mmtimer_fops = {
- .owner = THIS_MODULE,
- .mmap = mmtimer_mmap,
- .unlocked_ioctl = mmtimer_ioctl,
- .llseek = noop_llseek,
-};
-
-/*
- * We only have comparison registers RTC1-4 currently available per
- * node. RTC0 is used by SAL.
- */
-/* Check for an RTC interrupt pending */
-static int mmtimer_int_pending(int comparator)
-{
- if (HUB_L((unsigned long *)LOCAL_MMR_ADDR(SH_EVENT_OCCURRED)) &
- SH_EVENT_OCCURRED_RTC1_INT_MASK << comparator)
- return 1;
- else
- return 0;
-}
-
-/* Clear the RTC interrupt pending bit */
-static void mmtimer_clr_int_pending(int comparator)
-{
- HUB_S((u64 *)LOCAL_MMR_ADDR(SH_EVENT_OCCURRED_ALIAS),
- SH_EVENT_OCCURRED_RTC1_INT_MASK << comparator);
-}
-
-/* Setup timer on comparator RTC1 */
-static void mmtimer_setup_int_0(int cpu, u64 expires)
-{
- u64 val;
-
- /* Disable interrupt */
- HUB_S((u64 *)LOCAL_MMR_ADDR(SH_RTC1_INT_ENABLE), 0UL);
-
- /* Initialize comparator value */
- HUB_S((u64 *)LOCAL_MMR_ADDR(SH_INT_CMPB), -1L);
-
- /* Clear pending bit */
- mmtimer_clr_int_pending(0);
-
- val = ((u64)SGI_MMTIMER_VECTOR << SH_RTC1_INT_CONFIG_IDX_SHFT) |
- ((u64)cpu_physical_id(cpu) <<
- SH_RTC1_INT_CONFIG_PID_SHFT);
-
- /* Set configuration */
- HUB_S((u64 *)LOCAL_MMR_ADDR(SH_RTC1_INT_CONFIG), val);
-
- /* Enable RTC interrupts */
- HUB_S((u64 *)LOCAL_MMR_ADDR(SH_RTC1_INT_ENABLE), 1UL);
-
- /* Initialize comparator value */
- HUB_S((u64 *)LOCAL_MMR_ADDR(SH_INT_CMPB), expires);
-
-
-}
-
-/* Setup timer on comparator RTC2 */
-static void mmtimer_setup_int_1(int cpu, u64 expires)
-{
- u64 val;
-
- HUB_S((u64 *)LOCAL_MMR_ADDR(SH_RTC2_INT_ENABLE), 0UL);
-
- HUB_S((u64 *)LOCAL_MMR_ADDR(SH_INT_CMPC), -1L);
-
- mmtimer_clr_int_pending(1);
-
- val = ((u64)SGI_MMTIMER_VECTOR << SH_RTC2_INT_CONFIG_IDX_SHFT) |
- ((u64)cpu_physical_id(cpu) <<
- SH_RTC2_INT_CONFIG_PID_SHFT);
-
- HUB_S((u64 *)LOCAL_MMR_ADDR(SH_RTC2_INT_CONFIG), val);
-
- HUB_S((u64 *)LOCAL_MMR_ADDR(SH_RTC2_INT_ENABLE), 1UL);
-
- HUB_S((u64 *)LOCAL_MMR_ADDR(SH_INT_CMPC), expires);
-}
-
-/* Setup timer on comparator RTC3 */
-static void mmtimer_setup_int_2(int cpu, u64 expires)
-{
- u64 val;
-
- HUB_S((u64 *)LOCAL_MMR_ADDR(SH_RTC3_INT_ENABLE), 0UL);
-
- HUB_S((u64 *)LOCAL_MMR_ADDR(SH_INT_CMPD), -1L);
-
- mmtimer_clr_int_pending(2);
-
- val = ((u64)SGI_MMTIMER_VECTOR << SH_RTC3_INT_CONFIG_IDX_SHFT) |
- ((u64)cpu_physical_id(cpu) <<
- SH_RTC3_INT_CONFIG_PID_SHFT);
-
- HUB_S((u64 *)LOCAL_MMR_ADDR(SH_RTC3_INT_CONFIG), val);
-
- HUB_S((u64 *)LOCAL_MMR_ADDR(SH_RTC3_INT_ENABLE), 1UL);
-
- HUB_S((u64 *)LOCAL_MMR_ADDR(SH_INT_CMPD), expires);
-}
-
-/*
- * This function must be called with interrupts disabled and preemption off
- * in order to insure that the setup succeeds in a deterministic time frame.
- * It will check if the interrupt setup succeeded.
- */
-static int mmtimer_setup(int cpu, int comparator, unsigned long expires,
- u64 *set_completion_time)
-{
- switch (comparator) {
- case 0:
- mmtimer_setup_int_0(cpu, expires);
- break;
- case 1:
- mmtimer_setup_int_1(cpu, expires);
- break;
- case 2:
- mmtimer_setup_int_2(cpu, expires);
- break;
- }
- /* We might've missed our expiration time */
- *set_completion_time = rtc_time();
- if (*set_completion_time <= expires)
- return 1;
-
- /*
- * If an interrupt is already pending then its okay
- * if not then we failed
- */
- return mmtimer_int_pending(comparator);
-}
-
-static int mmtimer_disable_int(long nasid, int comparator)
-{
- switch (comparator) {
- case 0:
- nasid == -1 ? HUB_S((u64 *)LOCAL_MMR_ADDR(SH_RTC1_INT_ENABLE),
- 0UL) : REMOTE_HUB_S(nasid, SH_RTC1_INT_ENABLE, 0UL);
- break;
- case 1:
- nasid == -1 ? HUB_S((u64 *)LOCAL_MMR_ADDR(SH_RTC2_INT_ENABLE),
- 0UL) : REMOTE_HUB_S(nasid, SH_RTC2_INT_ENABLE, 0UL);
- break;
- case 2:
- nasid == -1 ? HUB_S((u64 *)LOCAL_MMR_ADDR(SH_RTC3_INT_ENABLE),
- 0UL) : REMOTE_HUB_S(nasid, SH_RTC3_INT_ENABLE, 0UL);
- break;
- default:
- return -EFAULT;
- }
- return 0;
-}
-
-#define COMPARATOR 1 /* The comparator to use */
-
-#define TIMER_OFF 0xbadcabLL /* Timer is not setup */
-#define TIMER_SET 0 /* Comparator is set for this timer */
-
-#define MMTIMER_INTERVAL_RETRY_INCREMENT_DEFAULT 40
-
-/* There is one of these for each timer */
-struct mmtimer {
- struct rb_node list;
- struct k_itimer *timer;
- int cpu;
-};
-
-struct mmtimer_node {
- spinlock_t lock ____cacheline_aligned;
- struct rb_root timer_head;
- struct rb_node *next;
- struct tasklet_struct tasklet;
-};
-static struct mmtimer_node *timers;
-
-static unsigned mmtimer_interval_retry_increment =
- MMTIMER_INTERVAL_RETRY_INCREMENT_DEFAULT;
-module_param(mmtimer_interval_retry_increment, uint, 0644);
-MODULE_PARM_DESC(mmtimer_interval_retry_increment,
- "RTC ticks to add to expiration on interval retry (default 40)");
-
-/*
- * Add a new mmtimer struct to the node's mmtimer list.
- * This function assumes the struct mmtimer_node is locked.
- */
-static void mmtimer_add_list(struct mmtimer *n)
-{
- int nodeid = n->timer->it.mmtimer.node;
- unsigned long expires = n->timer->it.mmtimer.expires;
- struct rb_node **link = &timers[nodeid].timer_head.rb_node;
- struct rb_node *parent = NULL;
- struct mmtimer *x;
-
- /*
- * Find the right place in the rbtree:
- */
- while (*link) {
- parent = *link;
- x = rb_entry(parent, struct mmtimer, list);
-
- if (expires < x->timer->it.mmtimer.expires)
- link = &(*link)->rb_left;
- else
- link = &(*link)->rb_right;
- }
-
- /*
- * Insert the timer to the rbtree and check whether it
- * replaces the first pending timer
- */
- rb_link_node(&n->list, parent, link);
- rb_insert_color(&n->list, &timers[nodeid].timer_head);
-
- if (!timers[nodeid].next || expires < rb_entry(timers[nodeid].next,
- struct mmtimer, list)->timer->it.mmtimer.expires)
- timers[nodeid].next = &n->list;
-}
-
-/*
- * Set the comparator for the next timer.
- * This function assumes the struct mmtimer_node is locked.
- */
-static void mmtimer_set_next_timer(int nodeid)
-{
- struct mmtimer_node *n = &timers[nodeid];
- struct mmtimer *x;
- struct k_itimer *t;
- u64 expires, exp, set_completion_time;
- int i;
-
-restart:
- if (n->next == NULL)
- return;
-
- x = rb_entry(n->next, struct mmtimer, list);
- t = x->timer;
- if (!t->it.mmtimer.incr) {
- /* Not an interval timer */
- if (!mmtimer_setup(x->cpu, COMPARATOR,
- t->it.mmtimer.expires,
- &set_completion_time)) {
- /* Late setup, fire now */
- tasklet_schedule(&n->tasklet);
- }
- return;
- }
-
- /* Interval timer */
- i = 0;
- expires = exp = t->it.mmtimer.expires;
- while (!mmtimer_setup(x->cpu, COMPARATOR, expires,
- &set_completion_time)) {
- int to;
-
- i++;
- expires = set_completion_time +
- mmtimer_interval_retry_increment + (1 << i);
- /* Calculate overruns as we go. */
- to = ((u64)(expires - exp) / t->it.mmtimer.incr);
- if (to) {
- t->it_overrun += to;
- t->it.mmtimer.expires += t->it.mmtimer.incr * to;
- exp = t->it.mmtimer.expires;
- }
- if (i > 20) {
- printk(KERN_ALERT "mmtimer: cannot reschedule timer\n");
- t->it.mmtimer.clock = TIMER_OFF;
- n->next = rb_next(&x->list);
- rb_erase(&x->list, &n->timer_head);
- kfree(x);
- goto restart;
- }
- }
-}
-
-/**
- * mmtimer_ioctl - ioctl interface for /dev/mmtimer
- * @file: file structure for the device
- * @cmd: command to execute
- * @arg: optional argument to command
- *
- * Executes the command specified by @cmd. Returns 0 for success, < 0 for
- * failure.
- *
- * Valid commands:
- *
- * %MMTIMER_GETOFFSET - Should return the offset (relative to the start
- * of the page where the registers are mapped) for the counter in question.
- *
- * %MMTIMER_GETRES - Returns the resolution of the clock in femto (10^-15)
- * seconds
- *
- * %MMTIMER_GETFREQ - Copies the frequency of the clock in Hz to the address
- * specified by @arg
- *
- * %MMTIMER_GETBITS - Returns the number of bits in the clock's counter
- *
- * %MMTIMER_MMAPAVAIL - Returns 1 if the registers can be mmap'd into userspace
- *
- * %MMTIMER_GETCOUNTER - Gets the current value in the counter and places it
- * in the address specified by @arg.
- */
-static long mmtimer_ioctl(struct file *file, unsigned int cmd,
- unsigned long arg)
-{
- int ret = 0;
-
- mutex_lock(&mmtimer_mutex);
-
- switch (cmd) {
- case MMTIMER_GETOFFSET: /* offset of the counter */
- /*
- * SN RTC registers are on their own 64k page
- */
- if(PAGE_SIZE <= (1 << 16))
- ret = (((long)RTC_COUNTER_ADDR) & (PAGE_SIZE-1)) / 8;
- else
- ret = -ENOSYS;
- break;
-
- case MMTIMER_GETRES: /* resolution of the clock in 10^-15 s */
- if(copy_to_user((unsigned long __user *)arg,
- &mmtimer_femtoperiod, sizeof(unsigned long)))
- ret = -EFAULT;
- break;
-
- case MMTIMER_GETFREQ: /* frequency in Hz */
- if(copy_to_user((unsigned long __user *)arg,
- &sn_rtc_cycles_per_second,
- sizeof(unsigned long)))
- ret = -EFAULT;
- break;
-
- case MMTIMER_GETBITS: /* number of bits in the clock */
- ret = RTC_BITS;
- break;
-
- case MMTIMER_MMAPAVAIL: /* can we mmap the clock into userspace? */
- ret = (PAGE_SIZE <= (1 << 16)) ? 1 : 0;
- break;
-
- case MMTIMER_GETCOUNTER:
- if(copy_to_user((unsigned long __user *)arg,
- RTC_COUNTER_ADDR, sizeof(unsigned long)))
- ret = -EFAULT;
- break;
- default:
- ret = -ENOTTY;
- break;
- }
- mutex_unlock(&mmtimer_mutex);
- return ret;
-}
-
-/**
- * mmtimer_mmap - maps the clock's registers into userspace
- * @file: file structure for the device
- * @vma: VMA to map the registers into
- *
- * Calls remap_pfn_range() to map the clock's registers into
- * the calling process' address space.
- */
-static int mmtimer_mmap(struct file *file, struct vm_area_struct *vma)
-{
- unsigned long mmtimer_addr;
-
- if (vma->vm_end - vma->vm_start != PAGE_SIZE)
- return -EINVAL;
-
- if (vma->vm_flags & VM_WRITE)
- return -EPERM;
-
- if (PAGE_SIZE > (1 << 16))
- return -ENOSYS;
-
- vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
-
- mmtimer_addr = __pa(RTC_COUNTER_ADDR);
- mmtimer_addr &= ~(PAGE_SIZE - 1);
- mmtimer_addr &= 0xfffffffffffffffUL;
-
- if (remap_pfn_range(vma, vma->vm_start, mmtimer_addr >> PAGE_SHIFT,
- PAGE_SIZE, vma->vm_page_prot)) {
- printk(KERN_ERR "remap_pfn_range failed in mmtimer.c\n");
- return -EAGAIN;
- }
-
- return 0;
-}
-
-static struct miscdevice mmtimer_miscdev = {
- .minor = SGI_MMTIMER,
- .name = MMTIMER_NAME,
- .fops = &mmtimer_fops
-};
-
-static struct timespec sgi_clock_offset;
-static int sgi_clock_period;
-
-/*
- * Posix Timer Interface
- */
-
-static struct timespec sgi_clock_offset;
-static int sgi_clock_period;
-
-static int sgi_clock_get(clockid_t clockid, struct timespec64 *tp)
-{
- u64 nsec;
-
- nsec = rtc_time() * sgi_clock_period
- + sgi_clock_offset.tv_nsec;
- *tp = ns_to_timespec64(nsec);
- tp->tv_sec += sgi_clock_offset.tv_sec;
- return 0;
-};
-
-static int sgi_clock_set(const clockid_t clockid, const struct timespec64 *tp)
-{
-
- u64 nsec;
- u32 rem;
-
- nsec = rtc_time() * sgi_clock_period;
-
- sgi_clock_offset.tv_sec = tp->tv_sec - div_u64_rem(nsec, NSEC_PER_SEC, &rem);
-
- if (rem <= tp->tv_nsec)
- sgi_clock_offset.tv_nsec = tp->tv_sec - rem;
- else {
- sgi_clock_offset.tv_nsec = tp->tv_sec + NSEC_PER_SEC - rem;
- sgi_clock_offset.tv_sec--;
- }
- return 0;
-}
-
-/**
- * mmtimer_interrupt - timer interrupt handler
- * @irq: irq received
- * @dev_id: device the irq came from
- *
- * Called when one of the comarators matches the counter, This
- * routine will send signals to processes that have requested
- * them.
- *
- * This interrupt is run in an interrupt context
- * by the SHUB. It is therefore safe to locally access SHub
- * registers.
- */
-static irqreturn_t
-mmtimer_interrupt(int irq, void *dev_id)
-{
- unsigned long expires = 0;
- int result = IRQ_NONE;
- unsigned indx = cpu_to_node(smp_processor_id());
- struct mmtimer *base;
-
- spin_lock(&timers[indx].lock);
- base = rb_entry(timers[indx].next, struct mmtimer, list);
- if (base == NULL) {
- spin_unlock(&timers[indx].lock);
- return result;
- }
-
- if (base->cpu == smp_processor_id()) {
- if (base->timer)
- expires = base->timer->it.mmtimer.expires;
- /* expires test won't work with shared irqs */
- if ((mmtimer_int_pending(COMPARATOR) > 0) ||
- (expires && (expires <= rtc_time()))) {
- mmtimer_clr_int_pending(COMPARATOR);
- tasklet_schedule(&timers[indx].tasklet);
- result = IRQ_HANDLED;
- }
- }
- spin_unlock(&timers[indx].lock);
- return result;
-}
-
-static void mmtimer_tasklet(unsigned long data)
-{
- int nodeid = data;
- struct mmtimer_node *mn = &timers[nodeid];
- struct mmtimer *x;
- struct k_itimer *t;
- unsigned long flags;
-
- /* Send signal and deal with periodic signals */
- spin_lock_irqsave(&mn->lock, flags);
- if (!mn->next)
- goto out;
-
- x = rb_entry(mn->next, struct mmtimer, list);
- t = x->timer;
-
- if (t->it.mmtimer.clock == TIMER_OFF)
- goto out;
-
- t->it_overrun = 0;
-
- mn->next = rb_next(&x->list);
- rb_erase(&x->list, &mn->timer_head);
-
- if (posix_timer_event(t, 0) != 0)
- t->it_overrun++;
-
- if(t->it.mmtimer.incr) {
- t->it.mmtimer.expires += t->it.mmtimer.incr;
- mmtimer_add_list(x);
- } else {
- /* Ensure we don't false trigger in mmtimer_interrupt */
- t->it.mmtimer.clock = TIMER_OFF;
- t->it.mmtimer.expires = 0;
- kfree(x);
- }
- /* Set comparator for next timer, if there is one */
- mmtimer_set_next_timer(nodeid);
-
- t->it_overrun_last = t->it_overrun;
-out:
- spin_unlock_irqrestore(&mn->lock, flags);
-}
-
-static int sgi_timer_create(struct k_itimer *timer)
-{
- /* Insure that a newly created timer is off */
- timer->it.mmtimer.clock = TIMER_OFF;
- return 0;
-}
-
-/* This does not really delete a timer. It just insures
- * that the timer is not active
- *
- * Assumption: it_lock is already held with irq's disabled
- */
-static int sgi_timer_del(struct k_itimer *timr)
-{
- cnodeid_t nodeid = timr->it.mmtimer.node;
- unsigned long irqflags;
-
- spin_lock_irqsave(&timers[nodeid].lock, irqflags);
- if (timr->it.mmtimer.clock != TIMER_OFF) {
- unsigned long expires = timr->it.mmtimer.expires;
- struct rb_node *n = timers[nodeid].timer_head.rb_node;
- struct mmtimer *uninitialized_var(t);
- int r = 0;
-
- timr->it.mmtimer.clock = TIMER_OFF;
- timr->it.mmtimer.expires = 0;
-
- while (n) {
- t = rb_entry(n, struct mmtimer, list);
- if (t->timer == timr)
- break;
-
- if (expires < t->timer->it.mmtimer.expires)
- n = n->rb_left;
- else
- n = n->rb_right;
- }
-
- if (!n) {
- spin_unlock_irqrestore(&timers[nodeid].lock, irqflags);
- return 0;
- }
-
- if (timers[nodeid].next == n) {
- timers[nodeid].next = rb_next(n);
- r = 1;
- }
-
- rb_erase(n, &timers[nodeid].timer_head);
- kfree(t);
-
- if (r) {
- mmtimer_disable_int(cnodeid_to_nasid(nodeid),
- COMPARATOR);
- mmtimer_set_next_timer(nodeid);
- }
- }
- spin_unlock_irqrestore(&timers[nodeid].lock, irqflags);
- return 0;
-}
-
-/* Assumption: it_lock is already held with irq's disabled */
-static void sgi_timer_get(struct k_itimer *timr, struct itimerspec64 *cur_setting)
-{
-
- if (timr->it.mmtimer.clock == TIMER_OFF) {
- cur_setting->it_interval.tv_nsec = 0;
- cur_setting->it_interval.tv_sec = 0;
- cur_setting->it_value.tv_nsec = 0;
- cur_setting->it_value.tv_sec =0;
- return;
- }
-
- cur_setting->it_interval = ns_to_timespec64(timr->it.mmtimer.incr * sgi_clock_period);
- cur_setting->it_value = ns_to_timespec64((timr->it.mmtimer.expires - rtc_time()) * sgi_clock_period);
-}
-
-
-static int sgi_timer_set(struct k_itimer *timr, int flags,
- struct itimerspec64 *new_setting,
- struct itimerspec64 *old_setting)
-{
- unsigned long when, period, irqflags;
- int err = 0;
- cnodeid_t nodeid;
- struct mmtimer *base;
- struct rb_node *n;
-
- if (old_setting)
- sgi_timer_get(timr, old_setting);
-
- sgi_timer_del(timr);
- when = timespec64_to_ns(&new_setting->it_value);
- period = timespec64_to_ns(&new_setting->it_interval);
-
- if (when == 0)
- /* Clear timer */
- return 0;
-
- base = kmalloc(sizeof(struct mmtimer), GFP_KERNEL);
- if (base == NULL)
- return -ENOMEM;
-
- if (flags & TIMER_ABSTIME) {
- struct timespec64 n;
- unsigned long now;
-
- getnstimeofday64(&n);
- now = timespec64_to_ns(&n);
- if (when > now)
- when -= now;
- else
- /* Fire the timer immediately */
- when = 0;
- }
-
- /*
- * Convert to sgi clock period. Need to keep rtc_time() as near as possible
- * to getnstimeofday() in order to be as faithful as possible to the time
- * specified.
- */
- when = (when + sgi_clock_period - 1) / sgi_clock_period + rtc_time();
- period = (period + sgi_clock_period - 1) / sgi_clock_period;
-
- /*
- * We are allocating a local SHub comparator. If we would be moved to another
- * cpu then another SHub may be local to us. Prohibit that by switching off
- * preemption.
- */
- preempt_disable();
-
- nodeid = cpu_to_node(smp_processor_id());
-
- /* Lock the node timer structure */
- spin_lock_irqsave(&timers[nodeid].lock, irqflags);
-
- base->timer = timr;
- base->cpu = smp_processor_id();
-
- timr->it.mmtimer.clock = TIMER_SET;
- timr->it.mmtimer.node = nodeid;
- timr->it.mmtimer.incr = period;
- timr->it.mmtimer.expires = when;
-
- n = timers[nodeid].next;
-
- /* Add the new struct mmtimer to node's timer list */
- mmtimer_add_list(base);
-
- if (timers[nodeid].next == n) {
- /* No need to reprogram comparator for now */
- spin_unlock_irqrestore(&timers[nodeid].lock, irqflags);
- preempt_enable();
- return err;
- }
-
- /* We need to reprogram the comparator */
- if (n)
- mmtimer_disable_int(cnodeid_to_nasid(nodeid), COMPARATOR);
-
- mmtimer_set_next_timer(nodeid);
-
- /* Unlock the node timer structure */
- spin_unlock_irqrestore(&timers[nodeid].lock, irqflags);
-
- preempt_enable();
-
- return err;
-}
-
-static int sgi_clock_getres(const clockid_t which_clock, struct timespec64 *tp)
-{
- tp->tv_sec = 0;
- tp->tv_nsec = sgi_clock_period;
- return 0;
-}
-
-static struct k_clock sgi_clock = {
- .clock_set = sgi_clock_set,
- .clock_get = sgi_clock_get,
- .clock_getres = sgi_clock_getres,
- .timer_create = sgi_timer_create,
- .timer_set = sgi_timer_set,
- .timer_del = sgi_timer_del,
- .timer_get = sgi_timer_get
-};
-
-/**
- * mmtimer_init - device initialization routine
- *
- * Does initial setup for the mmtimer device.
- */
-static int __init mmtimer_init(void)
-{
- cnodeid_t node, maxn = -1;
-
- if (!ia64_platform_is("sn2"))
- return 0;
-
- /*
- * Sanity check the cycles/sec variable
- */
- if (sn_rtc_cycles_per_second < 100000) {
- printk(KERN_ERR "%s: unable to determine clock frequency\n",
- MMTIMER_NAME);
- goto out1;
- }
-
- mmtimer_femtoperiod = ((unsigned long)1E15 + sn_rtc_cycles_per_second /
- 2) / sn_rtc_cycles_per_second;
-
- if (request_irq(SGI_MMTIMER_VECTOR, mmtimer_interrupt, IRQF_PERCPU, MMTIMER_NAME, NULL)) {
- printk(KERN_WARNING "%s: unable to allocate interrupt.",
- MMTIMER_NAME);
- goto out1;
- }
-
- if (misc_register(&mmtimer_miscdev)) {
- printk(KERN_ERR "%s: failed to register device\n",
- MMTIMER_NAME);
- goto out2;
- }
-
- /* Get max numbered node, calculate slots needed */
- for_each_online_node(node) {
- maxn = node;
- }
- maxn++;
-
- /* Allocate list of node ptrs to mmtimer_t's */
- timers = kzalloc(sizeof(struct mmtimer_node)*maxn, GFP_KERNEL);
- if (!timers) {
- printk(KERN_ERR "%s: failed to allocate memory for device\n",
- MMTIMER_NAME);
- goto out3;
- }
-
- /* Initialize struct mmtimer's for each online node */
- for_each_online_node(node) {
- spin_lock_init(&timers[node].lock);
- tasklet_init(&timers[node].tasklet, mmtimer_tasklet,
- (unsigned long) node);
- }
-
- sgi_clock_period = NSEC_PER_SEC / sn_rtc_cycles_per_second;
- posix_timers_register_clock(CLOCK_SGI_CYCLE, &sgi_clock);
-
- printk(KERN_INFO "%s: v%s, %ld MHz\n", MMTIMER_DESC, MMTIMER_VERSION,
- sn_rtc_cycles_per_second/(unsigned long)1E6);
-
- return 0;
-
-out3:
- misc_deregister(&mmtimer_miscdev);
-out2:
- free_irq(SGI_MMTIMER_VECTOR, NULL);
-out1:
- return -1;
-}
-
-module_init(mmtimer_init);
diff --git a/drivers/char/pcmcia/cm4040_cs.c b/drivers/char/pcmcia/cm4040_cs.c
index d4dbd8d8e524..382c864814d9 100644
--- a/drivers/char/pcmcia/cm4040_cs.c
+++ b/drivers/char/pcmcia/cm4040_cs.c
@@ -374,7 +374,7 @@ static ssize_t cm4040_write(struct file *filp, const char __user *buf,
rc = write_sync_reg(SCR_HOST_TO_READER_START, dev);
if (rc <= 0) {
- DEBUGP(5, dev, "write_sync_reg c=%.2Zx\n", rc);
+ DEBUGP(5, dev, "write_sync_reg c=%.2zx\n", rc);
DEBUGP(2, dev, "<- cm4040_write (failed)\n");
if (rc == -ERESTARTSYS)
return rc;
@@ -387,7 +387,7 @@ static ssize_t cm4040_write(struct file *filp, const char __user *buf,
for (i = 0; i < bytes_to_write; i++) {
rc = wait_for_bulk_out_ready(dev);
if (rc <= 0) {
- DEBUGP(5, dev, "wait_for_bulk_out_ready rc=%.2Zx\n",
+ DEBUGP(5, dev, "wait_for_bulk_out_ready rc=%.2zx\n",
rc);
DEBUGP(2, dev, "<- cm4040_write (failed)\n");
if (rc == -ERESTARTSYS)
@@ -403,7 +403,7 @@ static ssize_t cm4040_write(struct file *filp, const char __user *buf,
rc = write_sync_reg(SCR_HOST_TO_READER_DONE, dev);
if (rc <= 0) {
- DEBUGP(5, dev, "write_sync_reg c=%.2Zx\n", rc);
+ DEBUGP(5, dev, "write_sync_reg c=%.2zx\n", rc);
DEBUGP(2, dev, "<- cm4040_write (failed)\n");
if (rc == -ERESTARTSYS)
return rc;
diff --git a/drivers/char/random.c b/drivers/char/random.c
index 0ab024918907..01a260f67437 100644
--- a/drivers/char/random.c
+++ b/drivers/char/random.c
@@ -1,6 +1,9 @@
/*
* random.c -- A strong random number generator
*
+ * Copyright (C) 2017 Jason A. Donenfeld <Jason@zx2c4.com>. All
+ * Rights Reserved.
+ *
* Copyright Matt Mackall <mpm@selenic.com>, 2003, 2004, 2005
*
* Copyright Theodore Ts'o, 1994, 1995, 1996, 1997, 1998, 1999. All
@@ -762,6 +765,8 @@ static DECLARE_WAIT_QUEUE_HEAD(crng_init_wait);
static struct crng_state **crng_node_pool __read_mostly;
#endif
+static void invalidate_batched_entropy(void);
+
static void crng_initialize(struct crng_state *crng)
{
int i;
@@ -798,12 +803,13 @@ static int crng_fast_load(const char *cp, size_t len)
p[crng_init_cnt % CHACHA20_KEY_SIZE] ^= *cp;
cp++; crng_init_cnt++; len--;
}
+ spin_unlock_irqrestore(&primary_crng.lock, flags);
if (crng_init_cnt >= CRNG_INIT_CNT_THRESH) {
+ invalidate_batched_entropy();
crng_init = 1;
wake_up_interruptible(&crng_init_wait);
pr_notice("random: fast init done\n");
}
- spin_unlock_irqrestore(&primary_crng.lock, flags);
return 1;
}
@@ -835,13 +841,14 @@ static void crng_reseed(struct crng_state *crng, struct entropy_store *r)
}
memzero_explicit(&buf, sizeof(buf));
crng->init_time = jiffies;
+ spin_unlock_irqrestore(&primary_crng.lock, flags);
if (crng == &primary_crng && crng_init < 2) {
+ invalidate_batched_entropy();
crng_init = 2;
process_random_ready_list();
wake_up_interruptible(&crng_init_wait);
pr_notice("random: crng init done\n");
}
- spin_unlock_irqrestore(&primary_crng.lock, flags);
}
static inline void crng_wait_ready(void)
@@ -1097,12 +1104,16 @@ static void add_interrupt_bench(cycles_t start)
static __u32 get_reg(struct fast_pool *f, struct pt_regs *regs)
{
__u32 *ptr = (__u32 *) regs;
+ unsigned int idx;
if (regs == NULL)
return 0;
- if (f->reg_idx >= sizeof(struct pt_regs) / sizeof(__u32))
- f->reg_idx = 0;
- return *(ptr + f->reg_idx++);
+ idx = READ_ONCE(f->reg_idx);
+ if (idx >= sizeof(struct pt_regs) / sizeof(__u32))
+ idx = 0;
+ ptr += idx++;
+ WRITE_ONCE(f->reg_idx, idx);
+ return *ptr;
}
void add_interrupt_randomness(int irq, int irq_flags)
@@ -2019,6 +2030,7 @@ struct batched_entropy {
};
unsigned int position;
};
+static rwlock_t batched_entropy_reset_lock = __RW_LOCK_UNLOCKED(batched_entropy_reset_lock);
/*
* Get a random word for internal kernel use only. The quality of the random
@@ -2029,6 +2041,8 @@ static DEFINE_PER_CPU(struct batched_entropy, batched_entropy_u64);
u64 get_random_u64(void)
{
u64 ret;
+ bool use_lock = READ_ONCE(crng_init) < 2;
+ unsigned long flags = 0;
struct batched_entropy *batch;
#if BITS_PER_LONG == 64
@@ -2041,11 +2055,15 @@ u64 get_random_u64(void)
#endif
batch = &get_cpu_var(batched_entropy_u64);
+ if (use_lock)
+ read_lock_irqsave(&batched_entropy_reset_lock, flags);
if (batch->position % ARRAY_SIZE(batch->entropy_u64) == 0) {
extract_crng((u8 *)batch->entropy_u64);
batch->position = 0;
}
ret = batch->entropy_u64[batch->position++];
+ if (use_lock)
+ read_unlock_irqrestore(&batched_entropy_reset_lock, flags);
put_cpu_var(batched_entropy_u64);
return ret;
}
@@ -2055,22 +2073,45 @@ static DEFINE_PER_CPU(struct batched_entropy, batched_entropy_u32);
u32 get_random_u32(void)
{
u32 ret;
+ bool use_lock = READ_ONCE(crng_init) < 2;
+ unsigned long flags = 0;
struct batched_entropy *batch;
if (arch_get_random_int(&ret))
return ret;
batch = &get_cpu_var(batched_entropy_u32);
+ if (use_lock)
+ read_lock_irqsave(&batched_entropy_reset_lock, flags);
if (batch->position % ARRAY_SIZE(batch->entropy_u32) == 0) {
extract_crng((u8 *)batch->entropy_u32);
batch->position = 0;
}
ret = batch->entropy_u32[batch->position++];
+ if (use_lock)
+ read_unlock_irqrestore(&batched_entropy_reset_lock, flags);
put_cpu_var(batched_entropy_u32);
return ret;
}
EXPORT_SYMBOL(get_random_u32);
+/* It's important to invalidate all potential batched entropy that might
+ * be stored before the crng is initialized, which we can do lazily by
+ * simply resetting the counter to zero so that it's re-extracted on the
+ * next usage. */
+static void invalidate_batched_entropy(void)
+{
+ int cpu;
+ unsigned long flags;
+
+ write_lock_irqsave(&batched_entropy_reset_lock, flags);
+ for_each_possible_cpu (cpu) {
+ per_cpu_ptr(&batched_entropy_u32, cpu)->position = 0;
+ per_cpu_ptr(&batched_entropy_u64, cpu)->position = 0;
+ }
+ write_unlock_irqrestore(&batched_entropy_reset_lock, flags);
+}
+
/**
* randomize_page - Generate a random, page aligned address
* @start: The smallest acceptable address the caller will take.
diff --git a/drivers/char/tpm/tpm_crb.c b/drivers/char/tpm/tpm_crb.c
index b917b9d5f710..c378c7b15d49 100644
--- a/drivers/char/tpm/tpm_crb.c
+++ b/drivers/char/tpm/tpm_crb.c
@@ -27,10 +27,9 @@
#define ACPI_SIG_TPM2 "TPM2"
-static const u8 CRB_ACPI_START_UUID[] = {
- /* 0000 */ 0xAB, 0x6C, 0xBF, 0x6B, 0x63, 0x54, 0x14, 0x47,
- /* 0008 */ 0xB7, 0xCD, 0xF0, 0x20, 0x3C, 0x03, 0x68, 0xD4
-};
+static const guid_t crb_acpi_start_guid =
+ GUID_INIT(0x6BBF6CAB, 0x5463, 0x4714,
+ 0xB7, 0xCD, 0xF0, 0x20, 0x3C, 0x03, 0x68, 0xD4);
enum crb_defaults {
CRB_ACPI_START_REVISION_ID = 1,
@@ -266,7 +265,7 @@ static int crb_do_acpi_start(struct tpm_chip *chip)
int rc;
obj = acpi_evaluate_dsm(chip->acpi_dev_handle,
- CRB_ACPI_START_UUID,
+ &crb_acpi_start_guid,
CRB_ACPI_START_REVISION_ID,
CRB_ACPI_START_INDEX,
NULL);
diff --git a/drivers/char/tpm/tpm_ppi.c b/drivers/char/tpm/tpm_ppi.c
index 692a2c6ae036..86dd8521feef 100644
--- a/drivers/char/tpm/tpm_ppi.c
+++ b/drivers/char/tpm/tpm_ppi.c
@@ -32,20 +32,16 @@
#define PPI_VS_REQ_START 128
#define PPI_VS_REQ_END 255
-static const u8 tpm_ppi_uuid[] = {
- 0xA6, 0xFA, 0xDD, 0x3D,
- 0x1B, 0x36,
- 0xB4, 0x4E,
- 0xA4, 0x24,
- 0x8D, 0x10, 0x08, 0x9D, 0x16, 0x53
-};
+static const guid_t tpm_ppi_guid =
+ GUID_INIT(0x3DDDFAA6, 0x361B, 0x4EB4,
+ 0xA4, 0x24, 0x8D, 0x10, 0x08, 0x9D, 0x16, 0x53);
static inline union acpi_object *
tpm_eval_dsm(acpi_handle ppi_handle, int func, acpi_object_type type,
union acpi_object *argv4)
{
BUG_ON(!ppi_handle);
- return acpi_evaluate_dsm_typed(ppi_handle, tpm_ppi_uuid,
+ return acpi_evaluate_dsm_typed(ppi_handle, &tpm_ppi_guid,
TPM_PPI_REVISION_ID,
func, argv4, type);
}
@@ -107,7 +103,7 @@ static ssize_t tpm_store_ppi_request(struct device *dev,
* is updated with function index from SUBREQ to SUBREQ2 since PPI
* version 1.1
*/
- if (acpi_check_dsm(chip->acpi_dev_handle, tpm_ppi_uuid,
+ if (acpi_check_dsm(chip->acpi_dev_handle, &tpm_ppi_guid,
TPM_PPI_REVISION_ID, 1 << TPM_PPI_FN_SUBREQ2))
func = TPM_PPI_FN_SUBREQ2;
@@ -268,7 +264,7 @@ static ssize_t show_ppi_operations(acpi_handle dev_handle, char *buf, u32 start,
"User not required",
};
- if (!acpi_check_dsm(dev_handle, tpm_ppi_uuid, TPM_PPI_REVISION_ID,
+ if (!acpi_check_dsm(dev_handle, &tpm_ppi_guid, TPM_PPI_REVISION_ID,
1 << TPM_PPI_FN_GETOPR))
return -EPERM;
@@ -341,12 +337,12 @@ void tpm_add_ppi(struct tpm_chip *chip)
if (!chip->acpi_dev_handle)
return;
- if (!acpi_check_dsm(chip->acpi_dev_handle, tpm_ppi_uuid,
+ if (!acpi_check_dsm(chip->acpi_dev_handle, &tpm_ppi_guid,
TPM_PPI_REVISION_ID, 1 << TPM_PPI_FN_VERSION))
return;
/* Cache PPI version string. */
- obj = acpi_evaluate_dsm_typed(chip->acpi_dev_handle, tpm_ppi_uuid,
+ obj = acpi_evaluate_dsm_typed(chip->acpi_dev_handle, &tpm_ppi_guid,
TPM_PPI_REVISION_ID, TPM_PPI_FN_VERSION,
NULL, ACPI_TYPE_STRING);
if (obj) {
diff --git a/drivers/clk/meson/Kconfig b/drivers/clk/meson/Kconfig
index 19480bcc7046..2f29ee1a4d00 100644
--- a/drivers/clk/meson/Kconfig
+++ b/drivers/clk/meson/Kconfig
@@ -14,6 +14,7 @@ config COMMON_CLK_MESON8B
config COMMON_CLK_GXBB
bool
depends on COMMON_CLK_AMLOGIC
+ select RESET_CONTROLLER
help
Support for the clock controller on AmLogic S905 devices, aka gxbb.
Say Y if you want peripherals and CPU frequency scaling to work.
diff --git a/drivers/clk/sunxi-ng/Kconfig b/drivers/clk/sunxi-ng/Kconfig
index b0d551a8efe4..eb89c7801f00 100644
--- a/drivers/clk/sunxi-ng/Kconfig
+++ b/drivers/clk/sunxi-ng/Kconfig
@@ -156,6 +156,7 @@ config SUN8I_R_CCU
bool "Support for Allwinner SoCs' PRCM CCUs"
select SUNXI_CCU_DIV
select SUNXI_CCU_GATE
+ select SUNXI_CCU_MP
default MACH_SUN8I || (ARCH_SUNXI && ARM64)
endif
diff --git a/drivers/clk/sunxi-ng/ccu-sun50i-a64.h b/drivers/clk/sunxi-ng/ccu-sun50i-a64.h
index 9b3cd24b78d2..061b6fbb4f95 100644
--- a/drivers/clk/sunxi-ng/ccu-sun50i-a64.h
+++ b/drivers/clk/sunxi-ng/ccu-sun50i-a64.h
@@ -31,7 +31,9 @@
#define CLK_PLL_VIDEO0_2X 8
#define CLK_PLL_VE 9
#define CLK_PLL_DDR0 10
-#define CLK_PLL_PERIPH0 11
+
+/* PLL_PERIPH0 exported for PRCM */
+
#define CLK_PLL_PERIPH0_2X 12
#define CLK_PLL_PERIPH1 13
#define CLK_PLL_PERIPH1_2X 14
diff --git a/drivers/clk/sunxi-ng/ccu-sun5i.c b/drivers/clk/sunxi-ng/ccu-sun5i.c
index 5c476f966a72..5372bf8be5e6 100644
--- a/drivers/clk/sunxi-ng/ccu-sun5i.c
+++ b/drivers/clk/sunxi-ng/ccu-sun5i.c
@@ -243,7 +243,7 @@ static SUNXI_CCU_GATE(ahb_ss_clk, "ahb-ss", "ahb",
static SUNXI_CCU_GATE(ahb_dma_clk, "ahb-dma", "ahb",
0x060, BIT(6), 0);
static SUNXI_CCU_GATE(ahb_bist_clk, "ahb-bist", "ahb",
- 0x060, BIT(6), 0);
+ 0x060, BIT(7), 0);
static SUNXI_CCU_GATE(ahb_mmc0_clk, "ahb-mmc0", "ahb",
0x060, BIT(8), 0);
static SUNXI_CCU_GATE(ahb_mmc1_clk, "ahb-mmc1", "ahb",
diff --git a/drivers/clk/sunxi-ng/ccu-sun6i-a31.c b/drivers/clk/sunxi-ng/ccu-sun6i-a31.c
index 89e68d29bf45..df97e25aec76 100644
--- a/drivers/clk/sunxi-ng/ccu-sun6i-a31.c
+++ b/drivers/clk/sunxi-ng/ccu-sun6i-a31.c
@@ -556,7 +556,7 @@ static SUNXI_CCU_M_WITH_MUX_GATE(lcd0_ch1_clk, "lcd0-ch1", lcd_ch1_parents,
0x12c, 0, 4, 24, 3, BIT(31),
CLK_SET_RATE_PARENT);
static SUNXI_CCU_M_WITH_MUX_GATE(lcd1_ch1_clk, "lcd1-ch1", lcd_ch1_parents,
- 0x12c, 0, 4, 24, 3, BIT(31),
+ 0x130, 0, 4, 24, 3, BIT(31),
CLK_SET_RATE_PARENT);
static const char * const csi_sclk_parents[] = { "pll-video0", "pll-video1",
diff --git a/drivers/clk/sunxi-ng/ccu-sun8i-h3.h b/drivers/clk/sunxi-ng/ccu-sun8i-h3.h
index 85973d1e8165..1b4baea37d81 100644
--- a/drivers/clk/sunxi-ng/ccu-sun8i-h3.h
+++ b/drivers/clk/sunxi-ng/ccu-sun8i-h3.h
@@ -29,7 +29,9 @@
#define CLK_PLL_VIDEO 6
#define CLK_PLL_VE 7
#define CLK_PLL_DDR 8
-#define CLK_PLL_PERIPH0 9
+
+/* PLL_PERIPH0 exported for PRCM */
+
#define CLK_PLL_PERIPH0_2X 10
#define CLK_PLL_GPU 11
#define CLK_PLL_PERIPH1 12
diff --git a/drivers/clk/sunxi-ng/ccu-sun8i-v3s.c b/drivers/clk/sunxi-ng/ccu-sun8i-v3s.c
index e58706b40ae9..6297add857b5 100644
--- a/drivers/clk/sunxi-ng/ccu-sun8i-v3s.c
+++ b/drivers/clk/sunxi-ng/ccu-sun8i-v3s.c
@@ -537,7 +537,7 @@ static struct ccu_reset_map sun8i_v3s_ccu_resets[] = {
[RST_BUS_EMAC] = { 0x2c0, BIT(17) },
[RST_BUS_HSTIMER] = { 0x2c0, BIT(19) },
[RST_BUS_SPI0] = { 0x2c0, BIT(20) },
- [RST_BUS_OTG] = { 0x2c0, BIT(23) },
+ [RST_BUS_OTG] = { 0x2c0, BIT(24) },
[RST_BUS_EHCI0] = { 0x2c0, BIT(26) },
[RST_BUS_OHCI0] = { 0x2c0, BIT(29) },
diff --git a/drivers/clocksource/Kconfig b/drivers/clocksource/Kconfig
index 545d541ae20e..88818a43d6e9 100644
--- a/drivers/clocksource/Kconfig
+++ b/drivers/clocksource/Kconfig
@@ -1,22 +1,16 @@
menu "Clock Source drivers"
depends on !ARCH_USES_GETTIMEOFFSET
-config CLKSRC_OF
+config TIMER_OF
bool
- select CLKSRC_PROBE
-
-config CLKEVT_OF
- bool
- select CLKEVT_PROBE
-
-config CLKSRC_ACPI
- bool
- select CLKSRC_PROBE
+ depends on GENERIC_CLOCKEVENTS
+ select TIMER_PROBE
-config CLKSRC_PROBE
+config TIMER_ACPI
bool
+ select TIMER_PROBE
-config CLKEVT_PROBE
+config TIMER_PROBE
bool
config CLKSRC_I8253
@@ -65,14 +59,14 @@ config DW_APB_TIMER
config DW_APB_TIMER_OF
bool
select DW_APB_TIMER
- select CLKSRC_OF
+ select TIMER_OF
config FTTMR010_TIMER
bool "Faraday Technology timer driver" if COMPILE_TEST
depends on GENERIC_CLOCKEVENTS
depends on HAS_IOMEM
select CLKSRC_MMIO
- select CLKSRC_OF
+ select TIMER_OF
select MFD_SYSCON
help
Enables support for the Faraday Technology timer block
@@ -81,7 +75,7 @@ config FTTMR010_TIMER
config ROCKCHIP_TIMER
bool "Rockchip timer driver" if COMPILE_TEST
depends on ARM || ARM64
- select CLKSRC_OF
+ select TIMER_OF
select CLKSRC_MMIO
help
Enables the support for the rockchip timer driver.
@@ -89,7 +83,7 @@ config ROCKCHIP_TIMER
config ARMADA_370_XP_TIMER
bool "Armada 370 and XP timer driver" if COMPILE_TEST
depends on ARM
- select CLKSRC_OF
+ select TIMER_OF
select CLKSRC_MMIO
help
Enables the support for the Armada 370 and XP timer driver.
@@ -104,7 +98,7 @@ config MESON6_TIMER
config ORION_TIMER
bool "Orion timer driver" if COMPILE_TEST
depends on ARM
- select CLKSRC_OF
+ select TIMER_OF
select CLKSRC_MMIO
help
Enables the support for the Orion timer driver
@@ -114,6 +108,7 @@ config SUN4I_TIMER
depends on GENERIC_CLOCKEVENTS
depends on HAS_IOMEM
select CLKSRC_MMIO
+ select TIMER_OF
help
Enables support for the Sun4i timer.
@@ -148,7 +143,7 @@ config ASM9260_TIMER
bool "ASM9260 timer driver" if COMPILE_TEST
depends on GENERIC_CLOCKEVENTS
select CLKSRC_MMIO
- select CLKSRC_OF
+ select TIMER_OF
help
Enables support for the ASM9260 timer.
@@ -188,13 +183,6 @@ config ATLAS7_TIMER
help
Enables support for the Atlas7 timer.
-config MOXART_TIMER
- bool "Moxart timer driver" if COMPILE_TEST
- depends on GENERIC_CLOCKEVENTS
- select CLKSRC_MMIO
- help
- Enables support for the Moxart timer.
-
config MXS_TIMER
bool "Mxs timer driver" if COMPILE_TEST
depends on GENERIC_CLOCKEVENTS
@@ -261,21 +249,21 @@ config CLKSRC_LPC32XX
depends on GENERIC_CLOCKEVENTS && HAS_IOMEM
depends on ARM
select CLKSRC_MMIO
- select CLKSRC_OF
+ select TIMER_OF
help
Support for the LPC32XX clocksource.
config CLKSRC_PISTACHIO
bool "Clocksource for Pistachio SoC" if COMPILE_TEST
depends on HAS_IOMEM
- select CLKSRC_OF
+ select TIMER_OF
help
Enables the clocksource for the Pistachio SoC.
config CLKSRC_TI_32K
bool "Texas Instruments 32.768 Hz Clocksource" if COMPILE_TEST
depends on GENERIC_SCHED_CLOCK
- select CLKSRC_OF if OF
+ select TIMER_OF if OF
help
This option enables support for Texas Instruments 32.768 Hz clocksource
available on many OMAP-like platforms.
@@ -284,7 +272,7 @@ config CLKSRC_NPS
bool "NPS400 clocksource driver" if COMPILE_TEST
depends on !PHYS_ADDR_T_64BIT
select CLKSRC_MMIO
- select CLKSRC_OF if OF
+ select TIMER_OF if OF
help
NPS400 clocksource support.
Got 64 bit counter with update rate up to 1000MHz.
@@ -299,12 +287,12 @@ config CLKSRC_MPS2
bool "Clocksource for MPS2 SoCs" if COMPILE_TEST
depends on GENERIC_SCHED_CLOCK
select CLKSRC_MMIO
- select CLKSRC_OF
+ select TIMER_OF
config ARC_TIMERS
bool "Support for 32-bit TIMERn counters in ARC Cores" if COMPILE_TEST
depends on GENERIC_CLOCKEVENTS
- select CLKSRC_OF
+ select TIMER_OF
help
These are legacy 32-bit TIMER0 and TIMER1 counters found on all ARC cores
(ARC700 as well as ARC HS38).
@@ -314,7 +302,7 @@ config ARC_TIMERS_64BIT
bool "Support for 64-bit counters in ARC HS38 cores" if COMPILE_TEST
depends on GENERIC_CLOCKEVENTS
depends on ARC_TIMERS
- select CLKSRC_OF
+ select TIMER_OF
help
This enables 2 different 64-bit timers: RTC (for UP) and GFRC (for SMP)
RTC is implemented inside the core, while GFRC sits outside the core in
@@ -323,8 +311,8 @@ config ARC_TIMERS_64BIT
config ARM_ARCH_TIMER
bool
- select CLKSRC_OF if OF
- select CLKSRC_ACPI if ACPI
+ select TIMER_OF if OF
+ select TIMER_ACPI if ACPI
config ARM_ARCH_TIMER_EVTSTREAM
bool "Enable ARM architected timer event stream generation by default"
@@ -381,7 +369,7 @@ config ARM64_ERRATUM_858921
config ARM_GLOBAL_TIMER
bool "Support for the ARM global timer" if COMPILE_TEST
- select CLKSRC_OF if OF
+ select TIMER_OF if OF
depends on ARM
help
This options enables support for the ARM global timer unit
@@ -390,7 +378,7 @@ config ARM_TIMER_SP804
bool "Support for Dual Timer SP804 module"
depends on GENERIC_SCHED_CLOCK && CLKDEV_LOOKUP
select CLKSRC_MMIO
- select CLKSRC_OF if OF
+ select TIMER_OF if OF
config CLKSRC_ARM_GLOBAL_TIMER_SCHED_CLOCK
bool
@@ -401,19 +389,19 @@ config CLKSRC_ARM_GLOBAL_TIMER_SCHED_CLOCK
config ARMV7M_SYSTICK
bool "Support for the ARMv7M system time" if COMPILE_TEST
- select CLKSRC_OF if OF
+ select TIMER_OF if OF
select CLKSRC_MMIO
help
This options enables support for the ARMv7M system timer unit
config ATMEL_PIT
- select CLKSRC_OF if OF
+ select TIMER_OF if OF
def_bool SOC_AT91SAM9 || SOC_SAMA5
config ATMEL_ST
bool "Atmel ST timer support" if COMPILE_TEST
depends on GENERIC_CLOCKEVENTS
- select CLKSRC_OF
+ select TIMER_OF
select MFD_SYSCON
help
Support for the Atmel ST timer.
@@ -456,7 +444,7 @@ config VF_PIT_TIMER
config OXNAS_RPS_TIMER
bool "Oxford Semiconductor OXNAS RPS Timers driver" if COMPILE_TEST
depends on GENERIC_CLOCKEVENTS
- select CLKSRC_OF
+ select TIMER_OF
select CLKSRC_MMIO
help
This enables support for the Oxford Semiconductor OXNAS RPS timers.
@@ -467,7 +455,7 @@ config SYS_SUPPORTS_SH_CMT
config MTK_TIMER
bool "Mediatek timer driver" if COMPILE_TEST
depends on GENERIC_CLOCKEVENTS && HAS_IOMEM
- select CLKSRC_OF
+ select TIMER_OF
select CLKSRC_MMIO
help
Support for Mediatek timer driver.
@@ -540,7 +528,7 @@ config EM_TIMER_STI
config CLKSRC_QCOM
bool "Qualcomm MSM timer" if COMPILE_TEST
depends on ARM
- select CLKSRC_OF
+ select TIMER_OF
help
This enables the clocksource and the per CPU clockevent driver for the
Qualcomm SoCs.
@@ -548,7 +536,7 @@ config CLKSRC_QCOM
config CLKSRC_VERSATILE
bool "ARM Versatile (Express) reference platforms clock source" if COMPILE_TEST
depends on GENERIC_SCHED_CLOCK && !ARCH_USES_GETTIMEOFFSET
- select CLKSRC_OF
+ select TIMER_OF
default y if MFD_VEXPRESS_SYSREG
help
This option enables clock source based on free running
@@ -559,12 +547,12 @@ config CLKSRC_VERSATILE
config CLKSRC_MIPS_GIC
bool
depends on MIPS_GIC
- select CLKSRC_OF
+ select TIMER_OF
config CLKSRC_TANGO_XTAL
bool "Clocksource for Tango SoC" if COMPILE_TEST
depends on ARM
- select CLKSRC_OF
+ select TIMER_OF
select CLKSRC_MMIO
help
This enables the clocksource for Tango SoC
@@ -605,7 +593,7 @@ config CLKSRC_IMX_GPT
config CLKSRC_ST_LPC
bool "Low power clocksource found in the LPC" if COMPILE_TEST
- select CLKSRC_OF if OF
+ select TIMER_OF if OF
depends on HAS_IOMEM
select CLKSRC_MMIO
help
diff --git a/drivers/clocksource/Makefile b/drivers/clocksource/Makefile
index 2b5b56a6f00f..72bfd001cfbb 100644
--- a/drivers/clocksource/Makefile
+++ b/drivers/clocksource/Makefile
@@ -1,5 +1,5 @@
-obj-$(CONFIG_CLKSRC_PROBE) += clksrc-probe.o
-obj-$(CONFIG_CLKEVT_PROBE) += clkevt-probe.o
+obj-$(CONFIG_TIMER_OF) += timer-of.o
+obj-$(CONFIG_TIMER_PROBE) += timer-probe.o
obj-$(CONFIG_ATMEL_PIT) += timer-atmel-pit.o
obj-$(CONFIG_ATMEL_ST) += timer-atmel-st.o
obj-$(CONFIG_ATMEL_TCB_CLKSRC) += tcb_clksrc.o
@@ -26,7 +26,6 @@ obj-$(CONFIG_ORION_TIMER) += time-orion.o
obj-$(CONFIG_BCM2835_TIMER) += bcm2835_timer.o
obj-$(CONFIG_CLPS711X_TIMER) += clps711x-timer.o
obj-$(CONFIG_ATLAS7_TIMER) += timer-atlas7.o
-obj-$(CONFIG_MOXART_TIMER) += moxart_timer.o
obj-$(CONFIG_MXS_TIMER) += mxs_timer.o
obj-$(CONFIG_CLKSRC_PXA) += pxa_timer.o
obj-$(CONFIG_PRIMA2_TIMER) += timer-prima2.o
diff --git a/drivers/clocksource/arc_timer.c b/drivers/clocksource/arc_timer.c
index 21649733827d..4927355f9cbe 100644
--- a/drivers/clocksource/arc_timer.c
+++ b/drivers/clocksource/arc_timer.c
@@ -99,7 +99,7 @@ static int __init arc_cs_setup_gfrc(struct device_node *node)
return clocksource_register_hz(&arc_counter_gfrc, arc_timer_freq);
}
-CLOCKSOURCE_OF_DECLARE(arc_gfrc, "snps,archs-timer-gfrc", arc_cs_setup_gfrc);
+TIMER_OF_DECLARE(arc_gfrc, "snps,archs-timer-gfrc", arc_cs_setup_gfrc);
#define AUX_RTC_CTRL 0x103
#define AUX_RTC_LOW 0x104
@@ -158,7 +158,7 @@ static int __init arc_cs_setup_rtc(struct device_node *node)
return clocksource_register_hz(&arc_counter_rtc, arc_timer_freq);
}
-CLOCKSOURCE_OF_DECLARE(arc_rtc, "snps,archs-timer-rtc", arc_cs_setup_rtc);
+TIMER_OF_DECLARE(arc_rtc, "snps,archs-timer-rtc", arc_cs_setup_rtc);
#endif
@@ -333,4 +333,4 @@ static int __init arc_of_timer_init(struct device_node *np)
return ret;
}
-CLOCKSOURCE_OF_DECLARE(arc_clkevt, "snps,arc-timer", arc_of_timer_init);
+TIMER_OF_DECLARE(arc_clkevt, "snps,arc-timer", arc_of_timer_init);
diff --git a/drivers/clocksource/arm_arch_timer.c b/drivers/clocksource/arm_arch_timer.c
index 4bed671e490e..aae87c4c546e 100644
--- a/drivers/clocksource/arm_arch_timer.c
+++ b/drivers/clocksource/arm_arch_timer.c
@@ -1194,8 +1194,8 @@ static int __init arch_timer_of_init(struct device_node *np)
return arch_timer_common_init();
}
-CLOCKSOURCE_OF_DECLARE(armv7_arch_timer, "arm,armv7-timer", arch_timer_of_init);
-CLOCKSOURCE_OF_DECLARE(armv8_arch_timer, "arm,armv8-timer", arch_timer_of_init);
+TIMER_OF_DECLARE(armv7_arch_timer, "arm,armv7-timer", arch_timer_of_init);
+TIMER_OF_DECLARE(armv8_arch_timer, "arm,armv8-timer", arch_timer_of_init);
static u32 __init
arch_timer_mem_frame_get_cntfrq(struct arch_timer_mem_frame *frame)
@@ -1209,9 +1209,9 @@ arch_timer_mem_frame_get_cntfrq(struct arch_timer_mem_frame *frame)
return 0;
}
- rate = readl_relaxed(frame + CNTFRQ);
+ rate = readl_relaxed(base + CNTFRQ);
- iounmap(frame);
+ iounmap(base);
return rate;
}
@@ -1382,7 +1382,7 @@ out:
kfree(timer_mem);
return ret;
}
-CLOCKSOURCE_OF_DECLARE(armv7_arch_timer_mem, "arm,armv7-timer-mem",
+TIMER_OF_DECLARE(armv7_arch_timer_mem, "arm,armv7-timer-mem",
arch_timer_mem_of_init);
#ifdef CONFIG_ACPI_GTDT
@@ -1516,5 +1516,5 @@ static int __init arch_timer_acpi_init(struct acpi_table_header *table)
return arch_timer_common_init();
}
-CLOCKSOURCE_ACPI_DECLARE(arch_timer, ACPI_SIG_GTDT, arch_timer_acpi_init);
+TIMER_ACPI_DECLARE(arch_timer, ACPI_SIG_GTDT, arch_timer_acpi_init);
#endif
diff --git a/drivers/clocksource/arm_global_timer.c b/drivers/clocksource/arm_global_timer.c
index 123ed20ac2ff..095bb965f621 100644
--- a/drivers/clocksource/arm_global_timer.c
+++ b/drivers/clocksource/arm_global_timer.c
@@ -339,5 +339,5 @@ out_unmap:
}
/* Only tested on r2p2 and r3p0 */
-CLOCKSOURCE_OF_DECLARE(arm_gt, "arm,cortex-a9-global-timer",
+TIMER_OF_DECLARE(arm_gt, "arm,cortex-a9-global-timer",
global_timer_of_register);
diff --git a/drivers/clocksource/armv7m_systick.c b/drivers/clocksource/armv7m_systick.c
index a315491b7047..ac046d6fb0bf 100644
--- a/drivers/clocksource/armv7m_systick.c
+++ b/drivers/clocksource/armv7m_systick.c
@@ -82,5 +82,5 @@ out_unmap:
return ret;
}
-CLOCKSOURCE_OF_DECLARE(arm_systick, "arm,armv7m-systick",
+TIMER_OF_DECLARE(arm_systick, "arm,armv7m-systick",
system_timer_of_register);
diff --git a/drivers/clocksource/asm9260_timer.c b/drivers/clocksource/asm9260_timer.c
index c6780830b8ac..38cd2feb87c4 100644
--- a/drivers/clocksource/asm9260_timer.c
+++ b/drivers/clocksource/asm9260_timer.c
@@ -238,5 +238,5 @@ static int __init asm9260_timer_init(struct device_node *np)
return 0;
}
-CLOCKSOURCE_OF_DECLARE(asm9260_timer, "alphascale,asm9260-timer",
+TIMER_OF_DECLARE(asm9260_timer, "alphascale,asm9260-timer",
asm9260_timer_init);
diff --git a/drivers/clocksource/bcm2835_timer.c b/drivers/clocksource/bcm2835_timer.c
index dce44307469e..82828d3a4739 100644
--- a/drivers/clocksource/bcm2835_timer.c
+++ b/drivers/clocksource/bcm2835_timer.c
@@ -148,5 +148,5 @@ err_iounmap:
iounmap(base);
return ret;
}
-CLOCKSOURCE_OF_DECLARE(bcm2835, "brcm,bcm2835-system-timer",
+TIMER_OF_DECLARE(bcm2835, "brcm,bcm2835-system-timer",
bcm2835_timer_init);
diff --git a/drivers/clocksource/bcm_kona_timer.c b/drivers/clocksource/bcm_kona_timer.c
index fda5e1476638..5c40be9880f5 100644
--- a/drivers/clocksource/bcm_kona_timer.c
+++ b/drivers/clocksource/bcm_kona_timer.c
@@ -198,9 +198,9 @@ static int __init kona_timer_init(struct device_node *node)
return 0;
}
-CLOCKSOURCE_OF_DECLARE(brcm_kona, "brcm,kona-timer", kona_timer_init);
+TIMER_OF_DECLARE(brcm_kona, "brcm,kona-timer", kona_timer_init);
/*
* bcm,kona-timer is deprecated by brcm,kona-timer
* being kept here for driver compatibility
*/
-CLOCKSOURCE_OF_DECLARE(bcm_kona, "bcm,kona-timer", kona_timer_init);
+TIMER_OF_DECLARE(bcm_kona, "bcm,kona-timer", kona_timer_init);
diff --git a/drivers/clocksource/cadence_ttc_timer.c b/drivers/clocksource/cadence_ttc_timer.c
index 44e5e951583b..29d51755e18b 100644
--- a/drivers/clocksource/cadence_ttc_timer.c
+++ b/drivers/clocksource/cadence_ttc_timer.c
@@ -18,6 +18,7 @@
#include <linux/clk.h>
#include <linux/interrupt.h>
#include <linux/clockchips.h>
+#include <linux/clocksource.h>
#include <linux/of_address.h>
#include <linux/of_irq.h>
#include <linux/slab.h>
@@ -539,4 +540,4 @@ static int __init ttc_timer_init(struct device_node *timer)
return 0;
}
-CLOCKSOURCE_OF_DECLARE(ttc, "cdns,ttc", ttc_timer_init);
+TIMER_OF_DECLARE(ttc, "cdns,ttc", ttc_timer_init);
diff --git a/drivers/clocksource/clkevt-probe.c b/drivers/clocksource/clkevt-probe.c
deleted file mode 100644
index eb89b502acbd..000000000000
--- a/drivers/clocksource/clkevt-probe.c
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
- * Copyright (c) 2016, Linaro Ltd. All rights reserved.
- * Daniel Lezcano <daniel.lezcano@linaro.org>
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
-
-#include <linux/init.h>
-#include <linux/of.h>
-#include <linux/clockchips.h>
-
-extern struct of_device_id __clkevt_of_table[];
-
-static const struct of_device_id __clkevt_of_table_sentinel
- __used __section(__clkevt_of_table_end);
-
-int __init clockevent_probe(void)
-{
- struct device_node *np;
- const struct of_device_id *match;
- of_init_fn_1_ret init_func;
- int ret, clockevents = 0;
-
- for_each_matching_node_and_match(np, __clkevt_of_table, &match) {
- if (!of_device_is_available(np))
- continue;
-
- init_func = match->data;
-
- ret = init_func(np);
- if (ret) {
- pr_warn("Failed to initialize '%s' (%d)\n",
- np->name, ret);
- continue;
- }
-
- clockevents++;
- }
-
- if (!clockevents) {
- pr_crit("%s: no matching clockevent found\n", __func__);
- return -ENODEV;
- }
-
- return 0;
-}
diff --git a/drivers/clocksource/clksrc-dbx500-prcmu.c b/drivers/clocksource/clksrc-dbx500-prcmu.c
index c69e2772658d..c1b96dc5f444 100644
--- a/drivers/clocksource/clksrc-dbx500-prcmu.c
+++ b/drivers/clocksource/clksrc-dbx500-prcmu.c
@@ -86,5 +86,5 @@ static int __init clksrc_dbx500_prcmu_init(struct device_node *node)
#endif
return clocksource_register_hz(&clocksource_dbx500_prcmu, RATE_32K);
}
-CLOCKSOURCE_OF_DECLARE(dbx500_prcmu, "stericsson,db8500-prcmu-timer-4",
+TIMER_OF_DECLARE(dbx500_prcmu, "stericsson,db8500-prcmu-timer-4",
clksrc_dbx500_prcmu_init);
diff --git a/drivers/clocksource/clksrc_st_lpc.c b/drivers/clocksource/clksrc_st_lpc.c
index 03cc49217bb4..a1d01ebb81f5 100644
--- a/drivers/clocksource/clksrc_st_lpc.c
+++ b/drivers/clocksource/clksrc_st_lpc.c
@@ -132,4 +132,4 @@ static int __init st_clksrc_of_register(struct device_node *np)
return ret;
}
-CLOCKSOURCE_OF_DECLARE(ddata, "st,stih407-lpc", st_clksrc_of_register);
+TIMER_OF_DECLARE(ddata, "st,stih407-lpc", st_clksrc_of_register);
diff --git a/drivers/clocksource/clps711x-timer.c b/drivers/clocksource/clps711x-timer.c
index 24db6d605549..a8dd80576c95 100644
--- a/drivers/clocksource/clps711x-timer.c
+++ b/drivers/clocksource/clps711x-timer.c
@@ -103,7 +103,7 @@ void __init clps711x_clksrc_init(void __iomem *tc1_base, void __iomem *tc2_base,
BUG_ON(_clps711x_clkevt_init(tc2, tc2_base, irq));
}
-#ifdef CONFIG_CLKSRC_OF
+#ifdef CONFIG_TIMER_OF
static int __init clps711x_timer_init(struct device_node *np)
{
unsigned int irq = irq_of_parse_and_map(np, 0);
@@ -119,5 +119,5 @@ static int __init clps711x_timer_init(struct device_node *np)
return -EINVAL;
}
}
-CLOCKSOURCE_OF_DECLARE(clps711x, "cirrus,ep7209-timer", clps711x_timer_init);
+TIMER_OF_DECLARE(clps711x, "cirrus,ep7209-timer", clps711x_timer_init);
#endif
diff --git a/drivers/clocksource/dw_apb_timer_of.c b/drivers/clocksource/dw_apb_timer_of.c
index aee6c0d39a7c..69866cd8f4bb 100644
--- a/drivers/clocksource/dw_apb_timer_of.c
+++ b/drivers/clocksource/dw_apb_timer_of.c
@@ -167,7 +167,7 @@ static int __init dw_apb_timer_init(struct device_node *timer)
return 0;
}
-CLOCKSOURCE_OF_DECLARE(pc3x2_timer, "picochip,pc3x2-timer", dw_apb_timer_init);
-CLOCKSOURCE_OF_DECLARE(apb_timer_osc, "snps,dw-apb-timer-osc", dw_apb_timer_init);
-CLOCKSOURCE_OF_DECLARE(apb_timer_sp, "snps,dw-apb-timer-sp", dw_apb_timer_init);
-CLOCKSOURCE_OF_DECLARE(apb_timer, "snps,dw-apb-timer", dw_apb_timer_init);
+TIMER_OF_DECLARE(pc3x2_timer, "picochip,pc3x2-timer", dw_apb_timer_init);
+TIMER_OF_DECLARE(apb_timer_osc, "snps,dw-apb-timer-osc", dw_apb_timer_init);
+TIMER_OF_DECLARE(apb_timer_sp, "snps,dw-apb-timer-sp", dw_apb_timer_init);
+TIMER_OF_DECLARE(apb_timer, "snps,dw-apb-timer", dw_apb_timer_init);
diff --git a/drivers/clocksource/exynos_mct.c b/drivers/clocksource/exynos_mct.c
index 670ff0f25b67..7a244b681876 100644
--- a/drivers/clocksource/exynos_mct.c
+++ b/drivers/clocksource/exynos_mct.c
@@ -610,5 +610,5 @@ static int __init mct_init_ppi(struct device_node *np)
{
return mct_init_dt(np, MCT_INT_PPI);
}
-CLOCKSOURCE_OF_DECLARE(exynos4210, "samsung,exynos4210-mct", mct_init_spi);
-CLOCKSOURCE_OF_DECLARE(exynos4412, "samsung,exynos4412-mct", mct_init_ppi);
+TIMER_OF_DECLARE(exynos4210, "samsung,exynos4210-mct", mct_init_spi);
+TIMER_OF_DECLARE(exynos4412, "samsung,exynos4412-mct", mct_init_ppi);
diff --git a/drivers/clocksource/fsl_ftm_timer.c b/drivers/clocksource/fsl_ftm_timer.c
index 738515b89073..3ee7e6fea621 100644
--- a/drivers/clocksource/fsl_ftm_timer.c
+++ b/drivers/clocksource/fsl_ftm_timer.c
@@ -329,13 +329,13 @@ static int __init ftm_timer_init(struct device_node *np)
priv->clkevt_base = of_iomap(np, 0);
if (!priv->clkevt_base) {
pr_err("ftm: unable to map event timer registers\n");
- goto err;
+ goto err_clkevt;
}
priv->clksrc_base = of_iomap(np, 1);
if (!priv->clksrc_base) {
pr_err("ftm: unable to map source timer registers\n");
- goto err;
+ goto err_clksrc;
}
ret = -EINVAL;
@@ -366,7 +366,11 @@ static int __init ftm_timer_init(struct device_node *np)
return 0;
err:
+ iounmap(priv->clksrc_base);
+err_clksrc:
+ iounmap(priv->clkevt_base);
+err_clkevt:
kfree(priv);
return ret;
}
-CLOCKSOURCE_OF_DECLARE(flextimer, "fsl,ftm-timer", ftm_timer_init);
+TIMER_OF_DECLARE(flextimer, "fsl,ftm-timer", ftm_timer_init);
diff --git a/drivers/clocksource/h8300_timer16.c b/drivers/clocksource/h8300_timer16.c
index 5b27fb9997c2..dfbd4f8051cb 100644
--- a/drivers/clocksource/h8300_timer16.c
+++ b/drivers/clocksource/h8300_timer16.c
@@ -187,5 +187,5 @@ free_clk:
return ret;
}
-CLOCKSOURCE_OF_DECLARE(h8300_16bit, "renesas,16bit-timer",
+TIMER_OF_DECLARE(h8300_16bit, "renesas,16bit-timer",
h8300_16timer_init);
diff --git a/drivers/clocksource/h8300_timer8.c b/drivers/clocksource/h8300_timer8.c
index 804c489531d6..f6ffb0cef091 100644
--- a/drivers/clocksource/h8300_timer8.c
+++ b/drivers/clocksource/h8300_timer8.c
@@ -207,4 +207,4 @@ free_clk:
return ret;
}
-CLOCKSOURCE_OF_DECLARE(h8300_8bit, "renesas,8bit-timer", h8300_8timer_init);
+TIMER_OF_DECLARE(h8300_8bit, "renesas,8bit-timer", h8300_8timer_init);
diff --git a/drivers/clocksource/h8300_tpu.c b/drivers/clocksource/h8300_tpu.c
index 72e1cf2b3096..45a8d17dac1e 100644
--- a/drivers/clocksource/h8300_tpu.c
+++ b/drivers/clocksource/h8300_tpu.c
@@ -154,4 +154,4 @@ free_clk:
return ret;
}
-CLOCKSOURCE_OF_DECLARE(h8300_tpu, "renesas,tpu", h8300_tpu_init);
+TIMER_OF_DECLARE(h8300_tpu, "renesas,tpu", h8300_tpu_init);
diff --git a/drivers/clocksource/jcore-pit.c b/drivers/clocksource/jcore-pit.c
index 7c61226f4359..5d3d88e0fc8c 100644
--- a/drivers/clocksource/jcore-pit.c
+++ b/drivers/clocksource/jcore-pit.c
@@ -246,4 +246,4 @@ static int __init jcore_pit_init(struct device_node *node)
return 0;
}
-CLOCKSOURCE_OF_DECLARE(jcore_pit, "jcore,pit", jcore_pit_init);
+TIMER_OF_DECLARE(jcore_pit, "jcore,pit", jcore_pit_init);
diff --git a/drivers/clocksource/meson6_timer.c b/drivers/clocksource/meson6_timer.c
index 39d21f693a33..92f20991a937 100644
--- a/drivers/clocksource/meson6_timer.c
+++ b/drivers/clocksource/meson6_timer.c
@@ -174,5 +174,5 @@ static int __init meson6_timer_init(struct device_node *node)
1, 0xfffe);
return 0;
}
-CLOCKSOURCE_OF_DECLARE(meson6, "amlogic,meson6-timer",
+TIMER_OF_DECLARE(meson6, "amlogic,meson6-timer",
meson6_timer_init);
diff --git a/drivers/clocksource/mips-gic-timer.c b/drivers/clocksource/mips-gic-timer.c
index 3f52ee219923..17b861ea2626 100644
--- a/drivers/clocksource/mips-gic-timer.c
+++ b/drivers/clocksource/mips-gic-timer.c
@@ -167,10 +167,11 @@ static int __init gic_clocksource_of_init(struct device_node *node)
clk = of_clk_get(node, 0);
if (!IS_ERR(clk)) {
- if (clk_prepare_enable(clk) < 0) {
+ ret = clk_prepare_enable(clk);
+ if (ret < 0) {
pr_err("GIC failed to enable clock\n");
clk_put(clk);
- return PTR_ERR(clk);
+ return ret;
}
gic_frequency = clk_get_rate(clk);
@@ -200,5 +201,5 @@ static int __init gic_clocksource_of_init(struct device_node *node)
return 0;
}
-CLOCKSOURCE_OF_DECLARE(mips_gic_timer, "mti,gic-timer",
+TIMER_OF_DECLARE(mips_gic_timer, "mti,gic-timer",
gic_clocksource_of_init);
diff --git a/drivers/clocksource/moxart_timer.c b/drivers/clocksource/moxart_timer.c
deleted file mode 100644
index 7f3430654fbd..000000000000
--- a/drivers/clocksource/moxart_timer.c
+++ /dev/null
@@ -1,256 +0,0 @@
-/*
- * MOXA ART SoCs timer handling.
- *
- * Copyright (C) 2013 Jonas Jensen
- *
- * Jonas Jensen <jonas.jensen@gmail.com>
- *
- * This file is licensed under the terms of the GNU General Public
- * License version 2. This program is licensed "as is" without any
- * warranty of any kind, whether express or implied.
- */
-
-#include <linux/clk.h>
-#include <linux/clockchips.h>
-#include <linux/interrupt.h>
-#include <linux/irq.h>
-#include <linux/irqreturn.h>
-#include <linux/of.h>
-#include <linux/of_address.h>
-#include <linux/of_irq.h>
-#include <linux/io.h>
-#include <linux/clocksource.h>
-#include <linux/bitops.h>
-#include <linux/slab.h>
-
-#define TIMER1_BASE 0x00
-#define TIMER2_BASE 0x10
-#define TIMER3_BASE 0x20
-
-#define REG_COUNT 0x0 /* writable */
-#define REG_LOAD 0x4
-#define REG_MATCH1 0x8
-#define REG_MATCH2 0xC
-
-#define TIMER_CR 0x30
-#define TIMER_INTR_STATE 0x34
-#define TIMER_INTR_MASK 0x38
-
-/*
- * Moxart TIMER_CR flags:
- *
- * MOXART_CR_*_CLOCK 0: PCLK, 1: EXT1CLK
- * MOXART_CR_*_INT overflow interrupt enable bit
- */
-#define MOXART_CR_1_ENABLE BIT(0)
-#define MOXART_CR_1_CLOCK BIT(1)
-#define MOXART_CR_1_INT BIT(2)
-#define MOXART_CR_2_ENABLE BIT(3)
-#define MOXART_CR_2_CLOCK BIT(4)
-#define MOXART_CR_2_INT BIT(5)
-#define MOXART_CR_3_ENABLE BIT(6)
-#define MOXART_CR_3_CLOCK BIT(7)
-#define MOXART_CR_3_INT BIT(8)
-#define MOXART_CR_COUNT_UP BIT(9)
-
-#define MOXART_TIMER1_ENABLE (MOXART_CR_2_ENABLE | MOXART_CR_1_ENABLE)
-#define MOXART_TIMER1_DISABLE (MOXART_CR_2_ENABLE)
-
-/*
- * The ASpeed variant of the IP block has a different layout
- * for the control register
- */
-#define ASPEED_CR_1_ENABLE BIT(0)
-#define ASPEED_CR_1_CLOCK BIT(1)
-#define ASPEED_CR_1_INT BIT(2)
-#define ASPEED_CR_2_ENABLE BIT(4)
-#define ASPEED_CR_2_CLOCK BIT(5)
-#define ASPEED_CR_2_INT BIT(6)
-#define ASPEED_CR_3_ENABLE BIT(8)
-#define ASPEED_CR_3_CLOCK BIT(9)
-#define ASPEED_CR_3_INT BIT(10)
-
-#define ASPEED_TIMER1_ENABLE (ASPEED_CR_2_ENABLE | ASPEED_CR_1_ENABLE)
-#define ASPEED_TIMER1_DISABLE (ASPEED_CR_2_ENABLE)
-
-struct moxart_timer {
- void __iomem *base;
- unsigned int t1_disable_val;
- unsigned int t1_enable_val;
- unsigned int count_per_tick;
- struct clock_event_device clkevt;
-};
-
-static inline struct moxart_timer *to_moxart(struct clock_event_device *evt)
-{
- return container_of(evt, struct moxart_timer, clkevt);
-}
-
-static inline void moxart_disable(struct clock_event_device *evt)
-{
- struct moxart_timer *timer = to_moxart(evt);
-
- writel(timer->t1_disable_val, timer->base + TIMER_CR);
-}
-
-static inline void moxart_enable(struct clock_event_device *evt)
-{
- struct moxart_timer *timer = to_moxart(evt);
-
- writel(timer->t1_enable_val, timer->base + TIMER_CR);
-}
-
-static int moxart_shutdown(struct clock_event_device *evt)
-{
- moxart_disable(evt);
- return 0;
-}
-
-static int moxart_set_oneshot(struct clock_event_device *evt)
-{
- moxart_disable(evt);
- writel(~0, to_moxart(evt)->base + TIMER1_BASE + REG_LOAD);
- return 0;
-}
-
-static int moxart_set_periodic(struct clock_event_device *evt)
-{
- struct moxart_timer *timer = to_moxart(evt);
-
- moxart_disable(evt);
- writel(timer->count_per_tick, timer->base + TIMER1_BASE + REG_LOAD);
- writel(0, timer->base + TIMER1_BASE + REG_MATCH1);
- moxart_enable(evt);
- return 0;
-}
-
-static int moxart_clkevt_next_event(unsigned long cycles,
- struct clock_event_device *evt)
-{
- struct moxart_timer *timer = to_moxart(evt);
- u32 u;
-
- moxart_disable(evt);
-
- u = readl(timer->base + TIMER1_BASE + REG_COUNT) - cycles;
- writel(u, timer->base + TIMER1_BASE + REG_MATCH1);
-
- moxart_enable(evt);
-
- return 0;
-}
-
-static irqreturn_t moxart_timer_interrupt(int irq, void *dev_id)
-{
- struct clock_event_device *evt = dev_id;
- evt->event_handler(evt);
- return IRQ_HANDLED;
-}
-
-static int __init moxart_timer_init(struct device_node *node)
-{
- int ret, irq;
- unsigned long pclk;
- struct clk *clk;
- struct moxart_timer *timer;
-
- timer = kzalloc(sizeof(*timer), GFP_KERNEL);
- if (!timer)
- return -ENOMEM;
-
- timer->base = of_iomap(node, 0);
- if (!timer->base) {
- pr_err("%s: of_iomap failed\n", node->full_name);
- ret = -ENXIO;
- goto out_free;
- }
-
- irq = irq_of_parse_and_map(node, 0);
- if (irq <= 0) {
- pr_err("%s: irq_of_parse_and_map failed\n", node->full_name);
- ret = -EINVAL;
- goto out_unmap;
- }
-
- clk = of_clk_get(node, 0);
- if (IS_ERR(clk)) {
- pr_err("%s: of_clk_get failed\n", node->full_name);
- ret = PTR_ERR(clk);
- goto out_unmap;
- }
-
- pclk = clk_get_rate(clk);
-
- if (of_device_is_compatible(node, "moxa,moxart-timer")) {
- timer->t1_enable_val = MOXART_TIMER1_ENABLE;
- timer->t1_disable_val = MOXART_TIMER1_DISABLE;
- } else if (of_device_is_compatible(node, "aspeed,ast2400-timer")) {
- timer->t1_enable_val = ASPEED_TIMER1_ENABLE;
- timer->t1_disable_val = ASPEED_TIMER1_DISABLE;
- } else {
- pr_err("%s: unknown platform\n", node->full_name);
- ret = -EINVAL;
- goto out_unmap;
- }
-
- timer->count_per_tick = DIV_ROUND_CLOSEST(pclk, HZ);
-
- timer->clkevt.name = node->name;
- timer->clkevt.rating = 200;
- timer->clkevt.features = CLOCK_EVT_FEAT_PERIODIC |
- CLOCK_EVT_FEAT_ONESHOT;
- timer->clkevt.set_state_shutdown = moxart_shutdown;
- timer->clkevt.set_state_periodic = moxart_set_periodic;
- timer->clkevt.set_state_oneshot = moxart_set_oneshot;
- timer->clkevt.tick_resume = moxart_set_oneshot;
- timer->clkevt.set_next_event = moxart_clkevt_next_event;
- timer->clkevt.cpumask = cpumask_of(0);
- timer->clkevt.irq = irq;
-
- ret = clocksource_mmio_init(timer->base + TIMER2_BASE + REG_COUNT,
- "moxart_timer", pclk, 200, 32,
- clocksource_mmio_readl_down);
- if (ret) {
- pr_err("%s: clocksource_mmio_init failed\n", node->full_name);
- goto out_unmap;
- }
-
- ret = request_irq(irq, moxart_timer_interrupt, IRQF_TIMER,
- node->name, &timer->clkevt);
- if (ret) {
- pr_err("%s: setup_irq failed\n", node->full_name);
- goto out_unmap;
- }
-
- /* Clear match registers */
- writel(0, timer->base + TIMER1_BASE + REG_MATCH1);
- writel(0, timer->base + TIMER1_BASE + REG_MATCH2);
- writel(0, timer->base + TIMER2_BASE + REG_MATCH1);
- writel(0, timer->base + TIMER2_BASE + REG_MATCH2);
-
- /*
- * Start timer 2 rolling as our main wall clock source, keep timer 1
- * disabled
- */
- writel(0, timer->base + TIMER_CR);
- writel(~0, timer->base + TIMER2_BASE + REG_LOAD);
- writel(timer->t1_disable_val, timer->base + TIMER_CR);
-
- /*
- * documentation is not publicly available:
- * min_delta / max_delta obtained by trial-and-error,
- * max_delta 0xfffffffe should be ok because count
- * register size is u32
- */
- clockevents_config_and_register(&timer->clkevt, pclk, 0x4, 0xfffffffe);
-
- return 0;
-
-out_unmap:
- iounmap(timer->base);
-out_free:
- kfree(timer);
- return ret;
-}
-CLOCKSOURCE_OF_DECLARE(moxart, "moxa,moxart-timer", moxart_timer_init);
-CLOCKSOURCE_OF_DECLARE(aspeed, "aspeed,ast2400-timer", moxart_timer_init);
diff --git a/drivers/clocksource/mps2-timer.c b/drivers/clocksource/mps2-timer.c
index 3e4431ed9aa9..aa4d63af8706 100644
--- a/drivers/clocksource/mps2-timer.c
+++ b/drivers/clocksource/mps2-timer.c
@@ -274,4 +274,4 @@ static int __init mps2_timer_init(struct device_node *np)
return 0;
}
-CLOCKSOURCE_OF_DECLARE(mps2_timer, "arm,mps2-timer", mps2_timer_init);
+TIMER_OF_DECLARE(mps2_timer, "arm,mps2-timer", mps2_timer_init);
diff --git a/drivers/clocksource/mtk_timer.c b/drivers/clocksource/mtk_timer.c
index 90659493c59c..f9b724fd9950 100644
--- a/drivers/clocksource/mtk_timer.c
+++ b/drivers/clocksource/mtk_timer.c
@@ -265,4 +265,4 @@ err_kzalloc:
return -EINVAL;
}
-CLOCKSOURCE_OF_DECLARE(mtk_mt6577, "mediatek,mt6577-timer", mtk_timer_init);
+TIMER_OF_DECLARE(mtk_mt6577, "mediatek,mt6577-timer", mtk_timer_init);
diff --git a/drivers/clocksource/mxs_timer.c b/drivers/clocksource/mxs_timer.c
index 99b77aff0839..a03434e9fe8f 100644
--- a/drivers/clocksource/mxs_timer.c
+++ b/drivers/clocksource/mxs_timer.c
@@ -293,4 +293,4 @@ static int __init mxs_timer_init(struct device_node *np)
return setup_irq(irq, &mxs_timer_irq);
}
-CLOCKSOURCE_OF_DECLARE(mxs, "fsl,timrot", mxs_timer_init);
+TIMER_OF_DECLARE(mxs, "fsl,timrot", mxs_timer_init);
diff --git a/drivers/clocksource/nomadik-mtu.c b/drivers/clocksource/nomadik-mtu.c
index 7d44de304f37..8e4ddb9420c6 100644
--- a/drivers/clocksource/nomadik-mtu.c
+++ b/drivers/clocksource/nomadik-mtu.c
@@ -284,5 +284,5 @@ static int __init nmdk_timer_of_init(struct device_node *node)
return nmdk_timer_init(base, irq, pclk, clk);
}
-CLOCKSOURCE_OF_DECLARE(nomadik_mtu, "st,nomadik-mtu",
+TIMER_OF_DECLARE(nomadik_mtu, "st,nomadik-mtu",
nmdk_timer_of_init);
diff --git a/drivers/clocksource/pxa_timer.c b/drivers/clocksource/pxa_timer.c
index a10fa667325f..08cd6eaf3795 100644
--- a/drivers/clocksource/pxa_timer.c
+++ b/drivers/clocksource/pxa_timer.c
@@ -216,7 +216,7 @@ static int __init pxa_timer_dt_init(struct device_node *np)
return pxa_timer_common_init(irq, clk_get_rate(clk));
}
-CLOCKSOURCE_OF_DECLARE(pxa_timer, "marvell,pxa-timer", pxa_timer_dt_init);
+TIMER_OF_DECLARE(pxa_timer, "marvell,pxa-timer", pxa_timer_dt_init);
/*
* Legacy timer init for non device-tree boards.
diff --git a/drivers/clocksource/qcom-timer.c b/drivers/clocksource/qcom-timer.c
index ee358cdf4a07..89816f89ff3f 100644
--- a/drivers/clocksource/qcom-timer.c
+++ b/drivers/clocksource/qcom-timer.c
@@ -254,5 +254,5 @@ static int __init msm_dt_timer_init(struct device_node *np)
return msm_timer_init(freq, 32, irq, !!percpu_offset);
}
-CLOCKSOURCE_OF_DECLARE(kpss_timer, "qcom,kpss-timer", msm_dt_timer_init);
-CLOCKSOURCE_OF_DECLARE(scss_timer, "qcom,scss-timer", msm_dt_timer_init);
+TIMER_OF_DECLARE(kpss_timer, "qcom,kpss-timer", msm_dt_timer_init);
+TIMER_OF_DECLARE(scss_timer, "qcom,scss-timer", msm_dt_timer_init);
diff --git a/drivers/clocksource/renesas-ostm.c b/drivers/clocksource/renesas-ostm.c
index c76f57668fb2..6cffd7c6001a 100644
--- a/drivers/clocksource/renesas-ostm.c
+++ b/drivers/clocksource/renesas-ostm.c
@@ -262,4 +262,4 @@ err:
return 0;
}
-CLOCKSOURCE_OF_DECLARE(ostm, "renesas,ostm", ostm_init);
+TIMER_OF_DECLARE(ostm, "renesas,ostm", ostm_init);
diff --git a/drivers/clocksource/rockchip_timer.c b/drivers/clocksource/rockchip_timer.c
index 49c02be50eca..c27f4c850d83 100644
--- a/drivers/clocksource/rockchip_timer.c
+++ b/drivers/clocksource/rockchip_timer.c
@@ -303,5 +303,5 @@ static int __init rk_timer_init(struct device_node *np)
return -EINVAL;
}
-CLOCKSOURCE_OF_DECLARE(rk3288_timer, "rockchip,rk3288-timer", rk_timer_init);
-CLOCKSOURCE_OF_DECLARE(rk3399_timer, "rockchip,rk3399-timer", rk_timer_init);
+TIMER_OF_DECLARE(rk3288_timer, "rockchip,rk3288-timer", rk_timer_init);
+TIMER_OF_DECLARE(rk3399_timer, "rockchip,rk3399-timer", rk_timer_init);
diff --git a/drivers/clocksource/samsung_pwm_timer.c b/drivers/clocksource/samsung_pwm_timer.c
index a68e6538c809..6d5d126357c2 100644
--- a/drivers/clocksource/samsung_pwm_timer.c
+++ b/drivers/clocksource/samsung_pwm_timer.c
@@ -418,7 +418,7 @@ void __init samsung_pwm_clocksource_init(void __iomem *base,
_samsung_pwm_clocksource_init();
}
-#ifdef CONFIG_CLKSRC_OF
+#ifdef CONFIG_TIMER_OF
static int __init samsung_pwm_alloc(struct device_node *np,
const struct samsung_pwm_variant *variant)
{
@@ -466,7 +466,7 @@ static int __init s3c2410_pwm_clocksource_init(struct device_node *np)
{
return samsung_pwm_alloc(np, &s3c24xx_variant);
}
-CLOCKSOURCE_OF_DECLARE(s3c2410_pwm, "samsung,s3c2410-pwm", s3c2410_pwm_clocksource_init);
+TIMER_OF_DECLARE(s3c2410_pwm, "samsung,s3c2410-pwm", s3c2410_pwm_clocksource_init);
static const struct samsung_pwm_variant s3c64xx_variant = {
.bits = 32,
@@ -479,7 +479,7 @@ static int __init s3c64xx_pwm_clocksource_init(struct device_node *np)
{
return samsung_pwm_alloc(np, &s3c64xx_variant);
}
-CLOCKSOURCE_OF_DECLARE(s3c6400_pwm, "samsung,s3c6400-pwm", s3c64xx_pwm_clocksource_init);
+TIMER_OF_DECLARE(s3c6400_pwm, "samsung,s3c6400-pwm", s3c64xx_pwm_clocksource_init);
static const struct samsung_pwm_variant s5p64x0_variant = {
.bits = 32,
@@ -492,7 +492,7 @@ static int __init s5p64x0_pwm_clocksource_init(struct device_node *np)
{
return samsung_pwm_alloc(np, &s5p64x0_variant);
}
-CLOCKSOURCE_OF_DECLARE(s5p6440_pwm, "samsung,s5p6440-pwm", s5p64x0_pwm_clocksource_init);
+TIMER_OF_DECLARE(s5p6440_pwm, "samsung,s5p6440-pwm", s5p64x0_pwm_clocksource_init);
static const struct samsung_pwm_variant s5p_variant = {
.bits = 32,
@@ -505,5 +505,5 @@ static int __init s5p_pwm_clocksource_init(struct device_node *np)
{
return samsung_pwm_alloc(np, &s5p_variant);
}
-CLOCKSOURCE_OF_DECLARE(s5pc100_pwm, "samsung,s5pc100-pwm", s5p_pwm_clocksource_init);
+TIMER_OF_DECLARE(s5pc100_pwm, "samsung,s5pc100-pwm", s5p_pwm_clocksource_init);
#endif
diff --git a/drivers/clocksource/sun4i_timer.c b/drivers/clocksource/sun4i_timer.c
index 4452d5c8f304..6e0180aaf784 100644
--- a/drivers/clocksource/sun4i_timer.c
+++ b/drivers/clocksource/sun4i_timer.c
@@ -24,6 +24,8 @@
#include <linux/of_address.h>
#include <linux/of_irq.h>
+#include "timer-of.h"
+
#define TIMER_IRQ_EN_REG 0x00
#define TIMER_IRQ_EN(val) BIT(val)
#define TIMER_IRQ_ST_REG 0x04
@@ -39,38 +41,37 @@
#define TIMER_SYNC_TICKS 3
-static void __iomem *timer_base;
-static u32 ticks_per_jiffy;
-
/*
* When we disable a timer, we need to wait at least for 2 cycles of
* the timer source clock. We will use for that the clocksource timer
* that is already setup and runs at the same frequency than the other
* timers, and we never will be disabled.
*/
-static void sun4i_clkevt_sync(void)
+static void sun4i_clkevt_sync(void __iomem *base)
{
- u32 old = readl(timer_base + TIMER_CNTVAL_REG(1));
+ u32 old = readl(base + TIMER_CNTVAL_REG(1));
- while ((old - readl(timer_base + TIMER_CNTVAL_REG(1))) < TIMER_SYNC_TICKS)
+ while ((old - readl(base + TIMER_CNTVAL_REG(1))) < TIMER_SYNC_TICKS)
cpu_relax();
}
-static void sun4i_clkevt_time_stop(u8 timer)
+static void sun4i_clkevt_time_stop(void __iomem *base, u8 timer)
{
- u32 val = readl(timer_base + TIMER_CTL_REG(timer));
- writel(val & ~TIMER_CTL_ENABLE, timer_base + TIMER_CTL_REG(timer));
- sun4i_clkevt_sync();
+ u32 val = readl(base + TIMER_CTL_REG(timer));
+ writel(val & ~TIMER_CTL_ENABLE, base + TIMER_CTL_REG(timer));
+ sun4i_clkevt_sync(base);
}
-static void sun4i_clkevt_time_setup(u8 timer, unsigned long delay)
+static void sun4i_clkevt_time_setup(void __iomem *base, u8 timer,
+ unsigned long delay)
{
- writel(delay, timer_base + TIMER_INTVAL_REG(timer));
+ writel(delay, base + TIMER_INTVAL_REG(timer));
}
-static void sun4i_clkevt_time_start(u8 timer, bool periodic)
+static void sun4i_clkevt_time_start(void __iomem *base, u8 timer,
+ bool periodic)
{
- u32 val = readl(timer_base + TIMER_CTL_REG(timer));
+ u32 val = readl(base + TIMER_CTL_REG(timer));
if (periodic)
val &= ~TIMER_CTL_ONESHOT;
@@ -78,115 +79,106 @@ static void sun4i_clkevt_time_start(u8 timer, bool periodic)
val |= TIMER_CTL_ONESHOT;
writel(val | TIMER_CTL_ENABLE | TIMER_CTL_RELOAD,
- timer_base + TIMER_CTL_REG(timer));
+ base + TIMER_CTL_REG(timer));
}
static int sun4i_clkevt_shutdown(struct clock_event_device *evt)
{
- sun4i_clkevt_time_stop(0);
+ struct timer_of *to = to_timer_of(evt);
+
+ sun4i_clkevt_time_stop(timer_of_base(to), 0);
+
return 0;
}
static int sun4i_clkevt_set_oneshot(struct clock_event_device *evt)
{
- sun4i_clkevt_time_stop(0);
- sun4i_clkevt_time_start(0, false);
+ struct timer_of *to = to_timer_of(evt);
+
+ sun4i_clkevt_time_stop(timer_of_base(to), 0);
+ sun4i_clkevt_time_start(timer_of_base(to), 0, false);
+
return 0;
}
static int sun4i_clkevt_set_periodic(struct clock_event_device *evt)
{
- sun4i_clkevt_time_stop(0);
- sun4i_clkevt_time_setup(0, ticks_per_jiffy);
- sun4i_clkevt_time_start(0, true);
+ struct timer_of *to = to_timer_of(evt);
+
+ sun4i_clkevt_time_stop(timer_of_base(to), 0);
+ sun4i_clkevt_time_setup(timer_of_base(to), 0, timer_of_period(to));
+ sun4i_clkevt_time_start(timer_of_base(to), 0, true);
+
return 0;
}
static int sun4i_clkevt_next_event(unsigned long evt,
- struct clock_event_device *unused)
+ struct clock_event_device *clkevt)
{
- sun4i_clkevt_time_stop(0);
- sun4i_clkevt_time_setup(0, evt - TIMER_SYNC_TICKS);
- sun4i_clkevt_time_start(0, false);
+ struct timer_of *to = to_timer_of(clkevt);
+
+ sun4i_clkevt_time_stop(timer_of_base(to), 0);
+ sun4i_clkevt_time_setup(timer_of_base(to), 0, evt - TIMER_SYNC_TICKS);
+ sun4i_clkevt_time_start(timer_of_base(to), 0, false);
return 0;
}
-static struct clock_event_device sun4i_clockevent = {
- .name = "sun4i_tick",
- .rating = 350,
- .features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT,
- .set_state_shutdown = sun4i_clkevt_shutdown,
- .set_state_periodic = sun4i_clkevt_set_periodic,
- .set_state_oneshot = sun4i_clkevt_set_oneshot,
- .tick_resume = sun4i_clkevt_shutdown,
- .set_next_event = sun4i_clkevt_next_event,
-};
-
-static void sun4i_timer_clear_interrupt(void)
+static void sun4i_timer_clear_interrupt(void __iomem *base)
{
- writel(TIMER_IRQ_EN(0), timer_base + TIMER_IRQ_ST_REG);
+ writel(TIMER_IRQ_EN(0), base + TIMER_IRQ_ST_REG);
}
static irqreturn_t sun4i_timer_interrupt(int irq, void *dev_id)
{
struct clock_event_device *evt = (struct clock_event_device *)dev_id;
+ struct timer_of *to = to_timer_of(evt);
- sun4i_timer_clear_interrupt();
+ sun4i_timer_clear_interrupt(timer_of_base(to));
evt->event_handler(evt);
return IRQ_HANDLED;
}
-static struct irqaction sun4i_timer_irq = {
- .name = "sun4i_timer0",
- .flags = IRQF_TIMER | IRQF_IRQPOLL,
- .handler = sun4i_timer_interrupt,
- .dev_id = &sun4i_clockevent,
+static struct timer_of to = {
+ .flags = TIMER_OF_IRQ | TIMER_OF_CLOCK | TIMER_OF_BASE,
+
+ .clkevt = {
+ .name = "sun4i_tick",
+ .rating = 350,
+ .features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT,
+ .set_state_shutdown = sun4i_clkevt_shutdown,
+ .set_state_periodic = sun4i_clkevt_set_periodic,
+ .set_state_oneshot = sun4i_clkevt_set_oneshot,
+ .tick_resume = sun4i_clkevt_shutdown,
+ .set_next_event = sun4i_clkevt_next_event,
+ .cpumask = cpu_possible_mask,
+ },
+
+ .of_irq = {
+ .handler = sun4i_timer_interrupt,
+ .flags = IRQF_TIMER | IRQF_IRQPOLL,
+ },
};
static u64 notrace sun4i_timer_sched_read(void)
{
- return ~readl(timer_base + TIMER_CNTVAL_REG(1));
+ return ~readl(timer_of_base(&to) + TIMER_CNTVAL_REG(1));
}
static int __init sun4i_timer_init(struct device_node *node)
{
- unsigned long rate = 0;
- struct clk *clk;
- int ret, irq;
+ int ret;
u32 val;
- timer_base = of_iomap(node, 0);
- if (!timer_base) {
- pr_crit("Can't map registers\n");
- return -ENXIO;
- }
-
- irq = irq_of_parse_and_map(node, 0);
- if (irq <= 0) {
- pr_crit("Can't parse IRQ\n");
- return -EINVAL;
- }
-
- clk = of_clk_get(node, 0);
- if (IS_ERR(clk)) {
- pr_crit("Can't get timer clock\n");
- return PTR_ERR(clk);
- }
-
- ret = clk_prepare_enable(clk);
- if (ret) {
- pr_err("Failed to prepare clock\n");
+ ret = timer_of_init(node, &to);
+ if (ret)
return ret;
- }
-
- rate = clk_get_rate(clk);
- writel(~0, timer_base + TIMER_INTVAL_REG(1));
+ writel(~0, timer_of_base(&to) + TIMER_INTVAL_REG(1));
writel(TIMER_CTL_ENABLE | TIMER_CTL_RELOAD |
TIMER_CTL_CLK_SRC(TIMER_CTL_CLK_SRC_OSC24M),
- timer_base + TIMER_CTL_REG(1));
+ timer_of_base(&to) + TIMER_CTL_REG(1));
/*
* sched_clock_register does not have priorities, and on sun6i and
@@ -195,43 +187,34 @@ static int __init sun4i_timer_init(struct device_node *node)
if (of_machine_is_compatible("allwinner,sun4i-a10") ||
of_machine_is_compatible("allwinner,sun5i-a13") ||
of_machine_is_compatible("allwinner,sun5i-a10s"))
- sched_clock_register(sun4i_timer_sched_read, 32, rate);
+ sched_clock_register(sun4i_timer_sched_read, 32,
+ timer_of_rate(&to));
- ret = clocksource_mmio_init(timer_base + TIMER_CNTVAL_REG(1), node->name,
- rate, 350, 32, clocksource_mmio_readl_down);
+ ret = clocksource_mmio_init(timer_of_base(&to) + TIMER_CNTVAL_REG(1),
+ node->name, timer_of_rate(&to), 350, 32,
+ clocksource_mmio_readl_down);
if (ret) {
pr_err("Failed to register clocksource\n");
return ret;
}
- ticks_per_jiffy = DIV_ROUND_UP(rate, HZ);
-
writel(TIMER_CTL_CLK_SRC(TIMER_CTL_CLK_SRC_OSC24M),
- timer_base + TIMER_CTL_REG(0));
+ timer_of_base(&to) + TIMER_CTL_REG(0));
/* Make sure timer is stopped before playing with interrupts */
- sun4i_clkevt_time_stop(0);
+ sun4i_clkevt_time_stop(timer_of_base(&to), 0);
/* clear timer0 interrupt */
- sun4i_timer_clear_interrupt();
-
- sun4i_clockevent.cpumask = cpu_possible_mask;
- sun4i_clockevent.irq = irq;
+ sun4i_timer_clear_interrupt(timer_of_base(&to));
- clockevents_config_and_register(&sun4i_clockevent, rate,
+ clockevents_config_and_register(&to.clkevt, timer_of_rate(&to),
TIMER_SYNC_TICKS, 0xffffffff);
- ret = setup_irq(irq, &sun4i_timer_irq);
- if (ret) {
- pr_err("failed to setup irq %d\n", irq);
- return ret;
- }
-
/* Enable timer0 interrupt */
- val = readl(timer_base + TIMER_IRQ_EN_REG);
- writel(val | TIMER_IRQ_EN(0), timer_base + TIMER_IRQ_EN_REG);
+ val = readl(timer_of_base(&to) + TIMER_IRQ_EN_REG);
+ writel(val | TIMER_IRQ_EN(0), timer_of_base(&to) + TIMER_IRQ_EN_REG);
return ret;
}
-CLOCKSOURCE_OF_DECLARE(sun4i, "allwinner,sun4i-a10-timer",
+TIMER_OF_DECLARE(sun4i, "allwinner,sun4i-a10-timer",
sun4i_timer_init);
diff --git a/drivers/clocksource/tango_xtal.c b/drivers/clocksource/tango_xtal.c
index 12fcef8cf2d3..c4e1c2e6046f 100644
--- a/drivers/clocksource/tango_xtal.c
+++ b/drivers/clocksource/tango_xtal.c
@@ -53,4 +53,4 @@ static int __init tango_clocksource_init(struct device_node *np)
return 0;
}
-CLOCKSOURCE_OF_DECLARE(tango, "sigma,tick-counter", tango_clocksource_init);
+TIMER_OF_DECLARE(tango, "sigma,tick-counter", tango_clocksource_init);
diff --git a/drivers/clocksource/tcb_clksrc.c b/drivers/clocksource/tcb_clksrc.c
index d4ca9962a759..59e8aee0ec16 100644
--- a/drivers/clocksource/tcb_clksrc.c
+++ b/drivers/clocksource/tcb_clksrc.c
@@ -9,6 +9,7 @@
#include <linux/ioport.h>
#include <linux/io.h>
#include <linux/platform_device.h>
+#include <linux/syscore_ops.h>
#include <linux/atmel_tc.h>
@@ -40,6 +41,14 @@
*/
static void __iomem *tcaddr;
+static struct
+{
+ u32 cmr;
+ u32 imr;
+ u32 rc;
+ bool clken;
+} tcb_cache[3];
+static u32 bmr_cache;
static u64 tc_get_cycles(struct clocksource *cs)
{
@@ -48,9 +57,9 @@ static u64 tc_get_cycles(struct clocksource *cs)
raw_local_irq_save(flags);
do {
- upper = __raw_readl(tcaddr + ATMEL_TC_REG(1, CV));
- lower = __raw_readl(tcaddr + ATMEL_TC_REG(0, CV));
- } while (upper != __raw_readl(tcaddr + ATMEL_TC_REG(1, CV)));
+ upper = readl_relaxed(tcaddr + ATMEL_TC_REG(1, CV));
+ lower = readl_relaxed(tcaddr + ATMEL_TC_REG(0, CV));
+ } while (upper != readl_relaxed(tcaddr + ATMEL_TC_REG(1, CV)));
raw_local_irq_restore(flags);
return (upper << 16) | lower;
@@ -58,7 +67,47 @@ static u64 tc_get_cycles(struct clocksource *cs)
static u64 tc_get_cycles32(struct clocksource *cs)
{
- return __raw_readl(tcaddr + ATMEL_TC_REG(0, CV));
+ return readl_relaxed(tcaddr + ATMEL_TC_REG(0, CV));
+}
+
+void tc_clksrc_suspend(struct clocksource *cs)
+{
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(tcb_cache); i++) {
+ tcb_cache[i].cmr = readl(tcaddr + ATMEL_TC_REG(i, CMR));
+ tcb_cache[i].imr = readl(tcaddr + ATMEL_TC_REG(i, IMR));
+ tcb_cache[i].rc = readl(tcaddr + ATMEL_TC_REG(i, RC));
+ tcb_cache[i].clken = !!(readl(tcaddr + ATMEL_TC_REG(i, SR)) &
+ ATMEL_TC_CLKSTA);
+ }
+
+ bmr_cache = readl(tcaddr + ATMEL_TC_BMR);
+}
+
+void tc_clksrc_resume(struct clocksource *cs)
+{
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(tcb_cache); i++) {
+ /* Restore registers for the channel, RA and RB are not used */
+ writel(tcb_cache[i].cmr, tcaddr + ATMEL_TC_REG(i, CMR));
+ writel(tcb_cache[i].rc, tcaddr + ATMEL_TC_REG(i, RC));
+ writel(0, tcaddr + ATMEL_TC_REG(i, RA));
+ writel(0, tcaddr + ATMEL_TC_REG(i, RB));
+ /* Disable all the interrupts */
+ writel(0xff, tcaddr + ATMEL_TC_REG(i, IDR));
+ /* Reenable interrupts that were enabled before suspending */
+ writel(tcb_cache[i].imr, tcaddr + ATMEL_TC_REG(i, IER));
+ /* Start the clock if it was used */
+ if (tcb_cache[i].clken)
+ writel(ATMEL_TC_CLKEN, tcaddr + ATMEL_TC_REG(i, CCR));
+ }
+
+ /* Dual channel, chain channels */
+ writel(bmr_cache, tcaddr + ATMEL_TC_BMR);
+ /* Finally, trigger all the channels*/
+ writel(ATMEL_TC_SYNC, tcaddr + ATMEL_TC_BCR);
}
static struct clocksource clksrc = {
@@ -67,6 +116,8 @@ static struct clocksource clksrc = {
.read = tc_get_cycles,
.mask = CLOCKSOURCE_MASK(32),
.flags = CLOCK_SOURCE_IS_CONTINUOUS,
+ .suspend = tc_clksrc_suspend,
+ .resume = tc_clksrc_resume,
};
#ifdef CONFIG_GENERIC_CLOCKEVENTS
@@ -96,8 +147,8 @@ static int tc_shutdown(struct clock_event_device *d)
struct tc_clkevt_device *tcd = to_tc_clkevt(d);
void __iomem *regs = tcd->regs;
- __raw_writel(0xff, regs + ATMEL_TC_REG(2, IDR));
- __raw_writel(ATMEL_TC_CLKDIS, regs + ATMEL_TC_REG(2, CCR));
+ writel(0xff, regs + ATMEL_TC_REG(2, IDR));
+ writel(ATMEL_TC_CLKDIS, regs + ATMEL_TC_REG(2, CCR));
if (!clockevent_state_detached(d))
clk_disable(tcd->clk);
@@ -115,9 +166,9 @@ static int tc_set_oneshot(struct clock_event_device *d)
clk_enable(tcd->clk);
/* slow clock, count up to RC, then irq and stop */
- __raw_writel(timer_clock | ATMEL_TC_CPCSTOP | ATMEL_TC_WAVE |
+ writel(timer_clock | ATMEL_TC_CPCSTOP | ATMEL_TC_WAVE |
ATMEL_TC_WAVESEL_UP_AUTO, regs + ATMEL_TC_REG(2, CMR));
- __raw_writel(ATMEL_TC_CPCS, regs + ATMEL_TC_REG(2, IER));
+ writel(ATMEL_TC_CPCS, regs + ATMEL_TC_REG(2, IER));
/* set_next_event() configures and starts the timer */
return 0;
@@ -137,25 +188,25 @@ static int tc_set_periodic(struct clock_event_device *d)
clk_enable(tcd->clk);
/* slow clock, count up to RC, then irq and restart */
- __raw_writel(timer_clock | ATMEL_TC_WAVE | ATMEL_TC_WAVESEL_UP_AUTO,
+ writel(timer_clock | ATMEL_TC_WAVE | ATMEL_TC_WAVESEL_UP_AUTO,
regs + ATMEL_TC_REG(2, CMR));
- __raw_writel((32768 + HZ / 2) / HZ, tcaddr + ATMEL_TC_REG(2, RC));
+ writel((32768 + HZ / 2) / HZ, tcaddr + ATMEL_TC_REG(2, RC));
/* Enable clock and interrupts on RC compare */
- __raw_writel(ATMEL_TC_CPCS, regs + ATMEL_TC_REG(2, IER));
+ writel(ATMEL_TC_CPCS, regs + ATMEL_TC_REG(2, IER));
/* go go gadget! */
- __raw_writel(ATMEL_TC_CLKEN | ATMEL_TC_SWTRG, regs +
+ writel(ATMEL_TC_CLKEN | ATMEL_TC_SWTRG, regs +
ATMEL_TC_REG(2, CCR));
return 0;
}
static int tc_next_event(unsigned long delta, struct clock_event_device *d)
{
- __raw_writel(delta, tcaddr + ATMEL_TC_REG(2, RC));
+ writel_relaxed(delta, tcaddr + ATMEL_TC_REG(2, RC));
/* go go gadget! */
- __raw_writel(ATMEL_TC_CLKEN | ATMEL_TC_SWTRG,
+ writel_relaxed(ATMEL_TC_CLKEN | ATMEL_TC_SWTRG,
tcaddr + ATMEL_TC_REG(2, CCR));
return 0;
}
@@ -179,7 +230,7 @@ static irqreturn_t ch2_irq(int irq, void *handle)
struct tc_clkevt_device *dev = handle;
unsigned int sr;
- sr = __raw_readl(dev->regs + ATMEL_TC_REG(2, SR));
+ sr = readl_relaxed(dev->regs + ATMEL_TC_REG(2, SR));
if (sr & ATMEL_TC_CPCS) {
dev->clkevt.event_handler(&dev->clkevt);
return IRQ_HANDLED;
@@ -239,43 +290,43 @@ static int __init setup_clkevents(struct atmel_tc *tc, int clk32k_divisor_idx)
static void __init tcb_setup_dual_chan(struct atmel_tc *tc, int mck_divisor_idx)
{
/* channel 0: waveform mode, input mclk/8, clock TIOA0 on overflow */
- __raw_writel(mck_divisor_idx /* likely divide-by-8 */
+ writel(mck_divisor_idx /* likely divide-by-8 */
| ATMEL_TC_WAVE
| ATMEL_TC_WAVESEL_UP /* free-run */
| ATMEL_TC_ACPA_SET /* TIOA0 rises at 0 */
| ATMEL_TC_ACPC_CLEAR, /* (duty cycle 50%) */
tcaddr + ATMEL_TC_REG(0, CMR));
- __raw_writel(0x0000, tcaddr + ATMEL_TC_REG(0, RA));
- __raw_writel(0x8000, tcaddr + ATMEL_TC_REG(0, RC));
- __raw_writel(0xff, tcaddr + ATMEL_TC_REG(0, IDR)); /* no irqs */
- __raw_writel(ATMEL_TC_CLKEN, tcaddr + ATMEL_TC_REG(0, CCR));
+ writel(0x0000, tcaddr + ATMEL_TC_REG(0, RA));
+ writel(0x8000, tcaddr + ATMEL_TC_REG(0, RC));
+ writel(0xff, tcaddr + ATMEL_TC_REG(0, IDR)); /* no irqs */
+ writel(ATMEL_TC_CLKEN, tcaddr + ATMEL_TC_REG(0, CCR));
/* channel 1: waveform mode, input TIOA0 */
- __raw_writel(ATMEL_TC_XC1 /* input: TIOA0 */
+ writel(ATMEL_TC_XC1 /* input: TIOA0 */
| ATMEL_TC_WAVE
| ATMEL_TC_WAVESEL_UP, /* free-run */
tcaddr + ATMEL_TC_REG(1, CMR));
- __raw_writel(0xff, tcaddr + ATMEL_TC_REG(1, IDR)); /* no irqs */
- __raw_writel(ATMEL_TC_CLKEN, tcaddr + ATMEL_TC_REG(1, CCR));
+ writel(0xff, tcaddr + ATMEL_TC_REG(1, IDR)); /* no irqs */
+ writel(ATMEL_TC_CLKEN, tcaddr + ATMEL_TC_REG(1, CCR));
/* chain channel 0 to channel 1*/
- __raw_writel(ATMEL_TC_TC1XC1S_TIOA0, tcaddr + ATMEL_TC_BMR);
+ writel(ATMEL_TC_TC1XC1S_TIOA0, tcaddr + ATMEL_TC_BMR);
/* then reset all the timers */
- __raw_writel(ATMEL_TC_SYNC, tcaddr + ATMEL_TC_BCR);
+ writel(ATMEL_TC_SYNC, tcaddr + ATMEL_TC_BCR);
}
static void __init tcb_setup_single_chan(struct atmel_tc *tc, int mck_divisor_idx)
{
/* channel 0: waveform mode, input mclk/8 */
- __raw_writel(mck_divisor_idx /* likely divide-by-8 */
+ writel(mck_divisor_idx /* likely divide-by-8 */
| ATMEL_TC_WAVE
| ATMEL_TC_WAVESEL_UP, /* free-run */
tcaddr + ATMEL_TC_REG(0, CMR));
- __raw_writel(0xff, tcaddr + ATMEL_TC_REG(0, IDR)); /* no irqs */
- __raw_writel(ATMEL_TC_CLKEN, tcaddr + ATMEL_TC_REG(0, CCR));
+ writel(0xff, tcaddr + ATMEL_TC_REG(0, IDR)); /* no irqs */
+ writel(ATMEL_TC_CLKEN, tcaddr + ATMEL_TC_REG(0, CCR));
/* then reset all the timers */
- __raw_writel(ATMEL_TC_SYNC, tcaddr + ATMEL_TC_BCR);
+ writel(ATMEL_TC_SYNC, tcaddr + ATMEL_TC_BCR);
}
static int __init tcb_clksrc_init(void)
diff --git a/drivers/clocksource/tegra20_timer.c b/drivers/clocksource/tegra20_timer.c
index b9990b9c98c5..c337a8100a7b 100644
--- a/drivers/clocksource/tegra20_timer.c
+++ b/drivers/clocksource/tegra20_timer.c
@@ -237,7 +237,7 @@ static int __init tegra20_init_timer(struct device_node *np)
return 0;
}
-CLOCKSOURCE_OF_DECLARE(tegra20_timer, "nvidia,tegra20-timer", tegra20_init_timer);
+TIMER_OF_DECLARE(tegra20_timer, "nvidia,tegra20-timer", tegra20_init_timer);
static int __init tegra20_init_rtc(struct device_node *np)
{
@@ -261,4 +261,4 @@ static int __init tegra20_init_rtc(struct device_node *np)
return register_persistent_clock(NULL, tegra_read_persistent_clock64);
}
-CLOCKSOURCE_OF_DECLARE(tegra20_rtc, "nvidia,tegra20-rtc", tegra20_init_rtc);
+TIMER_OF_DECLARE(tegra20_rtc, "nvidia,tegra20-rtc", tegra20_init_rtc);
diff --git a/drivers/clocksource/time-armada-370-xp.c b/drivers/clocksource/time-armada-370-xp.c
index aea4380129ea..edf1a46269f1 100644
--- a/drivers/clocksource/time-armada-370-xp.c
+++ b/drivers/clocksource/time-armada-370-xp.c
@@ -351,7 +351,7 @@ static int __init armada_xp_timer_init(struct device_node *np)
return armada_370_xp_timer_common_init(np);
}
-CLOCKSOURCE_OF_DECLARE(armada_xp, "marvell,armada-xp-timer",
+TIMER_OF_DECLARE(armada_xp, "marvell,armada-xp-timer",
armada_xp_timer_init);
static int __init armada_375_timer_init(struct device_node *np)
@@ -389,7 +389,7 @@ static int __init armada_375_timer_init(struct device_node *np)
return armada_370_xp_timer_common_init(np);
}
-CLOCKSOURCE_OF_DECLARE(armada_375, "marvell,armada-375-timer",
+TIMER_OF_DECLARE(armada_375, "marvell,armada-375-timer",
armada_375_timer_init);
static int __init armada_370_timer_init(struct device_node *np)
@@ -412,5 +412,5 @@ static int __init armada_370_timer_init(struct device_node *np)
return armada_370_xp_timer_common_init(np);
}
-CLOCKSOURCE_OF_DECLARE(armada_370, "marvell,armada-370-timer",
+TIMER_OF_DECLARE(armada_370, "marvell,armada-370-timer",
armada_370_timer_init);
diff --git a/drivers/clocksource/time-efm32.c b/drivers/clocksource/time-efm32.c
index ce0f97b4e5db..257e810ec1ad 100644
--- a/drivers/clocksource/time-efm32.c
+++ b/drivers/clocksource/time-efm32.c
@@ -283,5 +283,5 @@ static int __init efm32_timer_init(struct device_node *np)
return ret;
}
-CLOCKSOURCE_OF_DECLARE(efm32compat, "efm32,timer", efm32_timer_init);
-CLOCKSOURCE_OF_DECLARE(efm32, "energymicro,efm32-timer", efm32_timer_init);
+TIMER_OF_DECLARE(efm32compat, "efm32,timer", efm32_timer_init);
+TIMER_OF_DECLARE(efm32, "energymicro,efm32-timer", efm32_timer_init);
diff --git a/drivers/clocksource/time-lpc32xx.c b/drivers/clocksource/time-lpc32xx.c
index 9649cfdb9213..d51a62a79ef7 100644
--- a/drivers/clocksource/time-lpc32xx.c
+++ b/drivers/clocksource/time-lpc32xx.c
@@ -311,4 +311,4 @@ static int __init lpc32xx_timer_init(struct device_node *np)
return ret;
}
-CLOCKSOURCE_OF_DECLARE(lpc32xx_timer, "nxp,lpc3220-timer", lpc32xx_timer_init);
+TIMER_OF_DECLARE(lpc32xx_timer, "nxp,lpc3220-timer", lpc32xx_timer_init);
diff --git a/drivers/clocksource/time-orion.c b/drivers/clocksource/time-orion.c
index b9b97f630c4d..12202067fe4b 100644
--- a/drivers/clocksource/time-orion.c
+++ b/drivers/clocksource/time-orion.c
@@ -189,4 +189,4 @@ static int __init orion_timer_init(struct device_node *np)
return 0;
}
-CLOCKSOURCE_OF_DECLARE(orion_timer, "marvell,orion-timer", orion_timer_init);
+TIMER_OF_DECLARE(orion_timer, "marvell,orion-timer", orion_timer_init);
diff --git a/drivers/clocksource/time-pistachio.c b/drivers/clocksource/time-pistachio.c
index 3710e4d9dcba..a2dd85d0c1d7 100644
--- a/drivers/clocksource/time-pistachio.c
+++ b/drivers/clocksource/time-pistachio.c
@@ -214,5 +214,5 @@ static int __init pistachio_clksrc_of_init(struct device_node *node)
sched_clock_register(pistachio_read_sched_clock, 32, rate);
return clocksource_register_hz(&pcs_gpt.cs, rate);
}
-CLOCKSOURCE_OF_DECLARE(pistachio_gptimer, "img,pistachio-gptimer",
+TIMER_OF_DECLARE(pistachio_gptimer, "img,pistachio-gptimer",
pistachio_clksrc_of_init);
diff --git a/drivers/clocksource/timer-atlas7.c b/drivers/clocksource/timer-atlas7.c
index 50300eec4a39..62c4bbc55a7e 100644
--- a/drivers/clocksource/timer-atlas7.c
+++ b/drivers/clocksource/timer-atlas7.c
@@ -283,4 +283,4 @@ static int __init sirfsoc_of_timer_init(struct device_node *np)
return sirfsoc_atlas7_timer_init(np);
}
-CLOCKSOURCE_OF_DECLARE(sirfsoc_atlas7_timer, "sirf,atlas7-tick", sirfsoc_of_timer_init);
+TIMER_OF_DECLARE(sirfsoc_atlas7_timer, "sirf,atlas7-tick", sirfsoc_of_timer_init);
diff --git a/drivers/clocksource/timer-atmel-pit.c b/drivers/clocksource/timer-atmel-pit.c
index cc112351dc70..ec8a4376f74f 100644
--- a/drivers/clocksource/timer-atmel-pit.c
+++ b/drivers/clocksource/timer-atmel-pit.c
@@ -255,5 +255,5 @@ static int __init at91sam926x_pit_dt_init(struct device_node *node)
return 0;
}
-CLOCKSOURCE_OF_DECLARE(at91sam926x_pit, "atmel,at91sam9260-pit",
+TIMER_OF_DECLARE(at91sam926x_pit, "atmel,at91sam9260-pit",
at91sam926x_pit_dt_init);
diff --git a/drivers/clocksource/timer-atmel-st.c b/drivers/clocksource/timer-atmel-st.c
index be4ac7604136..d2e660f475af 100644
--- a/drivers/clocksource/timer-atmel-st.c
+++ b/drivers/clocksource/timer-atmel-st.c
@@ -260,5 +260,5 @@ static int __init atmel_st_timer_init(struct device_node *node)
/* register clocksource */
return clocksource_register_hz(&clk32k, sclk_rate);
}
-CLOCKSOURCE_OF_DECLARE(atmel_st_timer, "atmel,at91rm9200-st",
+TIMER_OF_DECLARE(atmel_st_timer, "atmel,at91rm9200-st",
atmel_st_timer_init);
diff --git a/drivers/clocksource/timer-digicolor.c b/drivers/clocksource/timer-digicolor.c
index 94a161eb9cce..1e984a4d8ad0 100644
--- a/drivers/clocksource/timer-digicolor.c
+++ b/drivers/clocksource/timer-digicolor.c
@@ -203,5 +203,5 @@ static int __init digicolor_timer_init(struct device_node *node)
return 0;
}
-CLOCKSOURCE_OF_DECLARE(conexant_digicolor, "cnxt,cx92755-timer",
+TIMER_OF_DECLARE(conexant_digicolor, "cnxt,cx92755-timer",
digicolor_timer_init);
diff --git a/drivers/clocksource/timer-fttmr010.c b/drivers/clocksource/timer-fttmr010.c
index b4a6f1e4bc54..66dd909960c6 100644
--- a/drivers/clocksource/timer-fttmr010.c
+++ b/drivers/clocksource/timer-fttmr010.c
@@ -11,12 +11,13 @@
#include <linux/of.h>
#include <linux/of_address.h>
#include <linux/of_irq.h>
-#include <linux/mfd/syscon.h>
-#include <linux/regmap.h>
#include <linux/clockchips.h>
#include <linux/clocksource.h>
#include <linux/sched_clock.h>
#include <linux/clk.h>
+#include <linux/slab.h>
+#include <linux/bitops.h>
+#include <linux/delay.h>
/*
* Register definitions for the timers
@@ -37,267 +38,368 @@
#define TIMER_INTR_STATE (0x34)
#define TIMER_INTR_MASK (0x38)
-#define TIMER_1_CR_ENABLE (1 << 0)
-#define TIMER_1_CR_CLOCK (1 << 1)
-#define TIMER_1_CR_INT (1 << 2)
-#define TIMER_2_CR_ENABLE (1 << 3)
-#define TIMER_2_CR_CLOCK (1 << 4)
-#define TIMER_2_CR_INT (1 << 5)
-#define TIMER_3_CR_ENABLE (1 << 6)
-#define TIMER_3_CR_CLOCK (1 << 7)
-#define TIMER_3_CR_INT (1 << 8)
-#define TIMER_1_CR_UPDOWN (1 << 9)
-#define TIMER_2_CR_UPDOWN (1 << 10)
-#define TIMER_3_CR_UPDOWN (1 << 11)
-#define TIMER_DEFAULT_FLAGS (TIMER_1_CR_UPDOWN | \
- TIMER_3_CR_ENABLE | \
- TIMER_3_CR_UPDOWN)
-
-#define TIMER_1_INT_MATCH1 (1 << 0)
-#define TIMER_1_INT_MATCH2 (1 << 1)
-#define TIMER_1_INT_OVERFLOW (1 << 2)
-#define TIMER_2_INT_MATCH1 (1 << 3)
-#define TIMER_2_INT_MATCH2 (1 << 4)
-#define TIMER_2_INT_OVERFLOW (1 << 5)
-#define TIMER_3_INT_MATCH1 (1 << 6)
-#define TIMER_3_INT_MATCH2 (1 << 7)
-#define TIMER_3_INT_OVERFLOW (1 << 8)
+#define TIMER_1_CR_ENABLE BIT(0)
+#define TIMER_1_CR_CLOCK BIT(1)
+#define TIMER_1_CR_INT BIT(2)
+#define TIMER_2_CR_ENABLE BIT(3)
+#define TIMER_2_CR_CLOCK BIT(4)
+#define TIMER_2_CR_INT BIT(5)
+#define TIMER_3_CR_ENABLE BIT(6)
+#define TIMER_3_CR_CLOCK BIT(7)
+#define TIMER_3_CR_INT BIT(8)
+#define TIMER_1_CR_UPDOWN BIT(9)
+#define TIMER_2_CR_UPDOWN BIT(10)
+#define TIMER_3_CR_UPDOWN BIT(11)
+
+/*
+ * The Aspeed AST2400 moves bits around in the control register
+ * and lacks bits for setting the timer to count upwards.
+ */
+#define TIMER_1_CR_ASPEED_ENABLE BIT(0)
+#define TIMER_1_CR_ASPEED_CLOCK BIT(1)
+#define TIMER_1_CR_ASPEED_INT BIT(2)
+#define TIMER_2_CR_ASPEED_ENABLE BIT(4)
+#define TIMER_2_CR_ASPEED_CLOCK BIT(5)
+#define TIMER_2_CR_ASPEED_INT BIT(6)
+#define TIMER_3_CR_ASPEED_ENABLE BIT(8)
+#define TIMER_3_CR_ASPEED_CLOCK BIT(9)
+#define TIMER_3_CR_ASPEED_INT BIT(10)
+
+#define TIMER_1_INT_MATCH1 BIT(0)
+#define TIMER_1_INT_MATCH2 BIT(1)
+#define TIMER_1_INT_OVERFLOW BIT(2)
+#define TIMER_2_INT_MATCH1 BIT(3)
+#define TIMER_2_INT_MATCH2 BIT(4)
+#define TIMER_2_INT_OVERFLOW BIT(5)
+#define TIMER_3_INT_MATCH1 BIT(6)
+#define TIMER_3_INT_MATCH2 BIT(7)
+#define TIMER_3_INT_OVERFLOW BIT(8)
#define TIMER_INT_ALL_MASK 0x1ff
-static unsigned int tick_rate;
-static void __iomem *base;
+struct fttmr010 {
+ void __iomem *base;
+ unsigned int tick_rate;
+ bool count_down;
+ u32 t1_enable_val;
+ struct clock_event_device clkevt;
+#ifdef CONFIG_ARM
+ struct delay_timer delay_timer;
+#endif
+};
+
+/*
+ * A local singleton used by sched_clock and delay timer reads, which are
+ * fast and stateless
+ */
+static struct fttmr010 *local_fttmr;
+
+static inline struct fttmr010 *to_fttmr010(struct clock_event_device *evt)
+{
+ return container_of(evt, struct fttmr010, clkevt);
+}
+
+static unsigned long fttmr010_read_current_timer_up(void)
+{
+ return readl(local_fttmr->base + TIMER2_COUNT);
+}
+
+static unsigned long fttmr010_read_current_timer_down(void)
+{
+ return ~readl(local_fttmr->base + TIMER2_COUNT);
+}
+
+static u64 notrace fttmr010_read_sched_clock_up(void)
+{
+ return fttmr010_read_current_timer_up();
+}
-static u64 notrace fttmr010_read_sched_clock(void)
+static u64 notrace fttmr010_read_sched_clock_down(void)
{
- return readl(base + TIMER3_COUNT);
+ return fttmr010_read_current_timer_down();
}
static int fttmr010_timer_set_next_event(unsigned long cycles,
struct clock_event_device *evt)
{
+ struct fttmr010 *fttmr010 = to_fttmr010(evt);
u32 cr;
- /* Setup the match register */
- cr = readl(base + TIMER1_COUNT);
- writel(cr + cycles, base + TIMER1_MATCH1);
- if (readl(base + TIMER1_COUNT) - cr > cycles)
- return -ETIME;
+ /* Stop */
+ cr = readl(fttmr010->base + TIMER_CR);
+ cr &= ~fttmr010->t1_enable_val;
+ writel(cr, fttmr010->base + TIMER_CR);
+
+ /* Setup the match register forward/backward in time */
+ cr = readl(fttmr010->base + TIMER1_COUNT);
+ if (fttmr010->count_down)
+ cr -= cycles;
+ else
+ cr += cycles;
+ writel(cr, fttmr010->base + TIMER1_MATCH1);
+
+ /* Start */
+ cr = readl(fttmr010->base + TIMER_CR);
+ cr |= fttmr010->t1_enable_val;
+ writel(cr, fttmr010->base + TIMER_CR);
return 0;
}
static int fttmr010_timer_shutdown(struct clock_event_device *evt)
{
+ struct fttmr010 *fttmr010 = to_fttmr010(evt);
u32 cr;
- /*
- * Disable also for oneshot: the set_next() call will arm the timer
- * instead.
- */
- /* Stop timer and interrupt. */
- cr = readl(base + TIMER_CR);
- cr &= ~(TIMER_1_CR_ENABLE | TIMER_1_CR_INT);
- writel(cr, base + TIMER_CR);
+ /* Stop */
+ cr = readl(fttmr010->base + TIMER_CR);
+ cr &= ~fttmr010->t1_enable_val;
+ writel(cr, fttmr010->base + TIMER_CR);
+
+ return 0;
+}
+
+static int fttmr010_timer_set_oneshot(struct clock_event_device *evt)
+{
+ struct fttmr010 *fttmr010 = to_fttmr010(evt);
+ u32 cr;
+
+ /* Stop */
+ cr = readl(fttmr010->base + TIMER_CR);
+ cr &= ~fttmr010->t1_enable_val;
+ writel(cr, fttmr010->base + TIMER_CR);
- /* Setup counter start from 0 */
- writel(0, base + TIMER1_COUNT);
- writel(0, base + TIMER1_LOAD);
+ /* Setup counter start from 0 or ~0 */
+ writel(0, fttmr010->base + TIMER1_COUNT);
+ if (fttmr010->count_down)
+ writel(~0, fttmr010->base + TIMER1_LOAD);
+ else
+ writel(0, fttmr010->base + TIMER1_LOAD);
- /* enable interrupt */
- cr = readl(base + TIMER_INTR_MASK);
+ /* Enable interrupt */
+ cr = readl(fttmr010->base + TIMER_INTR_MASK);
cr &= ~(TIMER_1_INT_OVERFLOW | TIMER_1_INT_MATCH2);
cr |= TIMER_1_INT_MATCH1;
- writel(cr, base + TIMER_INTR_MASK);
-
- /* start the timer */
- cr = readl(base + TIMER_CR);
- cr |= TIMER_1_CR_ENABLE;
- writel(cr, base + TIMER_CR);
+ writel(cr, fttmr010->base + TIMER_INTR_MASK);
return 0;
}
static int fttmr010_timer_set_periodic(struct clock_event_device *evt)
{
- u32 period = DIV_ROUND_CLOSEST(tick_rate, HZ);
+ struct fttmr010 *fttmr010 = to_fttmr010(evt);
+ u32 period = DIV_ROUND_CLOSEST(fttmr010->tick_rate, HZ);
u32 cr;
- /* Stop timer and interrupt */
- cr = readl(base + TIMER_CR);
- cr &= ~(TIMER_1_CR_ENABLE | TIMER_1_CR_INT);
- writel(cr, base + TIMER_CR);
-
- /* Setup timer to fire at 1/HT intervals. */
- cr = 0xffffffff - (period - 1);
- writel(cr, base + TIMER1_COUNT);
- writel(cr, base + TIMER1_LOAD);
-
- /* enable interrupt on overflow */
- cr = readl(base + TIMER_INTR_MASK);
- cr &= ~(TIMER_1_INT_MATCH1 | TIMER_1_INT_MATCH2);
- cr |= TIMER_1_INT_OVERFLOW;
- writel(cr, base + TIMER_INTR_MASK);
+ /* Stop */
+ cr = readl(fttmr010->base + TIMER_CR);
+ cr &= ~fttmr010->t1_enable_val;
+ writel(cr, fttmr010->base + TIMER_CR);
+
+ /* Setup timer to fire at 1/HZ intervals. */
+ if (fttmr010->count_down) {
+ writel(period, fttmr010->base + TIMER1_LOAD);
+ writel(0, fttmr010->base + TIMER1_MATCH1);
+ } else {
+ cr = 0xffffffff - (period - 1);
+ writel(cr, fttmr010->base + TIMER1_COUNT);
+ writel(cr, fttmr010->base + TIMER1_LOAD);
+
+ /* Enable interrupt on overflow */
+ cr = readl(fttmr010->base + TIMER_INTR_MASK);
+ cr &= ~(TIMER_1_INT_MATCH1 | TIMER_1_INT_MATCH2);
+ cr |= TIMER_1_INT_OVERFLOW;
+ writel(cr, fttmr010->base + TIMER_INTR_MASK);
+ }
/* Start the timer */
- cr = readl(base + TIMER_CR);
- cr |= TIMER_1_CR_ENABLE;
- cr |= TIMER_1_CR_INT;
- writel(cr, base + TIMER_CR);
+ cr = readl(fttmr010->base + TIMER_CR);
+ cr |= fttmr010->t1_enable_val;
+ writel(cr, fttmr010->base + TIMER_CR);
return 0;
}
-/* Use TIMER1 as clock event */
-static struct clock_event_device fttmr010_clockevent = {
- .name = "TIMER1",
- /* Reasonably fast and accurate clock event */
- .rating = 300,
- .shift = 32,
- .features = CLOCK_EVT_FEAT_PERIODIC |
- CLOCK_EVT_FEAT_ONESHOT,
- .set_next_event = fttmr010_timer_set_next_event,
- .set_state_shutdown = fttmr010_timer_shutdown,
- .set_state_periodic = fttmr010_timer_set_periodic,
- .set_state_oneshot = fttmr010_timer_shutdown,
- .tick_resume = fttmr010_timer_shutdown,
-};
-
/*
* IRQ handler for the timer
*/
static irqreturn_t fttmr010_timer_interrupt(int irq, void *dev_id)
{
- struct clock_event_device *evt = &fttmr010_clockevent;
+ struct clock_event_device *evt = dev_id;
evt->event_handler(evt);
return IRQ_HANDLED;
}
-static struct irqaction fttmr010_timer_irq = {
- .name = "Faraday FTTMR010 Timer Tick",
- .flags = IRQF_TIMER,
- .handler = fttmr010_timer_interrupt,
-};
-
-static int __init fttmr010_timer_common_init(struct device_node *np)
+static int __init fttmr010_common_init(struct device_node *np, bool is_aspeed)
{
+ struct fttmr010 *fttmr010;
int irq;
+ struct clk *clk;
+ int ret;
+ u32 val;
+
+ /*
+ * These implementations require a clock reference.
+ * FIXME: we currently only support clocking using PCLK
+ * and using EXTCLK is not supported in the driver.
+ */
+ clk = of_clk_get_by_name(np, "PCLK");
+ if (IS_ERR(clk)) {
+ pr_err("could not get PCLK\n");
+ return PTR_ERR(clk);
+ }
+ ret = clk_prepare_enable(clk);
+ if (ret) {
+ pr_err("failed to enable PCLK\n");
+ return ret;
+ }
- base = of_iomap(np, 0);
- if (!base) {
+ fttmr010 = kzalloc(sizeof(*fttmr010), GFP_KERNEL);
+ if (!fttmr010) {
+ ret = -ENOMEM;
+ goto out_disable_clock;
+ }
+ fttmr010->tick_rate = clk_get_rate(clk);
+
+ fttmr010->base = of_iomap(np, 0);
+ if (!fttmr010->base) {
pr_err("Can't remap registers");
- return -ENXIO;
+ ret = -ENXIO;
+ goto out_free;
}
/* IRQ for timer 1 */
irq = irq_of_parse_and_map(np, 0);
if (irq <= 0) {
pr_err("Can't parse IRQ");
- return -EINVAL;
+ ret = -EINVAL;
+ goto out_unmap;
+ }
+
+ /*
+ * The Aspeed AST2400 moves bits around in the control register,
+ * otherwise it works the same.
+ */
+ if (is_aspeed) {
+ fttmr010->t1_enable_val = TIMER_1_CR_ASPEED_ENABLE |
+ TIMER_1_CR_ASPEED_INT;
+ /* Downward not available */
+ fttmr010->count_down = true;
+ } else {
+ fttmr010->t1_enable_val = TIMER_1_CR_ENABLE | TIMER_1_CR_INT;
}
/*
* Reset the interrupt mask and status
*/
- writel(TIMER_INT_ALL_MASK, base + TIMER_INTR_MASK);
- writel(0, base + TIMER_INTR_STATE);
- writel(TIMER_DEFAULT_FLAGS, base + TIMER_CR);
+ writel(TIMER_INT_ALL_MASK, fttmr010->base + TIMER_INTR_MASK);
+ writel(0, fttmr010->base + TIMER_INTR_STATE);
+
+ /*
+ * Enable timer 1 count up, timer 2 count up, except on Aspeed,
+ * where everything just counts down.
+ */
+ if (is_aspeed)
+ val = TIMER_2_CR_ASPEED_ENABLE;
+ else {
+ val = TIMER_2_CR_ENABLE;
+ if (!fttmr010->count_down)
+ val |= TIMER_1_CR_UPDOWN | TIMER_2_CR_UPDOWN;
+ }
+ writel(val, fttmr010->base + TIMER_CR);
/*
* Setup free-running clocksource timer (interrupts
* disabled.)
*/
- writel(0, base + TIMER3_COUNT);
- writel(0, base + TIMER3_LOAD);
- writel(0, base + TIMER3_MATCH1);
- writel(0, base + TIMER3_MATCH2);
- clocksource_mmio_init(base + TIMER3_COUNT,
- "fttmr010_clocksource", tick_rate,
- 300, 32, clocksource_mmio_readl_up);
- sched_clock_register(fttmr010_read_sched_clock, 32, tick_rate);
+ local_fttmr = fttmr010;
+ writel(0, fttmr010->base + TIMER2_COUNT);
+ writel(0, fttmr010->base + TIMER2_MATCH1);
+ writel(0, fttmr010->base + TIMER2_MATCH2);
+
+ if (fttmr010->count_down) {
+ writel(~0, fttmr010->base + TIMER2_LOAD);
+ clocksource_mmio_init(fttmr010->base + TIMER2_COUNT,
+ "FTTMR010-TIMER2",
+ fttmr010->tick_rate,
+ 300, 32, clocksource_mmio_readl_down);
+ sched_clock_register(fttmr010_read_sched_clock_down, 32,
+ fttmr010->tick_rate);
+ } else {
+ writel(0, fttmr010->base + TIMER2_LOAD);
+ clocksource_mmio_init(fttmr010->base + TIMER2_COUNT,
+ "FTTMR010-TIMER2",
+ fttmr010->tick_rate,
+ 300, 32, clocksource_mmio_readl_up);
+ sched_clock_register(fttmr010_read_sched_clock_up, 32,
+ fttmr010->tick_rate);
+ }
/*
- * Setup clockevent timer (interrupt-driven.)
+ * Setup clockevent timer (interrupt-driven) on timer 1.
*/
- writel(0, base + TIMER1_COUNT);
- writel(0, base + TIMER1_LOAD);
- writel(0, base + TIMER1_MATCH1);
- writel(0, base + TIMER1_MATCH2);
- setup_irq(irq, &fttmr010_timer_irq);
- fttmr010_clockevent.cpumask = cpumask_of(0);
- clockevents_config_and_register(&fttmr010_clockevent, tick_rate,
+ writel(0, fttmr010->base + TIMER1_COUNT);
+ writel(0, fttmr010->base + TIMER1_LOAD);
+ writel(0, fttmr010->base + TIMER1_MATCH1);
+ writel(0, fttmr010->base + TIMER1_MATCH2);
+ ret = request_irq(irq, fttmr010_timer_interrupt, IRQF_TIMER,
+ "FTTMR010-TIMER1", &fttmr010->clkevt);
+ if (ret) {
+ pr_err("FTTMR010-TIMER1 no IRQ\n");
+ goto out_unmap;
+ }
+
+ fttmr010->clkevt.name = "FTTMR010-TIMER1";
+ /* Reasonably fast and accurate clock event */
+ fttmr010->clkevt.rating = 300;
+ fttmr010->clkevt.features = CLOCK_EVT_FEAT_PERIODIC |
+ CLOCK_EVT_FEAT_ONESHOT;
+ fttmr010->clkevt.set_next_event = fttmr010_timer_set_next_event;
+ fttmr010->clkevt.set_state_shutdown = fttmr010_timer_shutdown;
+ fttmr010->clkevt.set_state_periodic = fttmr010_timer_set_periodic;
+ fttmr010->clkevt.set_state_oneshot = fttmr010_timer_set_oneshot;
+ fttmr010->clkevt.tick_resume = fttmr010_timer_shutdown;
+ fttmr010->clkevt.cpumask = cpumask_of(0);
+ fttmr010->clkevt.irq = irq;
+ clockevents_config_and_register(&fttmr010->clkevt,
+ fttmr010->tick_rate,
1, 0xffffffff);
- return 0;
-}
+#ifdef CONFIG_ARM
+ /* Also use this timer for delays */
+ if (fttmr010->count_down)
+ fttmr010->delay_timer.read_current_timer =
+ fttmr010_read_current_timer_down;
+ else
+ fttmr010->delay_timer.read_current_timer =
+ fttmr010_read_current_timer_up;
+ fttmr010->delay_timer.freq = fttmr010->tick_rate;
+ register_current_timer_delay(&fttmr010->delay_timer);
+#endif
-static int __init fttmr010_timer_of_init(struct device_node *np)
-{
- /*
- * These implementations require a clock reference.
- * FIXME: we currently only support clocking using PCLK
- * and using EXTCLK is not supported in the driver.
- */
- struct clk *clk;
+ return 0;
- clk = of_clk_get_by_name(np, "PCLK");
- if (IS_ERR(clk)) {
- pr_err("could not get PCLK");
- return PTR_ERR(clk);
- }
- tick_rate = clk_get_rate(clk);
+out_unmap:
+ iounmap(fttmr010->base);
+out_free:
+ kfree(fttmr010);
+out_disable_clock:
+ clk_disable_unprepare(clk);
- return fttmr010_timer_common_init(np);
+ return ret;
}
-CLOCKSOURCE_OF_DECLARE(fttmr010, "faraday,fttmr010", fttmr010_timer_of_init);
-/*
- * Gemini-specific: relevant registers in the global syscon
- */
-#define GLOBAL_STATUS 0x04
-#define CPU_AHB_RATIO_MASK (0x3 << 18)
-#define CPU_AHB_1_1 (0x0 << 18)
-#define CPU_AHB_3_2 (0x1 << 18)
-#define CPU_AHB_24_13 (0x2 << 18)
-#define CPU_AHB_2_1 (0x3 << 18)
-#define REG_TO_AHB_SPEED(reg) ((((reg) >> 15) & 0x7) * 10 + 130)
-
-static int __init gemini_timer_of_init(struct device_node *np)
+static __init int aspeed_timer_init(struct device_node *np)
{
- static struct regmap *map;
- int ret;
- u32 val;
-
- map = syscon_regmap_lookup_by_phandle(np, "syscon");
- if (IS_ERR(map)) {
- pr_err("Can't get regmap for syscon handle\n");
- return -ENODEV;
- }
- ret = regmap_read(map, GLOBAL_STATUS, &val);
- if (ret) {
- pr_err("Can't read syscon status register\n");
- return -ENXIO;
- }
-
- tick_rate = REG_TO_AHB_SPEED(val) * 1000000;
- pr_info("Bus: %dMHz ", tick_rate / 1000000);
-
- tick_rate /= 6; /* APB bus run AHB*(1/6) */
-
- switch (val & CPU_AHB_RATIO_MASK) {
- case CPU_AHB_1_1:
- pr_cont("(1/1)\n");
- break;
- case CPU_AHB_3_2:
- pr_cont("(3/2)\n");
- break;
- case CPU_AHB_24_13:
- pr_cont("(24/13)\n");
- break;
- case CPU_AHB_2_1:
- pr_cont("(2/1)\n");
- break;
- }
+ return fttmr010_common_init(np, true);
+}
- return fttmr010_timer_common_init(np);
+static __init int fttmr010_timer_init(struct device_node *np)
+{
+ return fttmr010_common_init(np, false);
}
-CLOCKSOURCE_OF_DECLARE(gemini, "cortina,gemini-timer", gemini_timer_of_init);
+
+TIMER_OF_DECLARE(fttmr010, "faraday,fttmr010", fttmr010_timer_init);
+TIMER_OF_DECLARE(gemini, "cortina,gemini-timer", fttmr010_timer_init);
+TIMER_OF_DECLARE(moxart, "moxa,moxart-timer", fttmr010_timer_init);
+TIMER_OF_DECLARE(ast2400, "aspeed,ast2400-timer", aspeed_timer_init);
+TIMER_OF_DECLARE(ast2500, "aspeed,ast2500-timer", aspeed_timer_init);
diff --git a/drivers/clocksource/timer-imx-gpt.c b/drivers/clocksource/timer-imx-gpt.c
index f595460bfc58..6ec6d79b237c 100644
--- a/drivers/clocksource/timer-imx-gpt.c
+++ b/drivers/clocksource/timer-imx-gpt.c
@@ -545,15 +545,15 @@ static int __init imx6dl_timer_init_dt(struct device_node *np)
return mxc_timer_init_dt(np, GPT_TYPE_IMX6DL);
}
-CLOCKSOURCE_OF_DECLARE(imx1_timer, "fsl,imx1-gpt", imx1_timer_init_dt);
-CLOCKSOURCE_OF_DECLARE(imx21_timer, "fsl,imx21-gpt", imx21_timer_init_dt);
-CLOCKSOURCE_OF_DECLARE(imx27_timer, "fsl,imx27-gpt", imx21_timer_init_dt);
-CLOCKSOURCE_OF_DECLARE(imx31_timer, "fsl,imx31-gpt", imx31_timer_init_dt);
-CLOCKSOURCE_OF_DECLARE(imx25_timer, "fsl,imx25-gpt", imx31_timer_init_dt);
-CLOCKSOURCE_OF_DECLARE(imx50_timer, "fsl,imx50-gpt", imx31_timer_init_dt);
-CLOCKSOURCE_OF_DECLARE(imx51_timer, "fsl,imx51-gpt", imx31_timer_init_dt);
-CLOCKSOURCE_OF_DECLARE(imx53_timer, "fsl,imx53-gpt", imx31_timer_init_dt);
-CLOCKSOURCE_OF_DECLARE(imx6q_timer, "fsl,imx6q-gpt", imx31_timer_init_dt);
-CLOCKSOURCE_OF_DECLARE(imx6dl_timer, "fsl,imx6dl-gpt", imx6dl_timer_init_dt);
-CLOCKSOURCE_OF_DECLARE(imx6sl_timer, "fsl,imx6sl-gpt", imx6dl_timer_init_dt);
-CLOCKSOURCE_OF_DECLARE(imx6sx_timer, "fsl,imx6sx-gpt", imx6dl_timer_init_dt);
+TIMER_OF_DECLARE(imx1_timer, "fsl,imx1-gpt", imx1_timer_init_dt);
+TIMER_OF_DECLARE(imx21_timer, "fsl,imx21-gpt", imx21_timer_init_dt);
+TIMER_OF_DECLARE(imx27_timer, "fsl,imx27-gpt", imx21_timer_init_dt);
+TIMER_OF_DECLARE(imx31_timer, "fsl,imx31-gpt", imx31_timer_init_dt);
+TIMER_OF_DECLARE(imx25_timer, "fsl,imx25-gpt", imx31_timer_init_dt);
+TIMER_OF_DECLARE(imx50_timer, "fsl,imx50-gpt", imx31_timer_init_dt);
+TIMER_OF_DECLARE(imx51_timer, "fsl,imx51-gpt", imx31_timer_init_dt);
+TIMER_OF_DECLARE(imx53_timer, "fsl,imx53-gpt", imx31_timer_init_dt);
+TIMER_OF_DECLARE(imx6q_timer, "fsl,imx6q-gpt", imx31_timer_init_dt);
+TIMER_OF_DECLARE(imx6dl_timer, "fsl,imx6dl-gpt", imx6dl_timer_init_dt);
+TIMER_OF_DECLARE(imx6sl_timer, "fsl,imx6sl-gpt", imx6dl_timer_init_dt);
+TIMER_OF_DECLARE(imx6sx_timer, "fsl,imx6sx-gpt", imx6dl_timer_init_dt);
diff --git a/drivers/clocksource/timer-integrator-ap.c b/drivers/clocksource/timer-integrator-ap.c
index 04ad3066e190..2ff64d9d4fb3 100644
--- a/drivers/clocksource/timer-integrator-ap.c
+++ b/drivers/clocksource/timer-integrator-ap.c
@@ -232,5 +232,5 @@ static int __init integrator_ap_timer_init_of(struct device_node *node)
return 0;
}
-CLOCKSOURCE_OF_DECLARE(integrator_ap_timer, "arm,integrator-timer",
+TIMER_OF_DECLARE(integrator_ap_timer, "arm,integrator-timer",
integrator_ap_timer_init_of);
diff --git a/drivers/clocksource/timer-keystone.c b/drivers/clocksource/timer-keystone.c
index ab68a47ab3b4..0eee03250cfc 100644
--- a/drivers/clocksource/timer-keystone.c
+++ b/drivers/clocksource/timer-keystone.c
@@ -226,5 +226,5 @@ err:
return error;
}
-CLOCKSOURCE_OF_DECLARE(keystone_timer, "ti,keystone-timer",
+TIMER_OF_DECLARE(keystone_timer, "ti,keystone-timer",
keystone_timer_init);
diff --git a/drivers/clocksource/timer-nps.c b/drivers/clocksource/timer-nps.c
index e74ea1722ad3..7b6bb0df96ae 100644
--- a/drivers/clocksource/timer-nps.c
+++ b/drivers/clocksource/timer-nps.c
@@ -110,9 +110,9 @@ static int __init nps_setup_clocksource(struct device_node *node)
return ret;
}
-CLOCKSOURCE_OF_DECLARE(ezchip_nps400_clksrc, "ezchip,nps400-timer",
+TIMER_OF_DECLARE(ezchip_nps400_clksrc, "ezchip,nps400-timer",
nps_setup_clocksource);
-CLOCKSOURCE_OF_DECLARE(ezchip_nps400_clk_src, "ezchip,nps400-timer1",
+TIMER_OF_DECLARE(ezchip_nps400_clk_src, "ezchip,nps400-timer1",
nps_setup_clocksource);
#ifdef CONFIG_EZNPS_MTM_EXT
@@ -279,6 +279,6 @@ static int __init nps_setup_clockevent(struct device_node *node)
return 0;
}
-CLOCKSOURCE_OF_DECLARE(ezchip_nps400_clk_evt, "ezchip,nps400-timer0",
+TIMER_OF_DECLARE(ezchip_nps400_clk_evt, "ezchip,nps400-timer0",
nps_setup_clockevent);
#endif /* CONFIG_EZNPS_MTM_EXT */
diff --git a/drivers/clocksource/timer-of.c b/drivers/clocksource/timer-of.c
new file mode 100644
index 000000000000..f6e7491c873c
--- /dev/null
+++ b/drivers/clocksource/timer-of.c
@@ -0,0 +1,171 @@
+/*
+ * Copyright (c) 2017, Linaro Ltd. All rights reserved.
+ *
+ * Author: Daniel Lezcano <daniel.lezcano@linaro.org>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+#include <linux/clk.h>
+#include <linux/interrupt.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/of_irq.h>
+#include <linux/slab.h>
+
+#include "timer-of.h"
+
+static __init void timer_irq_exit(struct of_timer_irq *of_irq)
+{
+ struct timer_of *to = container_of(of_irq, struct timer_of, of_irq);
+
+ struct clock_event_device *clkevt = &to->clkevt;
+
+ of_irq->percpu ? free_percpu_irq(of_irq->irq, clkevt) :
+ free_irq(of_irq->irq, clkevt);
+}
+
+static __init int timer_irq_init(struct device_node *np,
+ struct of_timer_irq *of_irq)
+{
+ int ret;
+ struct timer_of *to = container_of(of_irq, struct timer_of, of_irq);
+ struct clock_event_device *clkevt = &to->clkevt;
+
+ of_irq->irq = of_irq->name ? of_irq_get_byname(np, of_irq->name):
+ irq_of_parse_and_map(np, of_irq->index);
+ if (!of_irq->irq) {
+ pr_err("Failed to map interrupt for %s\n", np->full_name);
+ return -EINVAL;
+ }
+
+ ret = of_irq->percpu ?
+ request_percpu_irq(of_irq->irq, of_irq->handler,
+ np->full_name, clkevt) :
+ request_irq(of_irq->irq, of_irq->handler,
+ of_irq->flags ? of_irq->flags : IRQF_TIMER,
+ np->full_name, clkevt);
+ if (ret) {
+ pr_err("Failed to request irq %d for %s\n", of_irq->irq,
+ np->full_name);
+ return ret;
+ }
+
+ clkevt->irq = of_irq->irq;
+
+ return 0;
+}
+
+static __init void timer_clk_exit(struct of_timer_clk *of_clk)
+{
+ of_clk->rate = 0;
+ clk_disable_unprepare(of_clk->clk);
+ clk_put(of_clk->clk);
+}
+
+static __init int timer_clk_init(struct device_node *np,
+ struct of_timer_clk *of_clk)
+{
+ int ret;
+
+ of_clk->clk = of_clk->name ? of_clk_get_by_name(np, of_clk->name) :
+ of_clk_get(np, of_clk->index);
+ if (IS_ERR(of_clk->clk)) {
+ pr_err("Failed to get clock for %s\n", np->full_name);
+ return PTR_ERR(of_clk->clk);
+ }
+
+ ret = clk_prepare_enable(of_clk->clk);
+ if (ret) {
+ pr_err("Failed for enable clock for %s\n", np->full_name);
+ goto out_clk_put;
+ }
+
+ of_clk->rate = clk_get_rate(of_clk->clk);
+ if (!of_clk->rate) {
+ ret = -EINVAL;
+ pr_err("Failed to get clock rate for %s\n", np->full_name);
+ goto out_clk_disable;
+ }
+
+ of_clk->period = DIV_ROUND_UP(of_clk->rate, HZ);
+out:
+ return ret;
+
+out_clk_disable:
+ clk_disable_unprepare(of_clk->clk);
+out_clk_put:
+ clk_put(of_clk->clk);
+
+ goto out;
+}
+
+static __init void timer_base_exit(struct of_timer_base *of_base)
+{
+ iounmap(of_base->base);
+}
+
+static __init int timer_base_init(struct device_node *np,
+ struct of_timer_base *of_base)
+{
+ const char *name = of_base->name ? of_base->name : np->full_name;
+
+ of_base->base = of_io_request_and_map(np, of_base->index, name);
+ if (!of_base->base) {
+ pr_err("Failed to iomap (%s)\n", name);
+ return -ENXIO;
+ }
+
+ return 0;
+}
+
+int __init timer_of_init(struct device_node *np, struct timer_of *to)
+{
+ int ret = -EINVAL;
+ int flags = 0;
+
+ if (to->flags & TIMER_OF_BASE) {
+ ret = timer_base_init(np, &to->of_base);
+ if (ret)
+ goto out_fail;
+ flags |= TIMER_OF_BASE;
+ }
+
+ if (to->flags & TIMER_OF_CLOCK) {
+ ret = timer_clk_init(np, &to->of_clk);
+ if (ret)
+ goto out_fail;
+ flags |= TIMER_OF_CLOCK;
+ }
+
+ if (to->flags & TIMER_OF_IRQ) {
+ ret = timer_irq_init(np, &to->of_irq);
+ if (ret)
+ goto out_fail;
+ flags |= TIMER_OF_IRQ;
+ }
+
+ if (!to->clkevt.name)
+ to->clkevt.name = np->name;
+ return ret;
+
+out_fail:
+ if (flags & TIMER_OF_IRQ)
+ timer_irq_exit(&to->of_irq);
+
+ if (flags & TIMER_OF_CLOCK)
+ timer_clk_exit(&to->of_clk);
+
+ if (flags & TIMER_OF_BASE)
+ timer_base_exit(&to->of_base);
+ return ret;
+}
diff --git a/drivers/clocksource/timer-of.h b/drivers/clocksource/timer-of.h
new file mode 100644
index 000000000000..e0d727255f72
--- /dev/null
+++ b/drivers/clocksource/timer-of.h
@@ -0,0 +1,69 @@
+#ifndef __TIMER_OF_H__
+#define __TIMER_OF_H__
+
+#include <linux/clockchips.h>
+
+#define TIMER_OF_BASE 0x1
+#define TIMER_OF_CLOCK 0x2
+#define TIMER_OF_IRQ 0x4
+
+struct of_timer_irq {
+ int irq;
+ int index;
+ int percpu;
+ const char *name;
+ unsigned long flags;
+ irq_handler_t handler;
+};
+
+struct of_timer_base {
+ void __iomem *base;
+ const char *name;
+ int index;
+};
+
+struct of_timer_clk {
+ struct clk *clk;
+ const char *name;
+ int index;
+ unsigned long rate;
+ unsigned long period;
+};
+
+struct timer_of {
+ unsigned int flags;
+ struct clock_event_device clkevt;
+ struct of_timer_base of_base;
+ struct of_timer_irq of_irq;
+ struct of_timer_clk of_clk;
+ void *private_data;
+};
+
+static inline struct timer_of *to_timer_of(struct clock_event_device *clkevt)
+{
+ return container_of(clkevt, struct timer_of, clkevt);
+}
+
+static inline void __iomem *timer_of_base(struct timer_of *to)
+{
+ return to->of_base.base;
+}
+
+static inline int timer_of_irq(struct timer_of *to)
+{
+ return to->of_irq.irq;
+}
+
+static inline unsigned long timer_of_rate(struct timer_of *to)
+{
+ return to->of_clk.rate;
+}
+
+static inline unsigned long timer_of_period(struct timer_of *to)
+{
+ return to->of_clk.period;
+}
+
+extern int __init timer_of_init(struct device_node *np,
+ struct timer_of *to);
+#endif
diff --git a/drivers/clocksource/timer-oxnas-rps.c b/drivers/clocksource/timer-oxnas-rps.c
index d630bf417773..eed6feff8b5f 100644
--- a/drivers/clocksource/timer-oxnas-rps.c
+++ b/drivers/clocksource/timer-oxnas-rps.c
@@ -293,7 +293,7 @@ err_alloc:
return ret;
}
-CLOCKSOURCE_OF_DECLARE(ox810se_rps,
+TIMER_OF_DECLARE(ox810se_rps,
"oxsemi,ox810se-rps-timer", oxnas_rps_timer_init);
-CLOCKSOURCE_OF_DECLARE(ox820_rps,
+TIMER_OF_DECLARE(ox820_rps,
"oxsemi,ox820se-rps-timer", oxnas_rps_timer_init);
diff --git a/drivers/clocksource/timer-prima2.c b/drivers/clocksource/timer-prima2.c
index b4122ed1accb..20ff33b698df 100644
--- a/drivers/clocksource/timer-prima2.c
+++ b/drivers/clocksource/timer-prima2.c
@@ -245,5 +245,5 @@ static int __init sirfsoc_prima2_timer_init(struct device_node *np)
return 0;
}
-CLOCKSOURCE_OF_DECLARE(sirfsoc_prima2_timer,
+TIMER_OF_DECLARE(sirfsoc_prima2_timer,
"sirf,prima2-tick", sirfsoc_prima2_timer_init);
diff --git a/drivers/clocksource/clksrc-probe.c b/drivers/clocksource/timer-probe.c
index ac701ffb8d59..da81e5de74fe 100644
--- a/drivers/clocksource/clksrc-probe.c
+++ b/drivers/clocksource/timer-probe.c
@@ -19,20 +19,20 @@
#include <linux/of.h>
#include <linux/clocksource.h>
-extern struct of_device_id __clksrc_of_table[];
+extern struct of_device_id __timer_of_table[];
-static const struct of_device_id __clksrc_of_table_sentinel
- __used __section(__clksrc_of_table_end);
+static const struct of_device_id __timer_of_table_sentinel
+ __used __section(__timer_of_table_end);
-void __init clocksource_probe(void)
+void __init timer_probe(void)
{
struct device_node *np;
const struct of_device_id *match;
of_init_fn_1_ret init_func_ret;
- unsigned clocksources = 0;
+ unsigned timers = 0;
int ret;
- for_each_matching_node_and_match(np, __clksrc_of_table, &match) {
+ for_each_matching_node_and_match(np, __timer_of_table, &match) {
if (!of_device_is_available(np))
continue;
@@ -45,11 +45,11 @@ void __init clocksource_probe(void)
continue;
}
- clocksources++;
+ timers++;
}
- clocksources += acpi_probe_device_table(clksrc);
+ timers += acpi_probe_device_table(timer);
- if (!clocksources)
- pr_crit("%s: no matching clocksources found\n", __func__);
+ if (!timers)
+ pr_crit("%s: no matching timers found\n", __func__);
}
diff --git a/drivers/clocksource/timer-sp804.c b/drivers/clocksource/timer-sp804.c
index 2d575a8c0939..3ac9dec9a038 100644
--- a/drivers/clocksource/timer-sp804.c
+++ b/drivers/clocksource/timer-sp804.c
@@ -287,7 +287,7 @@ err:
iounmap(base);
return ret;
}
-CLOCKSOURCE_OF_DECLARE(sp804, "arm,sp804", sp804_of_init);
+TIMER_OF_DECLARE(sp804, "arm,sp804", sp804_of_init);
static int __init integrator_cp_of_init(struct device_node *np)
{
@@ -335,4 +335,4 @@ err:
iounmap(base);
return ret;
}
-CLOCKSOURCE_OF_DECLARE(intcp, "arm,integrator-cp-timer", integrator_cp_of_init);
+TIMER_OF_DECLARE(intcp, "arm,integrator-cp-timer", integrator_cp_of_init);
diff --git a/drivers/clocksource/timer-stm32.c b/drivers/clocksource/timer-stm32.c
index 1b2574c4fb97..174d1243ea93 100644
--- a/drivers/clocksource/timer-stm32.c
+++ b/drivers/clocksource/timer-stm32.c
@@ -187,4 +187,4 @@ err_clk_get:
return ret;
}
-CLOCKSOURCE_OF_DECLARE(stm32, "st,stm32-timer", stm32_clockevent_init);
+TIMER_OF_DECLARE(stm32, "st,stm32-timer", stm32_clockevent_init);
diff --git a/drivers/clocksource/timer-sun5i.c b/drivers/clocksource/timer-sun5i.c
index 2e9c830ae1cd..2a3fe83ec337 100644
--- a/drivers/clocksource/timer-sun5i.c
+++ b/drivers/clocksource/timer-sun5i.c
@@ -12,6 +12,7 @@
#include <linux/clk.h>
#include <linux/clockchips.h>
+#include <linux/clocksource.h>
#include <linux/delay.h>
#include <linux/interrupt.h>
#include <linux/irq.h>
@@ -358,7 +359,7 @@ static int __init sun5i_timer_init(struct device_node *node)
return sun5i_setup_clockevent(node, timer_base, clk, irq);
}
-CLOCKSOURCE_OF_DECLARE(sun5i_a13, "allwinner,sun5i-a13-hstimer",
+TIMER_OF_DECLARE(sun5i_a13, "allwinner,sun5i-a13-hstimer",
sun5i_timer_init);
-CLOCKSOURCE_OF_DECLARE(sun7i_a20, "allwinner,sun7i-a20-hstimer",
+TIMER_OF_DECLARE(sun7i_a20, "allwinner,sun7i-a20-hstimer",
sun5i_timer_init);
diff --git a/drivers/clocksource/timer-ti-32k.c b/drivers/clocksource/timer-ti-32k.c
index 624067712ef0..880a861ab3c8 100644
--- a/drivers/clocksource/timer-ti-32k.c
+++ b/drivers/clocksource/timer-ti-32k.c
@@ -124,5 +124,5 @@ static int __init ti_32k_timer_init(struct device_node *np)
return 0;
}
-CLOCKSOURCE_OF_DECLARE(ti_32k_timer, "ti,omap-counter32k",
+TIMER_OF_DECLARE(ti_32k_timer, "ti,omap-counter32k",
ti_32k_timer_init);
diff --git a/drivers/clocksource/timer-u300.c b/drivers/clocksource/timer-u300.c
index 704e40c6f151..be34b116d4d2 100644
--- a/drivers/clocksource/timer-u300.c
+++ b/drivers/clocksource/timer-u300.c
@@ -458,5 +458,5 @@ static int __init u300_timer_init_of(struct device_node *np)
return 0;
}
-CLOCKSOURCE_OF_DECLARE(u300_timer, "stericsson,u300-apptimer",
+TIMER_OF_DECLARE(u300_timer, "stericsson,u300-apptimer",
u300_timer_init_of);
diff --git a/drivers/clocksource/versatile.c b/drivers/clocksource/versatile.c
index 220b490a8142..39725d38aede 100644
--- a/drivers/clocksource/versatile.c
+++ b/drivers/clocksource/versatile.c
@@ -38,7 +38,7 @@ static int __init versatile_sched_clock_init(struct device_node *node)
return 0;
}
-CLOCKSOURCE_OF_DECLARE(vexpress, "arm,vexpress-sysreg",
+TIMER_OF_DECLARE(vexpress, "arm,vexpress-sysreg",
versatile_sched_clock_init);
-CLOCKSOURCE_OF_DECLARE(versatile, "arm,versatile-sysreg",
+TIMER_OF_DECLARE(versatile, "arm,versatile-sysreg",
versatile_sched_clock_init);
diff --git a/drivers/clocksource/vf_pit_timer.c b/drivers/clocksource/vf_pit_timer.c
index e0849e20a307..0f92089ec08c 100644
--- a/drivers/clocksource/vf_pit_timer.c
+++ b/drivers/clocksource/vf_pit_timer.c
@@ -201,4 +201,4 @@ static int __init pit_timer_init(struct device_node *np)
return pit_clockevent_init(clk_rate, irq);
}
-CLOCKSOURCE_OF_DECLARE(vf610, "fsl,vf610-pit", pit_timer_init);
+TIMER_OF_DECLARE(vf610, "fsl,vf610-pit", pit_timer_init);
diff --git a/drivers/clocksource/vt8500_timer.c b/drivers/clocksource/vt8500_timer.c
index d02b51075ad1..e0f7489cfc8e 100644
--- a/drivers/clocksource/vt8500_timer.c
+++ b/drivers/clocksource/vt8500_timer.c
@@ -165,4 +165,4 @@ static int __init vt8500_timer_init(struct device_node *np)
return 0;
}
-CLOCKSOURCE_OF_DECLARE(vt8500, "via,vt8500-timer", vt8500_timer_init);
+TIMER_OF_DECLARE(vt8500, "via,vt8500-timer", vt8500_timer_init);
diff --git a/drivers/clocksource/zevio-timer.c b/drivers/clocksource/zevio-timer.c
index 9a53f5ef6157..a6a0338eea77 100644
--- a/drivers/clocksource/zevio-timer.c
+++ b/drivers/clocksource/zevio-timer.c
@@ -215,4 +215,4 @@ static int __init zevio_timer_init(struct device_node *node)
return zevio_timer_add(node);
}
-CLOCKSOURCE_OF_DECLARE(zevio_timer, "lsi,zevio-timer", zevio_timer_init);
+TIMER_OF_DECLARE(zevio_timer, "lsi,zevio-timer", zevio_timer_init);
diff --git a/drivers/cpufreq/Kconfig.arm b/drivers/cpufreq/Kconfig.arm
index 74ed7e9a7f27..2011fec2d6ad 100644
--- a/drivers/cpufreq/Kconfig.arm
+++ b/drivers/cpufreq/Kconfig.arm
@@ -71,6 +71,15 @@ config ARM_HIGHBANK_CPUFREQ
If in doubt, say N.
+config ARM_DB8500_CPUFREQ
+ tristate "ST-Ericsson DB8500 cpufreq" if COMPILE_TEST && !ARCH_U8500
+ default ARCH_U8500
+ depends on HAS_IOMEM
+ depends on !CPU_THERMAL || THERMAL
+ help
+ This adds the CPUFreq driver for ST-Ericsson Ux500 (DB8500) SoC
+ series.
+
config ARM_IMX6Q_CPUFREQ
tristate "Freescale i.MX6 cpufreq support"
depends on ARCH_MXC
diff --git a/drivers/cpufreq/Makefile b/drivers/cpufreq/Makefile
index b7e78f063c4f..ab3a42cd29ef 100644
--- a/drivers/cpufreq/Makefile
+++ b/drivers/cpufreq/Makefile
@@ -53,7 +53,7 @@ obj-$(CONFIG_ARM_DT_BL_CPUFREQ) += arm_big_little_dt.o
obj-$(CONFIG_ARM_BRCMSTB_AVS_CPUFREQ) += brcmstb-avs-cpufreq.o
obj-$(CONFIG_ARCH_DAVINCI) += davinci-cpufreq.o
-obj-$(CONFIG_UX500_SOC_DB8500) += dbx500-cpufreq.o
+obj-$(CONFIG_ARM_DB8500_CPUFREQ) += dbx500-cpufreq.o
obj-$(CONFIG_ARM_EXYNOS5440_CPUFREQ) += exynos5440-cpufreq.o
obj-$(CONFIG_ARM_HIGHBANK_CPUFREQ) += highbank-cpufreq.o
obj-$(CONFIG_ARM_IMX6Q_CPUFREQ) += imx6q-cpufreq.o
diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c
index 0e3f6496524d..29c5b0cbad96 100644
--- a/drivers/cpufreq/cpufreq.c
+++ b/drivers/cpufreq/cpufreq.c
@@ -887,7 +887,7 @@ static ssize_t store(struct kobject *kobj, struct attribute *attr,
struct freq_attr *fattr = to_attr(attr);
ssize_t ret = -EINVAL;
- get_online_cpus();
+ cpus_read_lock();
if (cpu_online(policy->cpu)) {
down_write(&policy->rwsem);
@@ -895,7 +895,7 @@ static ssize_t store(struct kobject *kobj, struct attribute *attr,
up_write(&policy->rwsem);
}
- put_online_cpus();
+ cpus_read_unlock();
return ret;
}
@@ -2441,7 +2441,7 @@ int cpufreq_register_driver(struct cpufreq_driver *driver_data)
pr_debug("trying to register driver %s\n", driver_data->name);
/* Protect against concurrent CPU online/offline. */
- get_online_cpus();
+ cpus_read_lock();
write_lock_irqsave(&cpufreq_driver_lock, flags);
if (cpufreq_driver) {
@@ -2468,14 +2468,16 @@ int cpufreq_register_driver(struct cpufreq_driver *driver_data)
if (!(cpufreq_driver->flags & CPUFREQ_STICKY) &&
list_empty(&cpufreq_policy_list)) {
/* if all ->init() calls failed, unregister */
+ ret = -ENODEV;
pr_debug("%s: No CPU initialized for driver %s\n", __func__,
driver_data->name);
goto err_if_unreg;
}
- ret = cpuhp_setup_state_nocalls(CPUHP_AP_ONLINE_DYN, "cpufreq:online",
- cpuhp_cpufreq_online,
- cpuhp_cpufreq_offline);
+ ret = cpuhp_setup_state_nocalls_cpuslocked(CPUHP_AP_ONLINE_DYN,
+ "cpufreq:online",
+ cpuhp_cpufreq_online,
+ cpuhp_cpufreq_offline);
if (ret < 0)
goto err_if_unreg;
hp_online = ret;
@@ -2493,7 +2495,7 @@ err_null_driver:
cpufreq_driver = NULL;
write_unlock_irqrestore(&cpufreq_driver_lock, flags);
out:
- put_online_cpus();
+ cpus_read_unlock();
return ret;
}
EXPORT_SYMBOL_GPL(cpufreq_register_driver);
@@ -2516,17 +2518,17 @@ int cpufreq_unregister_driver(struct cpufreq_driver *driver)
pr_debug("unregistering driver %s\n", driver->name);
/* Protect against concurrent cpu hotplug */
- get_online_cpus();
+ cpus_read_lock();
subsys_interface_unregister(&cpufreq_interface);
remove_boost_sysfs_file();
- cpuhp_remove_state_nocalls(hp_online);
+ cpuhp_remove_state_nocalls_cpuslocked(hp_online);
write_lock_irqsave(&cpufreq_driver_lock, flags);
cpufreq_driver = NULL;
write_unlock_irqrestore(&cpufreq_driver_lock, flags);
- put_online_cpus();
+ cpus_read_unlock();
return 0;
}
diff --git a/drivers/cpufreq/cpufreq_conservative.c b/drivers/cpufreq/cpufreq_conservative.c
index 992f7c20760f..88220ff3e1c2 100644
--- a/drivers/cpufreq/cpufreq_conservative.c
+++ b/drivers/cpufreq/cpufreq_conservative.c
@@ -185,8 +185,8 @@ static ssize_t store_down_threshold(struct gov_attr_set *attr_set,
int ret;
ret = sscanf(buf, "%u", &input);
- /* cannot be lower than 11 otherwise freq will not fall */
- if (ret != 1 || input < 11 || input > 100 ||
+ /* cannot be lower than 1 otherwise freq will not fall */
+ if (ret != 1 || input < 1 || input > 100 ||
input >= dbs_data->up_threshold)
return -EINVAL;
diff --git a/drivers/cpufreq/intel_pstate.c b/drivers/cpufreq/intel_pstate.c
index b7de5bd76a31..eb1158532de3 100644
--- a/drivers/cpufreq/intel_pstate.c
+++ b/drivers/cpufreq/intel_pstate.c
@@ -571,9 +571,10 @@ static inline void update_turbo_state(void)
static int min_perf_pct_min(void)
{
struct cpudata *cpu = all_cpu_data[0];
+ int turbo_pstate = cpu->pstate.turbo_pstate;
- return DIV_ROUND_UP(cpu->pstate.min_pstate * 100,
- cpu->pstate.turbo_pstate);
+ return turbo_pstate ?
+ DIV_ROUND_UP(cpu->pstate.min_pstate * 100, turbo_pstate) : 0;
}
static s16 intel_pstate_get_epb(struct cpudata *cpu_data)
diff --git a/drivers/cpufreq/kirkwood-cpufreq.c b/drivers/cpufreq/kirkwood-cpufreq.c
index 1b9bcd76c60e..c2dd43f3f5d8 100644
--- a/drivers/cpufreq/kirkwood-cpufreq.c
+++ b/drivers/cpufreq/kirkwood-cpufreq.c
@@ -127,7 +127,12 @@ static int kirkwood_cpufreq_probe(struct platform_device *pdev)
return PTR_ERR(priv.cpu_clk);
}
- clk_prepare_enable(priv.cpu_clk);
+ err = clk_prepare_enable(priv.cpu_clk);
+ if (err) {
+ dev_err(priv.dev, "Unable to prepare cpuclk\n");
+ return err;
+ }
+
kirkwood_freq_table[0].frequency = clk_get_rate(priv.cpu_clk) / 1000;
priv.ddr_clk = of_clk_get_by_name(np, "ddrclk");
@@ -137,7 +142,11 @@ static int kirkwood_cpufreq_probe(struct platform_device *pdev)
goto out_cpu;
}
- clk_prepare_enable(priv.ddr_clk);
+ err = clk_prepare_enable(priv.ddr_clk);
+ if (err) {
+ dev_err(priv.dev, "Unable to prepare ddrclk\n");
+ goto out_cpu;
+ }
kirkwood_freq_table[1].frequency = clk_get_rate(priv.ddr_clk) / 1000;
priv.powersave_clk = of_clk_get_by_name(np, "powersave");
@@ -146,7 +155,11 @@ static int kirkwood_cpufreq_probe(struct platform_device *pdev)
err = PTR_ERR(priv.powersave_clk);
goto out_ddr;
}
- clk_prepare_enable(priv.powersave_clk);
+ err = clk_prepare_enable(priv.powersave_clk);
+ if (err) {
+ dev_err(priv.dev, "Unable to prepare powersave clk\n");
+ goto out_ddr;
+ }
of_node_put(np);
np = NULL;
diff --git a/drivers/cpufreq/pasemi-cpufreq.c b/drivers/cpufreq/pasemi-cpufreq.c
index 35dd4d7ffee0..b257fc7d5204 100644
--- a/drivers/cpufreq/pasemi-cpufreq.c
+++ b/drivers/cpufreq/pasemi-cpufreq.c
@@ -226,7 +226,7 @@ static int pas_cpufreq_cpu_exit(struct cpufreq_policy *policy)
* We don't support CPU hotplug. Don't unmap after the system
* has already made it to a running state.
*/
- if (system_state != SYSTEM_BOOTING)
+ if (system_state >= SYSTEM_RUNNING)
return 0;
if (sdcasr_mapbase)
diff --git a/drivers/cpuidle/cpuidle.c b/drivers/cpuidle/cpuidle.c
index 2706be7ed334..60bb64f4329d 100644
--- a/drivers/cpuidle/cpuidle.c
+++ b/drivers/cpuidle/cpuidle.c
@@ -220,6 +220,7 @@ int cpuidle_enter_state(struct cpuidle_device *dev, struct cpuidle_driver *drv,
entered_state = target_state->enter(dev, drv, index);
start_critical_timings();
+ sched_clock_idle_wakeup_event();
time_end = ns_to_ktime(local_clock());
trace_cpu_idle_rcuidle(PWR_EVENT_EXIT, dev->cpu);
diff --git a/drivers/cpuidle/dt_idle_states.c b/drivers/cpuidle/dt_idle_states.c
index ffca4fc0061d..ae8eb0359889 100644
--- a/drivers/cpuidle/dt_idle_states.c
+++ b/drivers/cpuidle/dt_idle_states.c
@@ -180,8 +180,10 @@ int dt_init_idle_driver(struct cpuidle_driver *drv,
if (!state_node)
break;
- if (!of_device_is_available(state_node))
+ if (!of_device_is_available(state_node)) {
+ of_node_put(state_node);
continue;
+ }
if (!idle_state_valid(state_node, i, cpumask)) {
pr_warn("%s idle state not valid, bailing out\n",
diff --git a/drivers/crypto/Kconfig b/drivers/crypto/Kconfig
index fb1e60f5002e..9c7951bb05ac 100644
--- a/drivers/crypto/Kconfig
+++ b/drivers/crypto/Kconfig
@@ -89,6 +89,20 @@ config PKEY
requires to have at least one CEX card in coprocessor mode
available at runtime.
+config CRYPTO_PAES_S390
+ tristate "PAES cipher algorithms"
+ depends on S390
+ depends on ZCRYPT
+ depends on PKEY
+ select CRYPTO_ALGAPI
+ select CRYPTO_BLKCIPHER
+ help
+ This is the s390 hardware accelerated implementation of the
+ AES cipher algorithms for use with protected key.
+
+ Select this option if you want to use the paes cipher
+ for example to use protected key encrypted devices.
+
config CRYPTO_SHA1_S390
tristate "SHA1 digest algorithm"
depends on S390
@@ -137,7 +151,6 @@ config CRYPTO_AES_S390
depends on S390
select CRYPTO_ALGAPI
select CRYPTO_BLKCIPHER
- select PKEY
help
This is the s390 hardware accelerated implementation of the
AES cipher algorithms (FIPS-197).
diff --git a/drivers/dax/super.c b/drivers/dax/super.c
index 6ed32aac8bbe..922d0823f8ec 100644
--- a/drivers/dax/super.c
+++ b/drivers/dax/super.c
@@ -210,9 +210,12 @@ EXPORT_SYMBOL_GPL(kill_dax);
static struct inode *dax_alloc_inode(struct super_block *sb)
{
struct dax_device *dax_dev;
+ struct inode *inode;
dax_dev = kmem_cache_alloc(dax_cache, GFP_KERNEL);
- return &dax_dev->inode;
+ inode = &dax_dev->inode;
+ inode->i_rdev = 0;
+ return inode;
}
static struct dax_device *to_dax_dev(struct inode *inode)
@@ -227,7 +230,8 @@ static void dax_i_callback(struct rcu_head *head)
kfree(dax_dev->host);
dax_dev->host = NULL;
- ida_simple_remove(&dax_minor_ida, MINOR(inode->i_rdev));
+ if (inode->i_rdev)
+ ida_simple_remove(&dax_minor_ida, MINOR(inode->i_rdev));
kmem_cache_free(dax_cache, dax_dev);
}
@@ -423,6 +427,7 @@ static void init_once(void *_dax_dev)
struct dax_device *dax_dev = _dax_dev;
struct inode *inode = &dax_dev->inode;
+ memset(dax_dev, 0, sizeof(*dax_dev));
inode_init_once(inode);
}
diff --git a/drivers/devfreq/event/exynos-nocp.c b/drivers/devfreq/event/exynos-nocp.c
index 5c3e7b11e8a6..f6e7956fc91a 100644
--- a/drivers/devfreq/event/exynos-nocp.c
+++ b/drivers/devfreq/event/exynos-nocp.c
@@ -267,7 +267,11 @@ static int exynos_nocp_probe(struct platform_device *pdev)
}
platform_set_drvdata(pdev, nocp);
- clk_prepare_enable(nocp->clk);
+ ret = clk_prepare_enable(nocp->clk);
+ if (ret) {
+ dev_err(&pdev->dev, "failed to prepare ppmu clock\n");
+ return ret;
+ }
pr_info("exynos-nocp: new NoC Probe device registered: %s\n",
dev_name(dev));
diff --git a/drivers/devfreq/event/exynos-ppmu.c b/drivers/devfreq/event/exynos-ppmu.c
index 9b7350935b73..d96e3dc71cf8 100644
--- a/drivers/devfreq/event/exynos-ppmu.c
+++ b/drivers/devfreq/event/exynos-ppmu.c
@@ -44,7 +44,7 @@ struct exynos_ppmu {
{ "ppmu-event2-"#name, PPMU_PMNCNT2 }, \
{ "ppmu-event3-"#name, PPMU_PMNCNT3 }
-struct __exynos_ppmu_events {
+static struct __exynos_ppmu_events {
char *name;
int id;
} ppmu_events[] = {
@@ -648,7 +648,11 @@ static int exynos_ppmu_probe(struct platform_device *pdev)
dev_name(&pdev->dev), desc[i].name);
}
- clk_prepare_enable(info->ppmu.clk);
+ ret = clk_prepare_enable(info->ppmu.clk);
+ if (ret) {
+ dev_err(&pdev->dev, "failed to prepare ppmu clock\n");
+ return ret;
+ }
return 0;
}
diff --git a/drivers/dma/ep93xx_dma.c b/drivers/dma/ep93xx_dma.c
index d37e8dda8079..ec240592f5c8 100644
--- a/drivers/dma/ep93xx_dma.c
+++ b/drivers/dma/ep93xx_dma.c
@@ -201,6 +201,7 @@ struct ep93xx_dma_engine {
struct dma_device dma_dev;
bool m2m;
int (*hw_setup)(struct ep93xx_dma_chan *);
+ void (*hw_synchronize)(struct ep93xx_dma_chan *);
void (*hw_shutdown)(struct ep93xx_dma_chan *);
void (*hw_submit)(struct ep93xx_dma_chan *);
int (*hw_interrupt)(struct ep93xx_dma_chan *);
@@ -323,6 +324,8 @@ static int m2p_hw_setup(struct ep93xx_dma_chan *edmac)
| M2P_CONTROL_ENABLE;
m2p_set_control(edmac, control);
+ edmac->buffer = 0;
+
return 0;
}
@@ -331,21 +334,27 @@ static inline u32 m2p_channel_state(struct ep93xx_dma_chan *edmac)
return (readl(edmac->regs + M2P_STATUS) >> 4) & 0x3;
}
-static void m2p_hw_shutdown(struct ep93xx_dma_chan *edmac)
+static void m2p_hw_synchronize(struct ep93xx_dma_chan *edmac)
{
+ unsigned long flags;
u32 control;
+ spin_lock_irqsave(&edmac->lock, flags);
control = readl(edmac->regs + M2P_CONTROL);
control &= ~(M2P_CONTROL_STALLINT | M2P_CONTROL_NFBINT);
m2p_set_control(edmac, control);
+ spin_unlock_irqrestore(&edmac->lock, flags);
while (m2p_channel_state(edmac) >= M2P_STATE_ON)
- cpu_relax();
+ schedule();
+}
+static void m2p_hw_shutdown(struct ep93xx_dma_chan *edmac)
+{
m2p_set_control(edmac, 0);
- while (m2p_channel_state(edmac) == M2P_STATE_STALL)
- cpu_relax();
+ while (m2p_channel_state(edmac) != M2P_STATE_IDLE)
+ dev_warn(chan2dev(edmac), "M2P: Not yet IDLE\n");
}
static void m2p_fill_desc(struct ep93xx_dma_chan *edmac)
@@ -1161,6 +1170,26 @@ fail:
}
/**
+ * ep93xx_dma_synchronize - Synchronizes the termination of transfers to the
+ * current context.
+ * @chan: channel
+ *
+ * Synchronizes the DMA channel termination to the current context. When this
+ * function returns it is guaranteed that all transfers for previously issued
+ * descriptors have stopped and and it is safe to free the memory associated
+ * with them. Furthermore it is guaranteed that all complete callback functions
+ * for a previously submitted descriptor have finished running and it is safe to
+ * free resources accessed from within the complete callbacks.
+ */
+static void ep93xx_dma_synchronize(struct dma_chan *chan)
+{
+ struct ep93xx_dma_chan *edmac = to_ep93xx_dma_chan(chan);
+
+ if (edmac->edma->hw_synchronize)
+ edmac->edma->hw_synchronize(edmac);
+}
+
+/**
* ep93xx_dma_terminate_all - terminate all transactions
* @chan: channel
*
@@ -1323,6 +1352,7 @@ static int __init ep93xx_dma_probe(struct platform_device *pdev)
dma_dev->device_prep_slave_sg = ep93xx_dma_prep_slave_sg;
dma_dev->device_prep_dma_cyclic = ep93xx_dma_prep_dma_cyclic;
dma_dev->device_config = ep93xx_dma_slave_config;
+ dma_dev->device_synchronize = ep93xx_dma_synchronize;
dma_dev->device_terminate_all = ep93xx_dma_terminate_all;
dma_dev->device_issue_pending = ep93xx_dma_issue_pending;
dma_dev->device_tx_status = ep93xx_dma_tx_status;
@@ -1340,6 +1370,7 @@ static int __init ep93xx_dma_probe(struct platform_device *pdev)
} else {
dma_cap_set(DMA_PRIVATE, dma_dev->cap_mask);
+ edma->hw_synchronize = m2p_hw_synchronize;
edma->hw_setup = m2p_hw_setup;
edma->hw_shutdown = m2p_hw_shutdown;
edma->hw_submit = m2p_hw_submit;
diff --git a/drivers/dma/mv_xor_v2.c b/drivers/dma/mv_xor_v2.c
index a28a01fcba67..f3e211f8f6c5 100644
--- a/drivers/dma/mv_xor_v2.c
+++ b/drivers/dma/mv_xor_v2.c
@@ -161,6 +161,7 @@ struct mv_xor_v2_device {
struct mv_xor_v2_sw_desc *sw_desq;
int desc_size;
unsigned int npendings;
+ unsigned int hw_queue_idx;
};
/**
@@ -214,18 +215,6 @@ static void mv_xor_v2_set_data_buffers(struct mv_xor_v2_device *xor_dev,
}
/*
- * Return the next available index in the DESQ.
- */
-static int mv_xor_v2_get_desq_write_ptr(struct mv_xor_v2_device *xor_dev)
-{
- /* read the index for the next available descriptor in the DESQ */
- u32 reg = readl(xor_dev->dma_base + MV_XOR_V2_DMA_DESQ_ALLOC_OFF);
-
- return ((reg >> MV_XOR_V2_DMA_DESQ_ALLOC_WRPTR_SHIFT)
- & MV_XOR_V2_DMA_DESQ_ALLOC_WRPTR_MASK);
-}
-
-/*
* notify the engine of new descriptors, and update the available index.
*/
static void mv_xor_v2_add_desc_to_desq(struct mv_xor_v2_device *xor_dev,
@@ -257,22 +246,6 @@ static int mv_xor_v2_set_desc_size(struct mv_xor_v2_device *xor_dev)
return MV_XOR_V2_EXT_DESC_SIZE;
}
-/*
- * Set the IMSG threshold
- */
-static inline
-void mv_xor_v2_set_imsg_thrd(struct mv_xor_v2_device *xor_dev, int thrd_val)
-{
- u32 reg;
-
- reg = readl(xor_dev->dma_base + MV_XOR_V2_DMA_IMSG_THRD_OFF);
-
- reg &= (~MV_XOR_V2_DMA_IMSG_THRD_MASK << MV_XOR_V2_DMA_IMSG_THRD_SHIFT);
- reg |= (thrd_val << MV_XOR_V2_DMA_IMSG_THRD_SHIFT);
-
- writel(reg, xor_dev->dma_base + MV_XOR_V2_DMA_IMSG_THRD_OFF);
-}
-
static irqreturn_t mv_xor_v2_interrupt_handler(int irq, void *data)
{
struct mv_xor_v2_device *xor_dev = data;
@@ -288,12 +261,6 @@ static irqreturn_t mv_xor_v2_interrupt_handler(int irq, void *data)
if (!ndescs)
return IRQ_NONE;
- /*
- * Update IMSG threshold, to disable new IMSG interrupts until
- * end of the tasklet
- */
- mv_xor_v2_set_imsg_thrd(xor_dev, MV_XOR_V2_DESC_NUM);
-
/* schedule a tasklet to handle descriptors callbacks */
tasklet_schedule(&xor_dev->irq_tasklet);
@@ -306,7 +273,6 @@ static irqreturn_t mv_xor_v2_interrupt_handler(int irq, void *data)
static dma_cookie_t
mv_xor_v2_tx_submit(struct dma_async_tx_descriptor *tx)
{
- int desq_ptr;
void *dest_hw_desc;
dma_cookie_t cookie;
struct mv_xor_v2_sw_desc *sw_desc =
@@ -322,15 +288,15 @@ mv_xor_v2_tx_submit(struct dma_async_tx_descriptor *tx)
spin_lock_bh(&xor_dev->lock);
cookie = dma_cookie_assign(tx);
- /* get the next available slot in the DESQ */
- desq_ptr = mv_xor_v2_get_desq_write_ptr(xor_dev);
-
/* copy the HW descriptor from the SW descriptor to the DESQ */
- dest_hw_desc = xor_dev->hw_desq_virt + desq_ptr;
+ dest_hw_desc = xor_dev->hw_desq_virt + xor_dev->hw_queue_idx;
memcpy(dest_hw_desc, &sw_desc->hw_desc, xor_dev->desc_size);
xor_dev->npendings++;
+ xor_dev->hw_queue_idx++;
+ if (xor_dev->hw_queue_idx >= MV_XOR_V2_DESC_NUM)
+ xor_dev->hw_queue_idx = 0;
spin_unlock_bh(&xor_dev->lock);
@@ -344,6 +310,7 @@ static struct mv_xor_v2_sw_desc *
mv_xor_v2_prep_sw_desc(struct mv_xor_v2_device *xor_dev)
{
struct mv_xor_v2_sw_desc *sw_desc;
+ bool found = false;
/* Lock the channel */
spin_lock_bh(&xor_dev->lock);
@@ -355,19 +322,23 @@ mv_xor_v2_prep_sw_desc(struct mv_xor_v2_device *xor_dev)
return NULL;
}
- /* get a free SW descriptor from the SW DESQ */
- sw_desc = list_first_entry(&xor_dev->free_sw_desc,
- struct mv_xor_v2_sw_desc, free_list);
+ list_for_each_entry(sw_desc, &xor_dev->free_sw_desc, free_list) {
+ if (async_tx_test_ack(&sw_desc->async_tx)) {
+ found = true;
+ break;
+ }
+ }
+
+ if (!found) {
+ spin_unlock_bh(&xor_dev->lock);
+ return NULL;
+ }
+
list_del(&sw_desc->free_list);
/* Release the channel */
spin_unlock_bh(&xor_dev->lock);
- /* set the async tx descriptor */
- dma_async_tx_descriptor_init(&sw_desc->async_tx, &xor_dev->dmachan);
- sw_desc->async_tx.tx_submit = mv_xor_v2_tx_submit;
- async_tx_ack(&sw_desc->async_tx);
-
return sw_desc;
}
@@ -389,6 +360,8 @@ mv_xor_v2_prep_dma_memcpy(struct dma_chan *chan, dma_addr_t dest,
__func__, len, &src, &dest, flags);
sw_desc = mv_xor_v2_prep_sw_desc(xor_dev);
+ if (!sw_desc)
+ return NULL;
sw_desc->async_tx.flags = flags;
@@ -443,6 +416,8 @@ mv_xor_v2_prep_dma_xor(struct dma_chan *chan, dma_addr_t dest, dma_addr_t *src,
__func__, src_cnt, len, &dest, flags);
sw_desc = mv_xor_v2_prep_sw_desc(xor_dev);
+ if (!sw_desc)
+ return NULL;
sw_desc->async_tx.flags = flags;
@@ -491,6 +466,8 @@ mv_xor_v2_prep_dma_interrupt(struct dma_chan *chan, unsigned long flags)
container_of(chan, struct mv_xor_v2_device, dmachan);
sw_desc = mv_xor_v2_prep_sw_desc(xor_dev);
+ if (!sw_desc)
+ return NULL;
/* set the HW descriptor */
hw_descriptor = &sw_desc->hw_desc;
@@ -554,7 +531,6 @@ static void mv_xor_v2_tasklet(unsigned long data)
{
struct mv_xor_v2_device *xor_dev = (struct mv_xor_v2_device *) data;
int pending_ptr, num_of_pending, i;
- struct mv_xor_v2_descriptor *next_pending_hw_desc = NULL;
struct mv_xor_v2_sw_desc *next_pending_sw_desc = NULL;
dev_dbg(xor_dev->dmadev.dev, "%s %d\n", __func__, __LINE__);
@@ -562,17 +538,10 @@ static void mv_xor_v2_tasklet(unsigned long data)
/* get the pending descriptors parameters */
num_of_pending = mv_xor_v2_get_pending_params(xor_dev, &pending_ptr);
- /* next HW descriptor */
- next_pending_hw_desc = xor_dev->hw_desq_virt + pending_ptr;
-
/* loop over free descriptors */
for (i = 0; i < num_of_pending; i++) {
-
- if (pending_ptr > MV_XOR_V2_DESC_NUM)
- pending_ptr = 0;
-
- if (next_pending_sw_desc != NULL)
- next_pending_hw_desc++;
+ struct mv_xor_v2_descriptor *next_pending_hw_desc =
+ xor_dev->hw_desq_virt + pending_ptr;
/* get the SW descriptor related to the HW descriptor */
next_pending_sw_desc =
@@ -608,15 +577,14 @@ static void mv_xor_v2_tasklet(unsigned long data)
/* increment the next descriptor */
pending_ptr++;
+ if (pending_ptr >= MV_XOR_V2_DESC_NUM)
+ pending_ptr = 0;
}
if (num_of_pending != 0) {
/* free the descriptores */
mv_xor_v2_free_desc_from_desq(xor_dev, num_of_pending);
}
-
- /* Update IMSG threshold, to enable new IMSG interrupts */
- mv_xor_v2_set_imsg_thrd(xor_dev, 0);
}
/*
@@ -648,9 +616,6 @@ static int mv_xor_v2_descq_init(struct mv_xor_v2_device *xor_dev)
writel((xor_dev->hw_desq & 0xFFFF00000000) >> 32,
xor_dev->dma_base + MV_XOR_V2_DMA_DESQ_BAHR_OFF);
- /* enable the DMA engine */
- writel(0, xor_dev->dma_base + MV_XOR_V2_DMA_DESQ_STOP_OFF);
-
/*
* This is a temporary solution, until we activate the
* SMMU. Set the attributes for reading & writing data buffers
@@ -694,6 +659,9 @@ static int mv_xor_v2_descq_init(struct mv_xor_v2_device *xor_dev)
reg |= MV_XOR_V2_GLOB_PAUSE_AXI_TIME_DIS_VAL;
writel(reg, xor_dev->glob_base + MV_XOR_V2_GLOB_PAUSE);
+ /* enable the DMA engine */
+ writel(0, xor_dev->dma_base + MV_XOR_V2_DMA_DESQ_STOP_OFF);
+
return 0;
}
@@ -725,6 +693,10 @@ static int mv_xor_v2_probe(struct platform_device *pdev)
platform_set_drvdata(pdev, xor_dev);
+ ret = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(40));
+ if (ret)
+ return ret;
+
xor_dev->clk = devm_clk_get(&pdev->dev, NULL);
if (IS_ERR(xor_dev->clk) && PTR_ERR(xor_dev->clk) == -EPROBE_DEFER)
return -EPROBE_DEFER;
@@ -785,8 +757,15 @@ static int mv_xor_v2_probe(struct platform_device *pdev)
/* add all SW descriptors to the free list */
for (i = 0; i < MV_XOR_V2_DESC_NUM; i++) {
- xor_dev->sw_desq[i].idx = i;
- list_add(&xor_dev->sw_desq[i].free_list,
+ struct mv_xor_v2_sw_desc *sw_desc =
+ xor_dev->sw_desq + i;
+ sw_desc->idx = i;
+ dma_async_tx_descriptor_init(&sw_desc->async_tx,
+ &xor_dev->dmachan);
+ sw_desc->async_tx.tx_submit = mv_xor_v2_tx_submit;
+ async_tx_ack(&sw_desc->async_tx);
+
+ list_add(&sw_desc->free_list,
&xor_dev->free_sw_desc);
}
diff --git a/drivers/dma/omap-dma.c b/drivers/dma/omap-dma.c
index daf479cce691..8c1665c8fe33 100644
--- a/drivers/dma/omap-dma.c
+++ b/drivers/dma/omap-dma.c
@@ -916,12 +916,6 @@ static struct dma_async_tx_descriptor *omap_dma_prep_slave_sg(
return NULL;
}
- /* When the port_window is used, one frame must cover the window */
- if (port_window) {
- burst = port_window;
- port_window_bytes = port_window * es_bytes[es];
- }
-
/* Now allocate and setup the descriptor. */
d = kzalloc(sizeof(*d) + sglen * sizeof(d->sg[0]), GFP_ATOMIC);
if (!d)
@@ -931,6 +925,21 @@ static struct dma_async_tx_descriptor *omap_dma_prep_slave_sg(
d->dev_addr = dev_addr;
d->es = es;
+ /* When the port_window is used, one frame must cover the window */
+ if (port_window) {
+ burst = port_window;
+ port_window_bytes = port_window * es_bytes[es];
+
+ d->ei = 1;
+ /*
+ * One frame covers the port_window and by configure
+ * the source frame index to be -1 * (port_window - 1)
+ * we instruct the sDMA that after a frame is processed
+ * it should move back to the start of the window.
+ */
+ d->fi = -(port_window_bytes - 1);
+ }
+
d->ccr = c->ccr | CCR_SYNC_FRAME;
if (dir == DMA_DEV_TO_MEM) {
d->csdp = CSDP_DST_BURST_64 | CSDP_DST_PACKED;
@@ -955,14 +964,6 @@ static struct dma_async_tx_descriptor *omap_dma_prep_slave_sg(
d->ccr |= CCR_SRC_AMODE_POSTINC;
if (port_window) {
d->ccr |= CCR_DST_AMODE_DBLIDX;
- d->ei = 1;
- /*
- * One frame covers the port_window and by configure
- * the source frame index to be -1 * (port_window - 1)
- * we instruct the sDMA that after a frame is processed
- * it should move back to the start of the window.
- */
- d->fi = -(port_window_bytes - 1);
if (port_window_bytes >= 64)
d->csdp |= CSDP_DST_BURST_64;
@@ -1018,16 +1019,6 @@ static struct dma_async_tx_descriptor *omap_dma_prep_slave_sg(
osg->addr = sg_dma_address(sgent);
osg->en = en;
osg->fn = sg_dma_len(sgent) / frame_bytes;
- if (port_window && dir == DMA_DEV_TO_MEM) {
- osg->ei = 1;
- /*
- * One frame covers the port_window and by configure
- * the source frame index to be -1 * (port_window - 1)
- * we instruct the sDMA that after a frame is processed
- * it should move back to the start of the window.
- */
- osg->fi = -(port_window_bytes - 1);
- }
if (d->using_ll) {
osg->t2_desc = dma_pool_alloc(od->desc_pool, GFP_ATOMIC,
diff --git a/drivers/dma/pl330.c b/drivers/dma/pl330.c
index 8b0da7fa520d..e90a7a0d760a 100644
--- a/drivers/dma/pl330.c
+++ b/drivers/dma/pl330.c
@@ -3008,7 +3008,8 @@ static int pl330_remove(struct amba_device *adev)
for (i = 0; i < AMBA_NR_IRQS; i++) {
irq = adev->irq[i];
- devm_free_irq(&adev->dev, irq, pl330);
+ if (irq)
+ devm_free_irq(&adev->dev, irq, pl330);
}
dma_async_device_unregister(&pl330->ddma);
diff --git a/drivers/dma/sh/rcar-dmac.c b/drivers/dma/sh/rcar-dmac.c
index db41795fe42a..bd261c9e9664 100644
--- a/drivers/dma/sh/rcar-dmac.c
+++ b/drivers/dma/sh/rcar-dmac.c
@@ -1287,6 +1287,9 @@ static unsigned int rcar_dmac_chan_get_residue(struct rcar_dmac_chan *chan,
if (desc->hwdescs.use) {
dptr = (rcar_dmac_chan_read(chan, RCAR_DMACHCRB) &
RCAR_DMACHCRB_DPTR_MASK) >> RCAR_DMACHCRB_DPTR_SHIFT;
+ if (dptr == 0)
+ dptr = desc->nchunks;
+ dptr--;
WARN_ON(dptr >= desc->nchunks);
} else {
running = desc->running;
diff --git a/drivers/dma/sh/usb-dmac.c b/drivers/dma/sh/usb-dmac.c
index 72c649713ace..31a145154e9f 100644
--- a/drivers/dma/sh/usb-dmac.c
+++ b/drivers/dma/sh/usb-dmac.c
@@ -117,7 +117,7 @@ struct usb_dmac {
#define USB_DMASWR 0x0008
#define USB_DMASWR_SWR (1 << 0)
#define USB_DMAOR 0x0060
-#define USB_DMAOR_AE (1 << 2)
+#define USB_DMAOR_AE (1 << 1)
#define USB_DMAOR_DME (1 << 0)
#define USB_DMASAR 0x0000
diff --git a/drivers/edac/altera_edac.c b/drivers/edac/altera_edac.c
index 7717b094fabb..db75d4b614f7 100644
--- a/drivers/edac/altera_edac.c
+++ b/drivers/edac/altera_edac.c
@@ -214,24 +214,16 @@ static void altr_sdr_mc_create_debugfs_nodes(struct mem_ctl_info *mci)
static unsigned long get_total_mem(void)
{
struct device_node *np = NULL;
- const unsigned int *reg, *reg_end;
- int len, sw, aw;
- unsigned long start, size, total_mem = 0;
+ struct resource res;
+ int ret;
+ unsigned long total_mem = 0;
for_each_node_by_type(np, "memory") {
- aw = of_n_addr_cells(np);
- sw = of_n_size_cells(np);
- reg = (const unsigned int *)of_get_property(np, "reg", &len);
- reg_end = reg + (len / sizeof(u32));
-
- total_mem = 0;
- do {
- start = of_read_number(reg, aw);
- reg += aw;
- size = of_read_number(reg, sw);
- reg += sw;
- total_mem += size;
- } while (reg < reg_end);
+ ret = of_address_to_resource(np, 0, &res);
+ if (ret)
+ continue;
+
+ total_mem += resource_size(&res);
}
edac_dbg(0, "total_mem 0x%lx\n", total_mem);
return total_mem;
@@ -1839,7 +1831,7 @@ static int a10_eccmgr_irqdomain_map(struct irq_domain *d, unsigned int irq,
return 0;
}
-static struct irq_domain_ops a10_eccmgr_ic_ops = {
+static const struct irq_domain_ops a10_eccmgr_ic_ops = {
.map = a10_eccmgr_irqdomain_map,
.xlate = irq_domain_xlate_twocell,
};
diff --git a/drivers/edac/i5000_edac.c b/drivers/edac/i5000_edac.c
index f683919981b0..8f5a56e25bd2 100644
--- a/drivers/edac/i5000_edac.c
+++ b/drivers/edac/i5000_edac.c
@@ -227,7 +227,7 @@
#define NREC_RDWR(x) (((x)>>11) & 1)
#define NREC_RANK(x) (((x)>>8) & 0x7)
#define NRECMEMB 0xC0
-#define NREC_CAS(x) (((x)>>16) & 0xFFFFFF)
+#define NREC_CAS(x) (((x)>>16) & 0xFFF)
#define NREC_RAS(x) ((x) & 0x7FFF)
#define NRECFGLOG 0xC4
#define NREEECFBDA 0xC8
@@ -371,7 +371,7 @@ struct i5000_error_info {
/* These registers are input ONLY if there was a
* Non-Recoverable Error */
u16 nrecmema; /* Non-Recoverable Mem log A */
- u16 nrecmemb; /* Non-Recoverable Mem log B */
+ u32 nrecmemb; /* Non-Recoverable Mem log B */
};
@@ -407,7 +407,7 @@ static void i5000_get_error_info(struct mem_ctl_info *mci,
NERR_FAT_FBD, &info->nerr_fat_fbd);
pci_read_config_word(pvt->branchmap_werrors,
NRECMEMA, &info->nrecmema);
- pci_read_config_word(pvt->branchmap_werrors,
+ pci_read_config_dword(pvt->branchmap_werrors,
NRECMEMB, &info->nrecmemb);
/* Clear the error bits, by writing them back */
diff --git a/drivers/edac/i5400_edac.c b/drivers/edac/i5400_edac.c
index 37a9ba71da44..cd889edc8516 100644
--- a/drivers/edac/i5400_edac.c
+++ b/drivers/edac/i5400_edac.c
@@ -368,7 +368,7 @@ struct i5400_error_info {
/* These registers are input ONLY if there was a Non-Rec Error */
u16 nrecmema; /* Non-Recoverable Mem log A */
- u16 nrecmemb; /* Non-Recoverable Mem log B */
+ u32 nrecmemb; /* Non-Recoverable Mem log B */
};
@@ -458,7 +458,7 @@ static void i5400_get_error_info(struct mem_ctl_info *mci,
NERR_FAT_FBD, &info->nerr_fat_fbd);
pci_read_config_word(pvt->branchmap_werrors,
NRECMEMA, &info->nrecmema);
- pci_read_config_word(pvt->branchmap_werrors,
+ pci_read_config_dword(pvt->branchmap_werrors,
NRECMEMB, &info->nrecmemb);
/* Clear the error bits, by writing them back */
diff --git a/drivers/edac/ie31200_edac.c b/drivers/edac/ie31200_edac.c
index 2733fb5938a4..4260579e6901 100644
--- a/drivers/edac/ie31200_edac.c
+++ b/drivers/edac/ie31200_edac.c
@@ -18,10 +18,12 @@
* 0c04: Xeon E3-1200 v3/4th Gen Core Processor DRAM Controller
* 0c08: Xeon E3-1200 v3 Processor DRAM Controller
* 1918: Xeon E3-1200 v5 Skylake Host Bridge/DRAM Registers
+ * 5918: Xeon E3-1200 Xeon E3-1200 v6/7th Gen Core Processor Host Bridge/DRAM Registers
*
* Based on Intel specification:
* http://www.intel.com/content/dam/www/public/us/en/documents/datasheets/xeon-e3-1200v3-vol-2-datasheet.pdf
* http://www.intel.com/content/www/us/en/processors/xeon/xeon-e3-1200-family-vol-2-datasheet.html
+ * http://www.intel.com/content/www/us/en/processors/core/7th-gen-core-family-mobile-h-processor-lines-datasheet-vol-2.html
*
* According to the above datasheet (p.16):
* "
@@ -57,6 +59,7 @@
#define PCI_DEVICE_ID_INTEL_IE31200_HB_6 0x0c04
#define PCI_DEVICE_ID_INTEL_IE31200_HB_7 0x0c08
#define PCI_DEVICE_ID_INTEL_IE31200_HB_8 0x1918
+#define PCI_DEVICE_ID_INTEL_IE31200_HB_9 0x5918
#define IE31200_DIMMS 4
#define IE31200_RANKS 8
@@ -376,7 +379,12 @@ static int ie31200_probe1(struct pci_dev *pdev, int dev_idx)
void __iomem *window;
struct ie31200_priv *priv;
u32 addr_decode, mad_offset;
- bool skl = (pdev->device == PCI_DEVICE_ID_INTEL_IE31200_HB_8);
+
+ /*
+ * Kaby Lake seems to work like Skylake. Please re-visit this logic
+ * when adding new CPU support.
+ */
+ bool skl = (pdev->device >= PCI_DEVICE_ID_INTEL_IE31200_HB_8);
edac_dbg(0, "MC:\n");
@@ -560,6 +568,9 @@ static const struct pci_device_id ie31200_pci_tbl[] = {
PCI_VEND_DEV(INTEL, IE31200_HB_8), PCI_ANY_ID, PCI_ANY_ID, 0, 0,
IE31200},
{
+ PCI_VEND_DEV(INTEL, IE31200_HB_9), PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+ IE31200},
+ {
0,
} /* 0 terminated list. */
};
diff --git a/drivers/edac/mce_amd.c b/drivers/edac/mce_amd.c
index ba35b7ea3686..9a2658a256a9 100644
--- a/drivers/edac/mce_amd.c
+++ b/drivers/edac/mce_amd.c
@@ -161,7 +161,7 @@ static const char * const smca_ls_mce_desc[] = {
"Sys Read data error thread 0",
"Sys read data error thread 1",
"DC tag error type 2",
- "DC data error type 1 (poison comsumption)",
+ "DC data error type 1 (poison consumption)",
"DC data error type 2",
"DC data error type 3",
"DC tag error type 4",
diff --git a/drivers/edac/mv64x60_edac.c b/drivers/edac/mv64x60_edac.c
index 14b7e7b71eaa..d3650df94fe8 100644
--- a/drivers/edac/mv64x60_edac.c
+++ b/drivers/edac/mv64x60_edac.c
@@ -32,21 +32,21 @@ static void mv64x60_pci_check(struct edac_pci_ctl_info *pci)
struct mv64x60_pci_pdata *pdata = pci->pvt_info;
u32 cause;
- cause = in_le32(pdata->pci_vbase + MV64X60_PCI_ERROR_CAUSE);
+ cause = readl(pdata->pci_vbase + MV64X60_PCI_ERROR_CAUSE);
if (!cause)
return;
printk(KERN_ERR "Error in PCI %d Interface\n", pdata->pci_hose);
printk(KERN_ERR "Cause register: 0x%08x\n", cause);
printk(KERN_ERR "Address Low: 0x%08x\n",
- in_le32(pdata->pci_vbase + MV64X60_PCI_ERROR_ADDR_LO));
+ readl(pdata->pci_vbase + MV64X60_PCI_ERROR_ADDR_LO));
printk(KERN_ERR "Address High: 0x%08x\n",
- in_le32(pdata->pci_vbase + MV64X60_PCI_ERROR_ADDR_HI));
+ readl(pdata->pci_vbase + MV64X60_PCI_ERROR_ADDR_HI));
printk(KERN_ERR "Attribute: 0x%08x\n",
- in_le32(pdata->pci_vbase + MV64X60_PCI_ERROR_ATTR));
+ readl(pdata->pci_vbase + MV64X60_PCI_ERROR_ATTR));
printk(KERN_ERR "Command: 0x%08x\n",
- in_le32(pdata->pci_vbase + MV64X60_PCI_ERROR_CMD));
- out_le32(pdata->pci_vbase + MV64X60_PCI_ERROR_CAUSE, ~cause);
+ readl(pdata->pci_vbase + MV64X60_PCI_ERROR_CMD));
+ writel(~cause, pdata->pci_vbase + MV64X60_PCI_ERROR_CAUSE);
if (cause & MV64X60_PCI_PE_MASK)
edac_pci_handle_pe(pci, pci->ctl_name);
@@ -61,7 +61,7 @@ static irqreturn_t mv64x60_pci_isr(int irq, void *dev_id)
struct mv64x60_pci_pdata *pdata = pci->pvt_info;
u32 val;
- val = in_le32(pdata->pci_vbase + MV64X60_PCI_ERROR_CAUSE);
+ val = readl(pdata->pci_vbase + MV64X60_PCI_ERROR_CAUSE);
if (!val)
return IRQ_NONE;
@@ -93,7 +93,7 @@ static int __init mv64x60_pci_fixup(struct platform_device *pdev)
if (!pci_serr)
return -ENOMEM;
- out_le32(pci_serr, in_le32(pci_serr) & ~0x1);
+ writel(readl(pci_serr) & ~0x1, pci_serr);
iounmap(pci_serr);
return 0;
@@ -116,7 +116,7 @@ static int mv64x60_pci_err_probe(struct platform_device *pdev)
pdata = pci->pvt_info;
pdata->pci_hose = pdev->id;
- pdata->name = "mpc85xx_pci_err";
+ pdata->name = "mv64x60_pci_err";
platform_set_drvdata(pdev, pci);
pci->dev = &pdev->dev;
pci->dev_name = dev_name(&pdev->dev);
@@ -161,10 +161,10 @@ static int mv64x60_pci_err_probe(struct platform_device *pdev)
goto err;
}
- out_le32(pdata->pci_vbase + MV64X60_PCI_ERROR_CAUSE, 0);
- out_le32(pdata->pci_vbase + MV64X60_PCI_ERROR_MASK, 0);
- out_le32(pdata->pci_vbase + MV64X60_PCI_ERROR_MASK,
- MV64X60_PCIx_ERR_MASK_VAL);
+ writel(0, pdata->pci_vbase + MV64X60_PCI_ERROR_CAUSE);
+ writel(0, pdata->pci_vbase + MV64X60_PCI_ERROR_MASK);
+ writel(MV64X60_PCIx_ERR_MASK_VAL,
+ pdata->pci_vbase + MV64X60_PCI_ERROR_MASK);
if (edac_pci_add_device(pci, pdata->edac_idx) > 0) {
edac_dbg(3, "failed edac_pci_add_device()\n");
@@ -233,23 +233,23 @@ static void mv64x60_sram_check(struct edac_device_ctl_info *edac_dev)
struct mv64x60_sram_pdata *pdata = edac_dev->pvt_info;
u32 cause;
- cause = in_le32(pdata->sram_vbase + MV64X60_SRAM_ERR_CAUSE);
+ cause = readl(pdata->sram_vbase + MV64X60_SRAM_ERR_CAUSE);
if (!cause)
return;
printk(KERN_ERR "Error in internal SRAM\n");
printk(KERN_ERR "Cause register: 0x%08x\n", cause);
printk(KERN_ERR "Address Low: 0x%08x\n",
- in_le32(pdata->sram_vbase + MV64X60_SRAM_ERR_ADDR_LO));
+ readl(pdata->sram_vbase + MV64X60_SRAM_ERR_ADDR_LO));
printk(KERN_ERR "Address High: 0x%08x\n",
- in_le32(pdata->sram_vbase + MV64X60_SRAM_ERR_ADDR_HI));
+ readl(pdata->sram_vbase + MV64X60_SRAM_ERR_ADDR_HI));
printk(KERN_ERR "Data Low: 0x%08x\n",
- in_le32(pdata->sram_vbase + MV64X60_SRAM_ERR_DATA_LO));
+ readl(pdata->sram_vbase + MV64X60_SRAM_ERR_DATA_LO));
printk(KERN_ERR "Data High: 0x%08x\n",
- in_le32(pdata->sram_vbase + MV64X60_SRAM_ERR_DATA_HI));
+ readl(pdata->sram_vbase + MV64X60_SRAM_ERR_DATA_HI));
printk(KERN_ERR "Parity: 0x%08x\n",
- in_le32(pdata->sram_vbase + MV64X60_SRAM_ERR_PARITY));
- out_le32(pdata->sram_vbase + MV64X60_SRAM_ERR_CAUSE, 0);
+ readl(pdata->sram_vbase + MV64X60_SRAM_ERR_PARITY));
+ writel(0, pdata->sram_vbase + MV64X60_SRAM_ERR_CAUSE);
edac_device_handle_ue(edac_dev, 0, 0, edac_dev->ctl_name);
}
@@ -260,7 +260,7 @@ static irqreturn_t mv64x60_sram_isr(int irq, void *dev_id)
struct mv64x60_sram_pdata *pdata = edac_dev->pvt_info;
u32 cause;
- cause = in_le32(pdata->sram_vbase + MV64X60_SRAM_ERR_CAUSE);
+ cause = readl(pdata->sram_vbase + MV64X60_SRAM_ERR_CAUSE);
if (!cause)
return IRQ_NONE;
@@ -322,7 +322,7 @@ static int mv64x60_sram_err_probe(struct platform_device *pdev)
}
/* setup SRAM err registers */
- out_le32(pdata->sram_vbase + MV64X60_SRAM_ERR_CAUSE, 0);
+ writel(0, pdata->sram_vbase + MV64X60_SRAM_ERR_CAUSE);
edac_dev->mod_name = EDAC_MOD_STR;
edac_dev->ctl_name = pdata->name;
@@ -398,7 +398,7 @@ static void mv64x60_cpu_check(struct edac_device_ctl_info *edac_dev)
struct mv64x60_cpu_pdata *pdata = edac_dev->pvt_info;
u32 cause;
- cause = in_le32(pdata->cpu_vbase[1] + MV64x60_CPU_ERR_CAUSE) &
+ cause = readl(pdata->cpu_vbase[1] + MV64x60_CPU_ERR_CAUSE) &
MV64x60_CPU_CAUSE_MASK;
if (!cause)
return;
@@ -406,16 +406,16 @@ static void mv64x60_cpu_check(struct edac_device_ctl_info *edac_dev)
printk(KERN_ERR "Error on CPU interface\n");
printk(KERN_ERR "Cause register: 0x%08x\n", cause);
printk(KERN_ERR "Address Low: 0x%08x\n",
- in_le32(pdata->cpu_vbase[0] + MV64x60_CPU_ERR_ADDR_LO));
+ readl(pdata->cpu_vbase[0] + MV64x60_CPU_ERR_ADDR_LO));
printk(KERN_ERR "Address High: 0x%08x\n",
- in_le32(pdata->cpu_vbase[0] + MV64x60_CPU_ERR_ADDR_HI));
+ readl(pdata->cpu_vbase[0] + MV64x60_CPU_ERR_ADDR_HI));
printk(KERN_ERR "Data Low: 0x%08x\n",
- in_le32(pdata->cpu_vbase[1] + MV64x60_CPU_ERR_DATA_LO));
+ readl(pdata->cpu_vbase[1] + MV64x60_CPU_ERR_DATA_LO));
printk(KERN_ERR "Data High: 0x%08x\n",
- in_le32(pdata->cpu_vbase[1] + MV64x60_CPU_ERR_DATA_HI));
+ readl(pdata->cpu_vbase[1] + MV64x60_CPU_ERR_DATA_HI));
printk(KERN_ERR "Parity: 0x%08x\n",
- in_le32(pdata->cpu_vbase[1] + MV64x60_CPU_ERR_PARITY));
- out_le32(pdata->cpu_vbase[1] + MV64x60_CPU_ERR_CAUSE, 0);
+ readl(pdata->cpu_vbase[1] + MV64x60_CPU_ERR_PARITY));
+ writel(0, pdata->cpu_vbase[1] + MV64x60_CPU_ERR_CAUSE);
edac_device_handle_ue(edac_dev, 0, 0, edac_dev->ctl_name);
}
@@ -426,7 +426,7 @@ static irqreturn_t mv64x60_cpu_isr(int irq, void *dev_id)
struct mv64x60_cpu_pdata *pdata = edac_dev->pvt_info;
u32 cause;
- cause = in_le32(pdata->cpu_vbase[1] + MV64x60_CPU_ERR_CAUSE) &
+ cause = readl(pdata->cpu_vbase[1] + MV64x60_CPU_ERR_CAUSE) &
MV64x60_CPU_CAUSE_MASK;
if (!cause)
return IRQ_NONE;
@@ -515,9 +515,9 @@ static int mv64x60_cpu_err_probe(struct platform_device *pdev)
}
/* setup CPU err registers */
- out_le32(pdata->cpu_vbase[1] + MV64x60_CPU_ERR_CAUSE, 0);
- out_le32(pdata->cpu_vbase[1] + MV64x60_CPU_ERR_MASK, 0);
- out_le32(pdata->cpu_vbase[1] + MV64x60_CPU_ERR_MASK, 0x000000ff);
+ writel(0, pdata->cpu_vbase[1] + MV64x60_CPU_ERR_CAUSE);
+ writel(0, pdata->cpu_vbase[1] + MV64x60_CPU_ERR_MASK);
+ writel(0x000000ff, pdata->cpu_vbase[1] + MV64x60_CPU_ERR_MASK);
edac_dev->mod_name = EDAC_MOD_STR;
edac_dev->ctl_name = pdata->name;
@@ -596,13 +596,13 @@ static void mv64x60_mc_check(struct mem_ctl_info *mci)
u32 comp_ecc;
u32 syndrome;
- reg = in_le32(pdata->mc_vbase + MV64X60_SDRAM_ERR_ADDR);
+ reg = readl(pdata->mc_vbase + MV64X60_SDRAM_ERR_ADDR);
if (!reg)
return;
err_addr = reg & ~0x3;
- sdram_ecc = in_le32(pdata->mc_vbase + MV64X60_SDRAM_ERR_ECC_RCVD);
- comp_ecc = in_le32(pdata->mc_vbase + MV64X60_SDRAM_ERR_ECC_CALC);
+ sdram_ecc = readl(pdata->mc_vbase + MV64X60_SDRAM_ERR_ECC_RCVD);
+ comp_ecc = readl(pdata->mc_vbase + MV64X60_SDRAM_ERR_ECC_CALC);
syndrome = sdram_ecc ^ comp_ecc;
/* first bit clear in ECC Err Reg, 1 bit error, correctable by HW */
@@ -620,7 +620,7 @@ static void mv64x60_mc_check(struct mem_ctl_info *mci)
mci->ctl_name, "");
/* clear the error */
- out_le32(pdata->mc_vbase + MV64X60_SDRAM_ERR_ADDR, 0);
+ writel(0, pdata->mc_vbase + MV64X60_SDRAM_ERR_ADDR);
}
static irqreturn_t mv64x60_mc_isr(int irq, void *dev_id)
@@ -629,7 +629,7 @@ static irqreturn_t mv64x60_mc_isr(int irq, void *dev_id)
struct mv64x60_mc_pdata *pdata = mci->pvt_info;
u32 reg;
- reg = in_le32(pdata->mc_vbase + MV64X60_SDRAM_ERR_ADDR);
+ reg = readl(pdata->mc_vbase + MV64X60_SDRAM_ERR_ADDR);
if (!reg)
return IRQ_NONE;
@@ -664,7 +664,7 @@ static void mv64x60_init_csrows(struct mem_ctl_info *mci,
get_total_mem(pdata);
- ctl = in_le32(pdata->mc_vbase + MV64X60_SDRAM_CONFIG);
+ ctl = readl(pdata->mc_vbase + MV64X60_SDRAM_CONFIG);
csrow = mci->csrows[0];
dimm = csrow->channels[0]->dimm;
@@ -753,7 +753,7 @@ static int mv64x60_mc_err_probe(struct platform_device *pdev)
goto err;
}
- ctl = in_le32(pdata->mc_vbase + MV64X60_SDRAM_CONFIG);
+ ctl = readl(pdata->mc_vbase + MV64X60_SDRAM_CONFIG);
if (!(ctl & MV64X60_SDRAM_ECC)) {
/* Non-ECC RAM? */
printk(KERN_WARNING "%s: No ECC DIMMs discovered\n", __func__);
@@ -779,10 +779,10 @@ static int mv64x60_mc_err_probe(struct platform_device *pdev)
mv64x60_init_csrows(mci, pdata);
/* setup MC registers */
- out_le32(pdata->mc_vbase + MV64X60_SDRAM_ERR_ADDR, 0);
- ctl = in_le32(pdata->mc_vbase + MV64X60_SDRAM_ERR_ECC_CNTL);
+ writel(0, pdata->mc_vbase + MV64X60_SDRAM_ERR_ADDR);
+ ctl = readl(pdata->mc_vbase + MV64X60_SDRAM_ERR_ECC_CNTL);
ctl = (ctl & 0xff00ffff) | 0x10000;
- out_le32(pdata->mc_vbase + MV64X60_SDRAM_ERR_ECC_CNTL, ctl);
+ writel(ctl, pdata->mc_vbase + MV64X60_SDRAM_ERR_ECC_CNTL);
res = edac_mc_add_mc(mci);
if (res) {
@@ -853,10 +853,10 @@ static struct platform_driver * const drivers[] = {
static int __init mv64x60_edac_init(void)
{
- int ret = 0;
printk(KERN_INFO "Marvell MV64x60 EDAC driver " MV64x60_REVISION "\n");
printk(KERN_INFO "\t(C) 2006-2007 MontaVista Software\n");
+
/* make sure error reporting method is sane */
switch (edac_op_state) {
case EDAC_OPSTATE_POLL:
diff --git a/drivers/edac/pnd2_edac.c b/drivers/edac/pnd2_edac.c
index 1cad5a9af8d0..8e599490f6de 100644
--- a/drivers/edac/pnd2_edac.c
+++ b/drivers/edac/pnd2_edac.c
@@ -131,7 +131,7 @@ static struct mem_ctl_info *pnd2_mci;
#ifdef CONFIG_X86_INTEL_SBI_APL
#include "linux/platform_data/sbi_apl.h"
-int sbi_send(int port, int off, int op, u32 *data)
+static int sbi_send(int port, int off, int op, u32 *data)
{
struct sbi_apl_message sbi_arg;
int ret, read = 0;
@@ -160,7 +160,7 @@ int sbi_send(int port, int off, int op, u32 *data)
return ret;
}
#else
-int sbi_send(int port, int off, int op, u32 *data)
+static int sbi_send(int port, int off, int op, u32 *data)
{
return -EUNATCH;
}
@@ -168,14 +168,15 @@ int sbi_send(int port, int off, int op, u32 *data)
static int apl_rd_reg(int port, int off, int op, void *data, size_t sz, char *name)
{
- int ret = 0;
+ int ret = 0;
edac_dbg(2, "Read %s port=%x off=%x op=%x\n", name, port, off, op);
switch (sz) {
case 8:
ret = sbi_send(port, off + 4, op, (u32 *)(data + 4));
+ /* fall through */
case 4:
- ret = sbi_send(port, off, op, (u32 *)data);
+ ret |= sbi_send(port, off, op, (u32 *)data);
pnd2_printk(KERN_DEBUG, "%s=%x%08x ret=%d\n", name,
sz == 8 ? *((u32 *)(data + 4)) : 0, *((u32 *)data), ret);
break;
@@ -423,16 +424,21 @@ static void dnv_mk_region(char *name, struct region *rp, void *asym)
static int apl_get_registers(void)
{
+ int ret = -ENODEV;
int i;
if (RD_REG(&asym_2way, b_cr_asym_2way_mem_region_mchbar))
return -ENODEV;
+ /*
+ * RD_REGP() will fail for unpopulated or non-existent
+ * DIMM slots. Return success if we find at least one DIMM.
+ */
for (i = 0; i < APL_NUM_CHANNELS; i++)
- if (RD_REGP(&drp0[i], d_cr_drp0, apl_dports[i]))
- return -ENODEV;
+ if (!RD_REGP(&drp0[i], d_cr_drp0, apl_dports[i]))
+ ret = 0;
- return 0;
+ return ret;
}
static int dnv_get_registers(void)
diff --git a/drivers/edac/sb_edac.c b/drivers/edac/sb_edac.c
index ea21cb651b3c..80d860cb0746 100644
--- a/drivers/edac/sb_edac.c
+++ b/drivers/edac/sb_edac.c
@@ -35,7 +35,7 @@ static LIST_HEAD(sbridge_edac_list);
/*
* Alter this version for the module when modifications are made
*/
-#define SBRIDGE_REVISION " Ver: 1.1.1 "
+#define SBRIDGE_REVISION " Ver: 1.1.2 "
#define EDAC_MOD_STR "sbridge_edac"
/*
@@ -279,7 +279,7 @@ static const u32 correrrthrsld[] = {
* sbridge structs
*/
-#define NUM_CHANNELS 8 /* 2MC per socket, four chan per MC */
+#define NUM_CHANNELS 4 /* Max channels per MC */
#define MAX_DIMMS 3 /* Max DIMMS per channel */
#define KNL_MAX_CHAS 38 /* KNL max num. of Cache Home Agents */
#define KNL_MAX_CHANNELS 6 /* KNL max num. of PCI channels */
@@ -294,6 +294,12 @@ enum type {
KNIGHTS_LANDING,
};
+enum domain {
+ IMC0 = 0,
+ IMC1,
+ SOCK,
+};
+
struct sbridge_pvt;
struct sbridge_info {
enum type type;
@@ -324,11 +330,14 @@ struct sbridge_channel {
struct pci_id_descr {
int dev_id;
int optional;
+ enum domain dom;
};
struct pci_id_table {
const struct pci_id_descr *descr;
- int n_devs;
+ int n_devs_per_imc;
+ int n_devs_per_sock;
+ int n_imcs_per_sock;
enum type type;
};
@@ -337,7 +346,9 @@ struct sbridge_dev {
u8 bus, mc;
u8 node_id, source_id;
struct pci_dev **pdev;
+ enum domain dom;
int n_devs;
+ int i_devs;
struct mem_ctl_info *mci;
};
@@ -352,11 +363,12 @@ struct knl_pvt {
};
struct sbridge_pvt {
- struct pci_dev *pci_ta, *pci_ddrio, *pci_ras;
+ /* Devices per socket */
+ struct pci_dev *pci_ddrio;
struct pci_dev *pci_sad0, *pci_sad1;
- struct pci_dev *pci_ha0, *pci_ha1;
struct pci_dev *pci_br0, *pci_br1;
- struct pci_dev *pci_ha1_ta;
+ /* Devices per memory controller */
+ struct pci_dev *pci_ha, *pci_ta, *pci_ras;
struct pci_dev *pci_tad[NUM_CHANNELS];
struct sbridge_dev *sbridge_dev;
@@ -373,39 +385,42 @@ struct sbridge_pvt {
struct knl_pvt knl;
};
-#define PCI_DESCR(device_id, opt) \
+#define PCI_DESCR(device_id, opt, domain) \
.dev_id = (device_id), \
- .optional = opt
+ .optional = opt, \
+ .dom = domain
static const struct pci_id_descr pci_dev_descr_sbridge[] = {
/* Processor Home Agent */
- { PCI_DESCR(PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_HA0, 0) },
+ { PCI_DESCR(PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_HA0, 0, IMC0) },
/* Memory controller */
- { PCI_DESCR(PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_TA, 0) },
- { PCI_DESCR(PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_RAS, 0) },
- { PCI_DESCR(PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_TAD0, 0) },
- { PCI_DESCR(PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_TAD1, 0) },
- { PCI_DESCR(PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_TAD2, 0) },
- { PCI_DESCR(PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_TAD3, 0) },
- { PCI_DESCR(PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_DDRIO, 1) },
+ { PCI_DESCR(PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_TA, 0, IMC0) },
+ { PCI_DESCR(PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_RAS, 0, IMC0) },
+ { PCI_DESCR(PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_TAD0, 0, IMC0) },
+ { PCI_DESCR(PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_TAD1, 0, IMC0) },
+ { PCI_DESCR(PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_TAD2, 0, IMC0) },
+ { PCI_DESCR(PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_TAD3, 0, IMC0) },
+ { PCI_DESCR(PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_DDRIO, 1, SOCK) },
/* System Address Decoder */
- { PCI_DESCR(PCI_DEVICE_ID_INTEL_SBRIDGE_SAD0, 0) },
- { PCI_DESCR(PCI_DEVICE_ID_INTEL_SBRIDGE_SAD1, 0) },
+ { PCI_DESCR(PCI_DEVICE_ID_INTEL_SBRIDGE_SAD0, 0, SOCK) },
+ { PCI_DESCR(PCI_DEVICE_ID_INTEL_SBRIDGE_SAD1, 0, SOCK) },
/* Broadcast Registers */
- { PCI_DESCR(PCI_DEVICE_ID_INTEL_SBRIDGE_BR, 0) },
+ { PCI_DESCR(PCI_DEVICE_ID_INTEL_SBRIDGE_BR, 0, SOCK) },
};
-#define PCI_ID_TABLE_ENTRY(A, T) { \
+#define PCI_ID_TABLE_ENTRY(A, N, M, T) { \
.descr = A, \
- .n_devs = ARRAY_SIZE(A), \
+ .n_devs_per_imc = N, \
+ .n_devs_per_sock = ARRAY_SIZE(A), \
+ .n_imcs_per_sock = M, \
.type = T \
}
static const struct pci_id_table pci_dev_descr_sbridge_table[] = {
- PCI_ID_TABLE_ENTRY(pci_dev_descr_sbridge, SANDY_BRIDGE),
+ PCI_ID_TABLE_ENTRY(pci_dev_descr_sbridge, ARRAY_SIZE(pci_dev_descr_sbridge), 1, SANDY_BRIDGE),
{0,} /* 0 terminated list. */
};
@@ -439,40 +454,39 @@ static const struct pci_id_table pci_dev_descr_sbridge_table[] = {
static const struct pci_id_descr pci_dev_descr_ibridge[] = {
/* Processor Home Agent */
- { PCI_DESCR(PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA0, 0) },
+ { PCI_DESCR(PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA0, 0, IMC0) },
/* Memory controller */
- { PCI_DESCR(PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA0_TA, 0) },
- { PCI_DESCR(PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA0_RAS, 0) },
- { PCI_DESCR(PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA0_TAD0, 0) },
- { PCI_DESCR(PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA0_TAD1, 0) },
- { PCI_DESCR(PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA0_TAD2, 0) },
- { PCI_DESCR(PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA0_TAD3, 0) },
+ { PCI_DESCR(PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA0_TA, 0, IMC0) },
+ { PCI_DESCR(PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA0_RAS, 0, IMC0) },
+ { PCI_DESCR(PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA0_TAD0, 0, IMC0) },
+ { PCI_DESCR(PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA0_TAD1, 0, IMC0) },
+ { PCI_DESCR(PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA0_TAD2, 0, IMC0) },
+ { PCI_DESCR(PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA0_TAD3, 0, IMC0) },
+
+ /* Optional, mode 2HA */
+ { PCI_DESCR(PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA1, 1, IMC1) },
+ { PCI_DESCR(PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA1_TA, 1, IMC1) },
+ { PCI_DESCR(PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA1_RAS, 1, IMC1) },
+ { PCI_DESCR(PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA1_TAD0, 1, IMC1) },
+ { PCI_DESCR(PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA1_TAD1, 1, IMC1) },
+ { PCI_DESCR(PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA1_TAD2, 1, IMC1) },
+ { PCI_DESCR(PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA1_TAD3, 1, IMC1) },
+
+ { PCI_DESCR(PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_1HA_DDRIO0, 1, SOCK) },
+ { PCI_DESCR(PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_2HA_DDRIO0, 1, SOCK) },
/* System Address Decoder */
- { PCI_DESCR(PCI_DEVICE_ID_INTEL_IBRIDGE_SAD, 0) },
+ { PCI_DESCR(PCI_DEVICE_ID_INTEL_IBRIDGE_SAD, 0, SOCK) },
/* Broadcast Registers */
- { PCI_DESCR(PCI_DEVICE_ID_INTEL_IBRIDGE_BR0, 1) },
- { PCI_DESCR(PCI_DEVICE_ID_INTEL_IBRIDGE_BR1, 0) },
+ { PCI_DESCR(PCI_DEVICE_ID_INTEL_IBRIDGE_BR0, 1, SOCK) },
+ { PCI_DESCR(PCI_DEVICE_ID_INTEL_IBRIDGE_BR1, 0, SOCK) },
- /* Optional, mode 2HA */
- { PCI_DESCR(PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA1, 1) },
-#if 0
- { PCI_DESCR(PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA1_TA, 1) },
- { PCI_DESCR(PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA1_RAS, 1) },
-#endif
- { PCI_DESCR(PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA1_TAD0, 1) },
- { PCI_DESCR(PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA1_TAD1, 1) },
- { PCI_DESCR(PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA1_TAD2, 1) },
- { PCI_DESCR(PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA1_TAD3, 1) },
-
- { PCI_DESCR(PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_1HA_DDRIO0, 1) },
- { PCI_DESCR(PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_2HA_DDRIO0, 1) },
};
static const struct pci_id_table pci_dev_descr_ibridge_table[] = {
- PCI_ID_TABLE_ENTRY(pci_dev_descr_ibridge, IVY_BRIDGE),
+ PCI_ID_TABLE_ENTRY(pci_dev_descr_ibridge, 12, 2, IVY_BRIDGE),
{0,} /* 0 terminated list. */
};
@@ -498,9 +512,9 @@ static const struct pci_id_table pci_dev_descr_ibridge_table[] = {
#define PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA0 0x2fa0
#define PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA1 0x2f60
#define PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA0_TA 0x2fa8
-#define PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA0_THERMAL 0x2f71
+#define PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA0_TM 0x2f71
#define PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA1_TA 0x2f68
-#define PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA1_THERMAL 0x2f79
+#define PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA1_TM 0x2f79
#define PCI_DEVICE_ID_INTEL_HASWELL_IMC_CBO_SAD0 0x2ffc
#define PCI_DEVICE_ID_INTEL_HASWELL_IMC_CBO_SAD1 0x2ffd
#define PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA0_TAD0 0x2faa
@@ -517,35 +531,33 @@ static const struct pci_id_table pci_dev_descr_ibridge_table[] = {
#define PCI_DEVICE_ID_INTEL_HASWELL_IMC_DDRIO3 0x2fbb
static const struct pci_id_descr pci_dev_descr_haswell[] = {
/* first item must be the HA */
- { PCI_DESCR(PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA0, 0) },
-
- { PCI_DESCR(PCI_DEVICE_ID_INTEL_HASWELL_IMC_CBO_SAD0, 0) },
- { PCI_DESCR(PCI_DEVICE_ID_INTEL_HASWELL_IMC_CBO_SAD1, 0) },
-
- { PCI_DESCR(PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA1, 1) },
-
- { PCI_DESCR(PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA0_TA, 0) },
- { PCI_DESCR(PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA0_THERMAL, 0) },
- { PCI_DESCR(PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA0_TAD0, 0) },
- { PCI_DESCR(PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA0_TAD1, 0) },
- { PCI_DESCR(PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA0_TAD2, 1) },
- { PCI_DESCR(PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA0_TAD3, 1) },
-
- { PCI_DESCR(PCI_DEVICE_ID_INTEL_HASWELL_IMC_DDRIO0, 1) },
- { PCI_DESCR(PCI_DEVICE_ID_INTEL_HASWELL_IMC_DDRIO1, 1) },
- { PCI_DESCR(PCI_DEVICE_ID_INTEL_HASWELL_IMC_DDRIO2, 1) },
- { PCI_DESCR(PCI_DEVICE_ID_INTEL_HASWELL_IMC_DDRIO3, 1) },
-
- { PCI_DESCR(PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA1_TA, 1) },
- { PCI_DESCR(PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA1_THERMAL, 1) },
- { PCI_DESCR(PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA1_TAD0, 1) },
- { PCI_DESCR(PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA1_TAD1, 1) },
- { PCI_DESCR(PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA1_TAD2, 1) },
- { PCI_DESCR(PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA1_TAD3, 1) },
+ { PCI_DESCR(PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA0, 0, IMC0) },
+ { PCI_DESCR(PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA1, 1, IMC1) },
+
+ { PCI_DESCR(PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA0_TA, 0, IMC0) },
+ { PCI_DESCR(PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA0_TM, 0, IMC0) },
+ { PCI_DESCR(PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA0_TAD0, 0, IMC0) },
+ { PCI_DESCR(PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA0_TAD1, 0, IMC0) },
+ { PCI_DESCR(PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA0_TAD2, 1, IMC0) },
+ { PCI_DESCR(PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA0_TAD3, 1, IMC0) },
+
+ { PCI_DESCR(PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA1_TA, 1, IMC1) },
+ { PCI_DESCR(PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA1_TM, 1, IMC1) },
+ { PCI_DESCR(PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA1_TAD0, 1, IMC1) },
+ { PCI_DESCR(PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA1_TAD1, 1, IMC1) },
+ { PCI_DESCR(PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA1_TAD2, 1, IMC1) },
+ { PCI_DESCR(PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA1_TAD3, 1, IMC1) },
+
+ { PCI_DESCR(PCI_DEVICE_ID_INTEL_HASWELL_IMC_CBO_SAD0, 0, SOCK) },
+ { PCI_DESCR(PCI_DEVICE_ID_INTEL_HASWELL_IMC_CBO_SAD1, 0, SOCK) },
+ { PCI_DESCR(PCI_DEVICE_ID_INTEL_HASWELL_IMC_DDRIO0, 1, SOCK) },
+ { PCI_DESCR(PCI_DEVICE_ID_INTEL_HASWELL_IMC_DDRIO1, 1, SOCK) },
+ { PCI_DESCR(PCI_DEVICE_ID_INTEL_HASWELL_IMC_DDRIO2, 1, SOCK) },
+ { PCI_DESCR(PCI_DEVICE_ID_INTEL_HASWELL_IMC_DDRIO3, 1, SOCK) },
};
static const struct pci_id_table pci_dev_descr_haswell_table[] = {
- PCI_ID_TABLE_ENTRY(pci_dev_descr_haswell, HASWELL),
+ PCI_ID_TABLE_ENTRY(pci_dev_descr_haswell, 13, 2, HASWELL),
{0,} /* 0 terminated list. */
};
@@ -559,7 +571,7 @@ static const struct pci_id_table pci_dev_descr_haswell_table[] = {
/* Memory controller, TAD tables, error injection - 2-8-0, 2-9-0 (2 of these) */
#define PCI_DEVICE_ID_INTEL_KNL_IMC_MC 0x7840
/* DRAM channel stuff; bank addrs, dimmmtr, etc.. 2-8-2 - 2-9-4 (6 of these) */
-#define PCI_DEVICE_ID_INTEL_KNL_IMC_CHANNEL 0x7843
+#define PCI_DEVICE_ID_INTEL_KNL_IMC_CHAN 0x7843
/* kdrwdbu TAD limits/offsets, MCMTR - 2-10-1, 2-11-1 (2 of these) */
#define PCI_DEVICE_ID_INTEL_KNL_IMC_TA 0x7844
/* CHA broadcast registers, dram rules - 1-29-0 (1 of these) */
@@ -579,17 +591,17 @@ static const struct pci_id_table pci_dev_descr_haswell_table[] = {
*/
static const struct pci_id_descr pci_dev_descr_knl[] = {
- [0] = { PCI_DESCR(PCI_DEVICE_ID_INTEL_KNL_IMC_SAD0, 0) },
- [1] = { PCI_DESCR(PCI_DEVICE_ID_INTEL_KNL_IMC_SAD1, 0) },
- [2 ... 3] = { PCI_DESCR(PCI_DEVICE_ID_INTEL_KNL_IMC_MC, 0)},
- [4 ... 41] = { PCI_DESCR(PCI_DEVICE_ID_INTEL_KNL_IMC_CHA, 0) },
- [42 ... 47] = { PCI_DESCR(PCI_DEVICE_ID_INTEL_KNL_IMC_CHANNEL, 0) },
- [48] = { PCI_DESCR(PCI_DEVICE_ID_INTEL_KNL_IMC_TA, 0) },
- [49] = { PCI_DESCR(PCI_DEVICE_ID_INTEL_KNL_IMC_TOLHM, 0) },
+ [0 ... 1] = { PCI_DESCR(PCI_DEVICE_ID_INTEL_KNL_IMC_MC, 0, IMC0)},
+ [2 ... 7] = { PCI_DESCR(PCI_DEVICE_ID_INTEL_KNL_IMC_CHAN, 0, IMC0) },
+ [8] = { PCI_DESCR(PCI_DEVICE_ID_INTEL_KNL_IMC_TA, 0, IMC0) },
+ [9] = { PCI_DESCR(PCI_DEVICE_ID_INTEL_KNL_IMC_TOLHM, 0, IMC0) },
+ [10] = { PCI_DESCR(PCI_DEVICE_ID_INTEL_KNL_IMC_SAD0, 0, SOCK) },
+ [11] = { PCI_DESCR(PCI_DEVICE_ID_INTEL_KNL_IMC_SAD1, 0, SOCK) },
+ [12 ... 49] = { PCI_DESCR(PCI_DEVICE_ID_INTEL_KNL_IMC_CHA, 0, SOCK) },
};
static const struct pci_id_table pci_dev_descr_knl_table[] = {
- PCI_ID_TABLE_ENTRY(pci_dev_descr_knl, KNIGHTS_LANDING),
+ PCI_ID_TABLE_ENTRY(pci_dev_descr_knl, ARRAY_SIZE(pci_dev_descr_knl), 1, KNIGHTS_LANDING),
{0,}
};
@@ -615,9 +627,9 @@ static const struct pci_id_table pci_dev_descr_knl_table[] = {
#define PCI_DEVICE_ID_INTEL_BROADWELL_IMC_HA0 0x6fa0
#define PCI_DEVICE_ID_INTEL_BROADWELL_IMC_HA1 0x6f60
#define PCI_DEVICE_ID_INTEL_BROADWELL_IMC_HA0_TA 0x6fa8
-#define PCI_DEVICE_ID_INTEL_BROADWELL_IMC_HA0_THERMAL 0x6f71
+#define PCI_DEVICE_ID_INTEL_BROADWELL_IMC_HA0_TM 0x6f71
#define PCI_DEVICE_ID_INTEL_BROADWELL_IMC_HA1_TA 0x6f68
-#define PCI_DEVICE_ID_INTEL_BROADWELL_IMC_HA1_THERMAL 0x6f79
+#define PCI_DEVICE_ID_INTEL_BROADWELL_IMC_HA1_TM 0x6f79
#define PCI_DEVICE_ID_INTEL_BROADWELL_IMC_CBO_SAD0 0x6ffc
#define PCI_DEVICE_ID_INTEL_BROADWELL_IMC_CBO_SAD1 0x6ffd
#define PCI_DEVICE_ID_INTEL_BROADWELL_IMC_HA0_TAD0 0x6faa
@@ -632,32 +644,30 @@ static const struct pci_id_table pci_dev_descr_knl_table[] = {
static const struct pci_id_descr pci_dev_descr_broadwell[] = {
/* first item must be the HA */
- { PCI_DESCR(PCI_DEVICE_ID_INTEL_BROADWELL_IMC_HA0, 0) },
-
- { PCI_DESCR(PCI_DEVICE_ID_INTEL_BROADWELL_IMC_CBO_SAD0, 0) },
- { PCI_DESCR(PCI_DEVICE_ID_INTEL_BROADWELL_IMC_CBO_SAD1, 0) },
-
- { PCI_DESCR(PCI_DEVICE_ID_INTEL_BROADWELL_IMC_HA1, 1) },
-
- { PCI_DESCR(PCI_DEVICE_ID_INTEL_BROADWELL_IMC_HA0_TA, 0) },
- { PCI_DESCR(PCI_DEVICE_ID_INTEL_BROADWELL_IMC_HA0_THERMAL, 0) },
- { PCI_DESCR(PCI_DEVICE_ID_INTEL_BROADWELL_IMC_HA0_TAD0, 0) },
- { PCI_DESCR(PCI_DEVICE_ID_INTEL_BROADWELL_IMC_HA0_TAD1, 0) },
- { PCI_DESCR(PCI_DEVICE_ID_INTEL_BROADWELL_IMC_HA0_TAD2, 1) },
- { PCI_DESCR(PCI_DEVICE_ID_INTEL_BROADWELL_IMC_HA0_TAD3, 1) },
-
- { PCI_DESCR(PCI_DEVICE_ID_INTEL_BROADWELL_IMC_DDRIO0, 1) },
-
- { PCI_DESCR(PCI_DEVICE_ID_INTEL_BROADWELL_IMC_HA1_TA, 1) },
- { PCI_DESCR(PCI_DEVICE_ID_INTEL_BROADWELL_IMC_HA1_THERMAL, 1) },
- { PCI_DESCR(PCI_DEVICE_ID_INTEL_BROADWELL_IMC_HA1_TAD0, 1) },
- { PCI_DESCR(PCI_DEVICE_ID_INTEL_BROADWELL_IMC_HA1_TAD1, 1) },
- { PCI_DESCR(PCI_DEVICE_ID_INTEL_BROADWELL_IMC_HA1_TAD2, 1) },
- { PCI_DESCR(PCI_DEVICE_ID_INTEL_BROADWELL_IMC_HA1_TAD3, 1) },
+ { PCI_DESCR(PCI_DEVICE_ID_INTEL_BROADWELL_IMC_HA0, 0, IMC0) },
+ { PCI_DESCR(PCI_DEVICE_ID_INTEL_BROADWELL_IMC_HA1, 1, IMC1) },
+
+ { PCI_DESCR(PCI_DEVICE_ID_INTEL_BROADWELL_IMC_HA0_TA, 0, IMC0) },
+ { PCI_DESCR(PCI_DEVICE_ID_INTEL_BROADWELL_IMC_HA0_TM, 0, IMC0) },
+ { PCI_DESCR(PCI_DEVICE_ID_INTEL_BROADWELL_IMC_HA0_TAD0, 0, IMC0) },
+ { PCI_DESCR(PCI_DEVICE_ID_INTEL_BROADWELL_IMC_HA0_TAD1, 0, IMC0) },
+ { PCI_DESCR(PCI_DEVICE_ID_INTEL_BROADWELL_IMC_HA0_TAD2, 1, IMC0) },
+ { PCI_DESCR(PCI_DEVICE_ID_INTEL_BROADWELL_IMC_HA0_TAD3, 1, IMC0) },
+
+ { PCI_DESCR(PCI_DEVICE_ID_INTEL_BROADWELL_IMC_HA1_TA, 1, IMC1) },
+ { PCI_DESCR(PCI_DEVICE_ID_INTEL_BROADWELL_IMC_HA1_TM, 1, IMC1) },
+ { PCI_DESCR(PCI_DEVICE_ID_INTEL_BROADWELL_IMC_HA1_TAD0, 1, IMC1) },
+ { PCI_DESCR(PCI_DEVICE_ID_INTEL_BROADWELL_IMC_HA1_TAD1, 1, IMC1) },
+ { PCI_DESCR(PCI_DEVICE_ID_INTEL_BROADWELL_IMC_HA1_TAD2, 1, IMC1) },
+ { PCI_DESCR(PCI_DEVICE_ID_INTEL_BROADWELL_IMC_HA1_TAD3, 1, IMC1) },
+
+ { PCI_DESCR(PCI_DEVICE_ID_INTEL_BROADWELL_IMC_CBO_SAD0, 0, SOCK) },
+ { PCI_DESCR(PCI_DEVICE_ID_INTEL_BROADWELL_IMC_CBO_SAD1, 0, SOCK) },
+ { PCI_DESCR(PCI_DEVICE_ID_INTEL_BROADWELL_IMC_DDRIO0, 1, SOCK) },
};
static const struct pci_id_table pci_dev_descr_broadwell_table[] = {
- PCI_ID_TABLE_ENTRY(pci_dev_descr_broadwell, BROADWELL),
+ PCI_ID_TABLE_ENTRY(pci_dev_descr_broadwell, 10, 2, BROADWELL),
{0,} /* 0 terminated list. */
};
@@ -709,7 +719,8 @@ static inline int numcol(u32 mtr)
return 1 << cols;
}
-static struct sbridge_dev *get_sbridge_dev(u8 bus, int multi_bus)
+static struct sbridge_dev *get_sbridge_dev(u8 bus, enum domain dom, int multi_bus,
+ struct sbridge_dev *prev)
{
struct sbridge_dev *sbridge_dev;
@@ -722,16 +733,19 @@ static struct sbridge_dev *get_sbridge_dev(u8 bus, int multi_bus)
struct sbridge_dev, list);
}
- list_for_each_entry(sbridge_dev, &sbridge_edac_list, list) {
- if (sbridge_dev->bus == bus)
+ sbridge_dev = list_entry(prev ? prev->list.next
+ : sbridge_edac_list.next, struct sbridge_dev, list);
+
+ list_for_each_entry_from(sbridge_dev, &sbridge_edac_list, list) {
+ if (sbridge_dev->bus == bus && (dom == SOCK || dom == sbridge_dev->dom))
return sbridge_dev;
}
return NULL;
}
-static struct sbridge_dev *alloc_sbridge_dev(u8 bus,
- const struct pci_id_table *table)
+static struct sbridge_dev *alloc_sbridge_dev(u8 bus, enum domain dom,
+ const struct pci_id_table *table)
{
struct sbridge_dev *sbridge_dev;
@@ -739,15 +753,17 @@ static struct sbridge_dev *alloc_sbridge_dev(u8 bus,
if (!sbridge_dev)
return NULL;
- sbridge_dev->pdev = kzalloc(sizeof(*sbridge_dev->pdev) * table->n_devs,
- GFP_KERNEL);
+ sbridge_dev->pdev = kcalloc(table->n_devs_per_imc,
+ sizeof(*sbridge_dev->pdev),
+ GFP_KERNEL);
if (!sbridge_dev->pdev) {
kfree(sbridge_dev);
return NULL;
}
sbridge_dev->bus = bus;
- sbridge_dev->n_devs = table->n_devs;
+ sbridge_dev->dom = dom;
+ sbridge_dev->n_devs = table->n_devs_per_imc;
list_add_tail(&sbridge_dev->list, &sbridge_edac_list);
return sbridge_dev;
@@ -1044,79 +1060,6 @@ static int haswell_chan_hash(int idx, u64 addr)
return idx;
}
-/****************************************************************************
- Memory check routines
- ****************************************************************************/
-static struct pci_dev *get_pdev_same_bus(u8 bus, u32 id)
-{
- struct pci_dev *pdev = NULL;
-
- do {
- pdev = pci_get_device(PCI_VENDOR_ID_INTEL, id, pdev);
- if (pdev && pdev->bus->number == bus)
- break;
- } while (pdev);
-
- return pdev;
-}
-
-/**
- * check_if_ecc_is_active() - Checks if ECC is active
- * @bus: Device bus
- * @type: Memory controller type
- * returns: 0 in case ECC is active, -ENODEV if it can't be determined or
- * disabled
- */
-static int check_if_ecc_is_active(const u8 bus, enum type type)
-{
- struct pci_dev *pdev = NULL;
- u32 mcmtr, id;
-
- switch (type) {
- case IVY_BRIDGE:
- id = PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA0_TA;
- break;
- case HASWELL:
- id = PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA0_TA;
- break;
- case SANDY_BRIDGE:
- id = PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_TA;
- break;
- case BROADWELL:
- id = PCI_DEVICE_ID_INTEL_BROADWELL_IMC_HA0_TA;
- break;
- case KNIGHTS_LANDING:
- /*
- * KNL doesn't group things by bus the same way
- * SB/IB/Haswell does.
- */
- id = PCI_DEVICE_ID_INTEL_KNL_IMC_TA;
- break;
- default:
- return -ENODEV;
- }
-
- if (type != KNIGHTS_LANDING)
- pdev = get_pdev_same_bus(bus, id);
- else
- pdev = pci_get_device(PCI_VENDOR_ID_INTEL, id, 0);
-
- if (!pdev) {
- sbridge_printk(KERN_ERR, "Couldn't find PCI device "
- "%04x:%04x! on bus %02d\n",
- PCI_VENDOR_ID_INTEL, id, bus);
- return -ENODEV;
- }
-
- pci_read_config_dword(pdev,
- type == KNIGHTS_LANDING ? KNL_MCMTR : MCMTR, &mcmtr);
- if (!IS_ECC_ENABLED(mcmtr)) {
- sbridge_printk(KERN_ERR, "ECC is disabled. Aborting\n");
- return -ENODEV;
- }
- return 0;
-}
-
/* Low bits of TAD limit, and some metadata. */
static const u32 knl_tad_dram_limit_lo[] = {
0x400, 0x500, 0x600, 0x700,
@@ -1587,25 +1530,13 @@ static int knl_get_dimm_capacity(struct sbridge_pvt *pvt, u64 *mc_sizes)
return 0;
}
-static int get_dimm_config(struct mem_ctl_info *mci)
+static void get_source_id(struct mem_ctl_info *mci)
{
struct sbridge_pvt *pvt = mci->pvt_info;
- struct dimm_info *dimm;
- unsigned i, j, banks, ranks, rows, cols, npages;
- u64 size;
u32 reg;
- enum edac_type mode;
- enum mem_type mtype;
- int channels = pvt->info.type == KNIGHTS_LANDING ?
- KNL_MAX_CHANNELS : NUM_CHANNELS;
- u64 knl_mc_sizes[KNL_MAX_CHANNELS];
- if (pvt->info.type == HASWELL || pvt->info.type == BROADWELL) {
- pci_read_config_dword(pvt->pci_ha0, HASWELL_HASYSDEFEATURE2, &reg);
- pvt->is_chan_hash = GET_BITFIELD(reg, 21, 21);
- }
if (pvt->info.type == HASWELL || pvt->info.type == BROADWELL ||
- pvt->info.type == KNIGHTS_LANDING)
+ pvt->info.type == KNIGHTS_LANDING)
pci_read_config_dword(pvt->pci_sad1, SAD_TARGET, &reg);
else
pci_read_config_dword(pvt->pci_br0, SAD_TARGET, &reg);
@@ -1614,50 +1545,19 @@ static int get_dimm_config(struct mem_ctl_info *mci)
pvt->sbridge_dev->source_id = SOURCE_ID_KNL(reg);
else
pvt->sbridge_dev->source_id = SOURCE_ID(reg);
+}
- pvt->sbridge_dev->node_id = pvt->info.get_node_id(pvt);
- edac_dbg(0, "mc#%d: Node ID: %d, source ID: %d\n",
- pvt->sbridge_dev->mc,
- pvt->sbridge_dev->node_id,
- pvt->sbridge_dev->source_id);
-
- /* KNL doesn't support mirroring or lockstep,
- * and is always closed page
- */
- if (pvt->info.type == KNIGHTS_LANDING) {
- mode = EDAC_S4ECD4ED;
- pvt->is_mirrored = false;
-
- if (knl_get_dimm_capacity(pvt, knl_mc_sizes) != 0)
- return -1;
- } else {
- pci_read_config_dword(pvt->pci_ras, RASENABLES, &reg);
- if (IS_MIRROR_ENABLED(reg)) {
- edac_dbg(0, "Memory mirror is enabled\n");
- pvt->is_mirrored = true;
- } else {
- edac_dbg(0, "Memory mirror is disabled\n");
- pvt->is_mirrored = false;
- }
-
- pci_read_config_dword(pvt->pci_ta, MCMTR, &pvt->info.mcmtr);
- if (IS_LOCKSTEP_ENABLED(pvt->info.mcmtr)) {
- edac_dbg(0, "Lockstep is enabled\n");
- mode = EDAC_S8ECD8ED;
- pvt->is_lockstep = true;
- } else {
- edac_dbg(0, "Lockstep is disabled\n");
- mode = EDAC_S4ECD4ED;
- pvt->is_lockstep = false;
- }
- if (IS_CLOSE_PG(pvt->info.mcmtr)) {
- edac_dbg(0, "address map is on closed page mode\n");
- pvt->is_close_pg = true;
- } else {
- edac_dbg(0, "address map is on open page mode\n");
- pvt->is_close_pg = false;
- }
- }
+static int __populate_dimms(struct mem_ctl_info *mci,
+ u64 knl_mc_sizes[KNL_MAX_CHANNELS],
+ enum edac_type mode)
+{
+ struct sbridge_pvt *pvt = mci->pvt_info;
+ int channels = pvt->info.type == KNIGHTS_LANDING ? KNL_MAX_CHANNELS
+ : NUM_CHANNELS;
+ unsigned int i, j, banks, ranks, rows, cols, npages;
+ struct dimm_info *dimm;
+ enum mem_type mtype;
+ u64 size;
mtype = pvt->info.get_memory_type(pvt);
if (mtype == MEM_RDDR3 || mtype == MEM_RDDR4)
@@ -1688,8 +1588,7 @@ static int get_dimm_config(struct mem_ctl_info *mci)
}
for (j = 0; j < max_dimms_per_channel; j++) {
- dimm = EDAC_DIMM_PTR(mci->layers, mci->dimms, mci->n_layers,
- i, j, 0);
+ dimm = EDAC_DIMM_PTR(mci->layers, mci->dimms, mci->n_layers, i, j, 0);
if (pvt->info.type == KNIGHTS_LANDING) {
pci_read_config_dword(pvt->knl.pci_channel[i],
knl_mtr_reg, &mtr);
@@ -1699,6 +1598,12 @@ static int get_dimm_config(struct mem_ctl_info *mci)
}
edac_dbg(4, "Channel #%d MTR%d = %x\n", i, j, mtr);
if (IS_DIMM_PRESENT(mtr)) {
+ if (!IS_ECC_ENABLED(pvt->info.mcmtr)) {
+ sbridge_printk(KERN_ERR, "CPU SrcID #%d, Ha #%d, Channel #%d has DIMMs, but ECC is disabled\n",
+ pvt->sbridge_dev->source_id,
+ pvt->sbridge_dev->dom, i);
+ return -ENODEV;
+ }
pvt->channel[i].dimms++;
ranks = numrank(pvt->info.type, mtr);
@@ -1717,7 +1622,7 @@ static int get_dimm_config(struct mem_ctl_info *mci)
npages = MiB_TO_PAGES(size);
edac_dbg(0, "mc#%d: ha %d channel %d, dimm %d, %lld Mb (%d pages) bank: %d, rank: %d, row: %#x, col: %#x\n",
- pvt->sbridge_dev->mc, i/4, i%4, j,
+ pvt->sbridge_dev->mc, pvt->sbridge_dev->dom, i, j,
size, npages,
banks, ranks, rows, cols);
@@ -1727,8 +1632,8 @@ static int get_dimm_config(struct mem_ctl_info *mci)
dimm->mtype = mtype;
dimm->edac_mode = mode;
snprintf(dimm->label, sizeof(dimm->label),
- "CPU_SrcID#%u_Ha#%u_Chan#%u_DIMM#%u",
- pvt->sbridge_dev->source_id, i/4, i%4, j);
+ "CPU_SrcID#%u_Ha#%u_Chan#%u_DIMM#%u",
+ pvt->sbridge_dev->source_id, pvt->sbridge_dev->dom, i, j);
}
}
}
@@ -1736,6 +1641,65 @@ static int get_dimm_config(struct mem_ctl_info *mci)
return 0;
}
+static int get_dimm_config(struct mem_ctl_info *mci)
+{
+ struct sbridge_pvt *pvt = mci->pvt_info;
+ u64 knl_mc_sizes[KNL_MAX_CHANNELS];
+ enum edac_type mode;
+ u32 reg;
+
+ if (pvt->info.type == HASWELL || pvt->info.type == BROADWELL) {
+ pci_read_config_dword(pvt->pci_ha, HASWELL_HASYSDEFEATURE2, &reg);
+ pvt->is_chan_hash = GET_BITFIELD(reg, 21, 21);
+ }
+ pvt->sbridge_dev->node_id = pvt->info.get_node_id(pvt);
+ edac_dbg(0, "mc#%d: Node ID: %d, source ID: %d\n",
+ pvt->sbridge_dev->mc,
+ pvt->sbridge_dev->node_id,
+ pvt->sbridge_dev->source_id);
+
+ /* KNL doesn't support mirroring or lockstep,
+ * and is always closed page
+ */
+ if (pvt->info.type == KNIGHTS_LANDING) {
+ mode = EDAC_S4ECD4ED;
+ pvt->is_mirrored = false;
+
+ if (knl_get_dimm_capacity(pvt, knl_mc_sizes) != 0)
+ return -1;
+ pci_read_config_dword(pvt->pci_ta, KNL_MCMTR, &pvt->info.mcmtr);
+ } else {
+ pci_read_config_dword(pvt->pci_ras, RASENABLES, &reg);
+ if (IS_MIRROR_ENABLED(reg)) {
+ edac_dbg(0, "Memory mirror is enabled\n");
+ pvt->is_mirrored = true;
+ } else {
+ edac_dbg(0, "Memory mirror is disabled\n");
+ pvt->is_mirrored = false;
+ }
+
+ pci_read_config_dword(pvt->pci_ta, MCMTR, &pvt->info.mcmtr);
+ if (IS_LOCKSTEP_ENABLED(pvt->info.mcmtr)) {
+ edac_dbg(0, "Lockstep is enabled\n");
+ mode = EDAC_S8ECD8ED;
+ pvt->is_lockstep = true;
+ } else {
+ edac_dbg(0, "Lockstep is disabled\n");
+ mode = EDAC_S4ECD4ED;
+ pvt->is_lockstep = false;
+ }
+ if (IS_CLOSE_PG(pvt->info.mcmtr)) {
+ edac_dbg(0, "address map is on closed page mode\n");
+ pvt->is_close_pg = true;
+ } else {
+ edac_dbg(0, "address map is on open page mode\n");
+ pvt->is_close_pg = false;
+ }
+ }
+
+ return __populate_dimms(mci, knl_mc_sizes, mode);
+}
+
static void get_memory_layout(const struct mem_ctl_info *mci)
{
struct sbridge_pvt *pvt = mci->pvt_info;
@@ -1816,8 +1780,7 @@ static void get_memory_layout(const struct mem_ctl_info *mci)
*/
prv = 0;
for (n_tads = 0; n_tads < MAX_TAD; n_tads++) {
- pci_read_config_dword(pvt->pci_ha0, tad_dram_rule[n_tads],
- &reg);
+ pci_read_config_dword(pvt->pci_ha, tad_dram_rule[n_tads], &reg);
limit = TAD_LIMIT(reg);
if (limit <= prv)
break;
@@ -1899,12 +1862,12 @@ static void get_memory_layout(const struct mem_ctl_info *mci)
}
}
-static struct mem_ctl_info *get_mci_for_node_id(u8 node_id)
+static struct mem_ctl_info *get_mci_for_node_id(u8 node_id, u8 ha)
{
struct sbridge_dev *sbridge_dev;
list_for_each_entry(sbridge_dev, &sbridge_edac_list, list) {
- if (sbridge_dev->node_id == node_id)
+ if (sbridge_dev->node_id == node_id && sbridge_dev->dom == ha)
return sbridge_dev->mci;
}
return NULL;
@@ -1925,7 +1888,7 @@ static int get_memory_error_data(struct mem_ctl_info *mci,
int interleave_mode, shiftup = 0;
unsigned sad_interleave[pvt->info.max_interleave];
u32 reg, dram_rule;
- u8 ch_way, sck_way, pkg, sad_ha = 0, ch_add = 0;
+ u8 ch_way, sck_way, pkg, sad_ha = 0;
u32 tad_offset;
u32 rir_way;
u32 mb, gb;
@@ -2038,13 +2001,10 @@ static int get_memory_error_data(struct mem_ctl_info *mci,
pkg = sad_pkg(pvt->info.interleave_pkg, reg, idx);
*socket = sad_pkg_socket(pkg);
sad_ha = sad_pkg_ha(pkg);
- if (sad_ha)
- ch_add = 4;
if (a7mode) {
/* MCChanShiftUpEnable */
- pci_read_config_dword(pvt->pci_ha0,
- HASWELL_HASYSDEFEATURE2, &reg);
+ pci_read_config_dword(pvt->pci_ha, HASWELL_HASYSDEFEATURE2, &reg);
shiftup = GET_BITFIELD(reg, 22, 22);
}
@@ -2056,8 +2016,6 @@ static int get_memory_error_data(struct mem_ctl_info *mci,
pkg = sad_pkg(pvt->info.interleave_pkg, reg, idx);
*socket = sad_pkg_socket(pkg);
sad_ha = sad_pkg_ha(pkg);
- if (sad_ha)
- ch_add = 4;
edac_dbg(0, "SAD interleave package: %d = CPU socket %d, HA %d\n",
idx, *socket, sad_ha);
}
@@ -2068,7 +2026,7 @@ static int get_memory_error_data(struct mem_ctl_info *mci,
* Move to the proper node structure, in order to access the
* right PCI registers
*/
- new_mci = get_mci_for_node_id(*socket);
+ new_mci = get_mci_for_node_id(*socket, sad_ha);
if (!new_mci) {
sprintf(msg, "Struct for socket #%u wasn't initialized",
*socket);
@@ -2081,14 +2039,7 @@ static int get_memory_error_data(struct mem_ctl_info *mci,
* Step 2) Get memory channel
*/
prv = 0;
- if (pvt->info.type == SANDY_BRIDGE)
- pci_ha = pvt->pci_ha0;
- else {
- if (sad_ha)
- pci_ha = pvt->pci_ha1;
- else
- pci_ha = pvt->pci_ha0;
- }
+ pci_ha = pvt->pci_ha;
for (n_tads = 0; n_tads < MAX_TAD; n_tads++) {
pci_read_config_dword(pci_ha, tad_dram_rule[n_tads], &reg);
limit = TAD_LIMIT(reg);
@@ -2139,9 +2090,7 @@ static int get_memory_error_data(struct mem_ctl_info *mci,
}
*channel_mask = 1 << base_ch;
- pci_read_config_dword(pvt->pci_tad[ch_add + base_ch],
- tad_ch_nilv_offset[n_tads],
- &tad_offset);
+ pci_read_config_dword(pvt->pci_tad[base_ch], tad_ch_nilv_offset[n_tads], &tad_offset);
if (pvt->is_mirrored) {
*channel_mask |= 1 << ((base_ch + 2) % 4);
@@ -2192,9 +2141,7 @@ static int get_memory_error_data(struct mem_ctl_info *mci,
* Step 3) Decode rank
*/
for (n_rir = 0; n_rir < MAX_RIR_RANGES; n_rir++) {
- pci_read_config_dword(pvt->pci_tad[ch_add + base_ch],
- rir_way_limit[n_rir],
- &reg);
+ pci_read_config_dword(pvt->pci_tad[base_ch], rir_way_limit[n_rir], &reg);
if (!IS_RIR_VALID(reg))
continue;
@@ -2222,9 +2169,7 @@ static int get_memory_error_data(struct mem_ctl_info *mci,
idx = (ch_addr >> 13); /* FIXME: Datasheet says to shift by 15 */
idx %= 1 << rir_way;
- pci_read_config_dword(pvt->pci_tad[ch_add + base_ch],
- rir_offset[n_rir][idx],
- &reg);
+ pci_read_config_dword(pvt->pci_tad[base_ch], rir_offset[n_rir][idx], &reg);
*rank = RIR_RNK_TGT(pvt->info.type, reg);
edac_dbg(0, "RIR#%d: channel address 0x%08Lx < 0x%08Lx, RIR interleave %d, index %d\n",
@@ -2277,10 +2222,11 @@ static int sbridge_get_onedevice(struct pci_dev **prev,
const unsigned devno,
const int multi_bus)
{
- struct sbridge_dev *sbridge_dev;
+ struct sbridge_dev *sbridge_dev = NULL;
const struct pci_id_descr *dev_descr = &table->descr[devno];
struct pci_dev *pdev = NULL;
u8 bus = 0;
+ int i = 0;
sbridge_printk(KERN_DEBUG,
"Seeking for: PCI ID %04x:%04x\n",
@@ -2311,9 +2257,14 @@ static int sbridge_get_onedevice(struct pci_dev **prev,
}
bus = pdev->bus->number;
- sbridge_dev = get_sbridge_dev(bus, multi_bus);
+next_imc:
+ sbridge_dev = get_sbridge_dev(bus, dev_descr->dom, multi_bus, sbridge_dev);
if (!sbridge_dev) {
- sbridge_dev = alloc_sbridge_dev(bus, table);
+
+ if (dev_descr->dom == SOCK)
+ goto out_imc;
+
+ sbridge_dev = alloc_sbridge_dev(bus, dev_descr->dom, table);
if (!sbridge_dev) {
pci_dev_put(pdev);
return -ENOMEM;
@@ -2321,7 +2272,7 @@ static int sbridge_get_onedevice(struct pci_dev **prev,
(*num_mc)++;
}
- if (sbridge_dev->pdev[devno]) {
+ if (sbridge_dev->pdev[sbridge_dev->i_devs]) {
sbridge_printk(KERN_ERR,
"Duplicated device for %04x:%04x\n",
PCI_VENDOR_ID_INTEL, dev_descr->dev_id);
@@ -2329,8 +2280,16 @@ static int sbridge_get_onedevice(struct pci_dev **prev,
return -ENODEV;
}
- sbridge_dev->pdev[devno] = pdev;
+ sbridge_dev->pdev[sbridge_dev->i_devs++] = pdev;
+
+ /* pdev belongs to more than one IMC, do extra gets */
+ if (++i > 1)
+ pci_dev_get(pdev);
+ if (dev_descr->dom == SOCK && i < table->n_imcs_per_sock)
+ goto next_imc;
+
+out_imc:
/* Be sure that the device is enabled */
if (unlikely(pci_enable_device(pdev) < 0)) {
sbridge_printk(KERN_ERR,
@@ -2374,7 +2333,7 @@ static int sbridge_get_all_devices(u8 *num_mc,
if (table->type == KNIGHTS_LANDING)
allow_dups = multi_bus = 1;
while (table && table->descr) {
- for (i = 0; i < table->n_devs; i++) {
+ for (i = 0; i < table->n_devs_per_sock; i++) {
if (!allow_dups || i == 0 ||
table->descr[i].dev_id !=
table->descr[i-1].dev_id) {
@@ -2385,7 +2344,7 @@ static int sbridge_get_all_devices(u8 *num_mc,
table, i, multi_bus);
if (rc < 0) {
if (i == 0) {
- i = table->n_devs;
+ i = table->n_devs_per_sock;
break;
}
sbridge_put_all_devices();
@@ -2399,6 +2358,13 @@ static int sbridge_get_all_devices(u8 *num_mc,
return 0;
}
+/*
+ * Device IDs for {SBRIDGE,IBRIDGE,HASWELL,BROADWELL}_IMC_HA0_TAD0 are in
+ * the format: XXXa. So we can convert from a device to the corresponding
+ * channel like this
+ */
+#define TAD_DEV_TO_CHAN(dev) (((dev) & 0xf) - 0xa)
+
static int sbridge_mci_bind_devs(struct mem_ctl_info *mci,
struct sbridge_dev *sbridge_dev)
{
@@ -2423,7 +2389,7 @@ static int sbridge_mci_bind_devs(struct mem_ctl_info *mci,
pvt->pci_br0 = pdev;
break;
case PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_HA0:
- pvt->pci_ha0 = pdev;
+ pvt->pci_ha = pdev;
break;
case PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_TA:
pvt->pci_ta = pdev;
@@ -2436,7 +2402,7 @@ static int sbridge_mci_bind_devs(struct mem_ctl_info *mci,
case PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_TAD2:
case PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_TAD3:
{
- int id = pdev->device - PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_TAD0;
+ int id = TAD_DEV_TO_CHAN(pdev->device);
pvt->pci_tad[id] = pdev;
saw_chan_mask |= 1 << id;
}
@@ -2455,7 +2421,7 @@ static int sbridge_mci_bind_devs(struct mem_ctl_info *mci,
}
/* Check if everything were registered */
- if (!pvt->pci_sad0 || !pvt->pci_sad1 || !pvt->pci_ha0 ||
+ if (!pvt->pci_sad0 || !pvt->pci_sad1 || !pvt->pci_ha ||
!pvt->pci_ras || !pvt->pci_ta)
goto enodev;
@@ -2488,19 +2454,26 @@ static int ibridge_mci_bind_devs(struct mem_ctl_info *mci,
switch (pdev->device) {
case PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA0:
- pvt->pci_ha0 = pdev;
+ case PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA1:
+ pvt->pci_ha = pdev;
break;
case PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA0_TA:
+ case PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA1_TA:
pvt->pci_ta = pdev;
case PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA0_RAS:
+ case PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA1_RAS:
pvt->pci_ras = pdev;
break;
case PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA0_TAD0:
case PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA0_TAD1:
case PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA0_TAD2:
case PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA0_TAD3:
+ case PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA1_TAD0:
+ case PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA1_TAD1:
+ case PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA1_TAD2:
+ case PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA1_TAD3:
{
- int id = pdev->device - PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA0_TAD0;
+ int id = TAD_DEV_TO_CHAN(pdev->device);
pvt->pci_tad[id] = pdev;
saw_chan_mask |= 1 << id;
}
@@ -2520,19 +2493,6 @@ static int ibridge_mci_bind_devs(struct mem_ctl_info *mci,
case PCI_DEVICE_ID_INTEL_IBRIDGE_BR1:
pvt->pci_br1 = pdev;
break;
- case PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA1:
- pvt->pci_ha1 = pdev;
- break;
- case PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA1_TAD0:
- case PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA1_TAD1:
- case PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA1_TAD2:
- case PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA1_TAD3:
- {
- int id = pdev->device - PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA1_TAD0 + 4;
- pvt->pci_tad[id] = pdev;
- saw_chan_mask |= 1 << id;
- }
- break;
default:
goto error;
}
@@ -2544,13 +2504,12 @@ static int ibridge_mci_bind_devs(struct mem_ctl_info *mci,
}
/* Check if everything were registered */
- if (!pvt->pci_sad0 || !pvt->pci_ha0 || !pvt->pci_br0 ||
+ if (!pvt->pci_sad0 || !pvt->pci_ha || !pvt->pci_br0 ||
!pvt->pci_br1 || !pvt->pci_ras || !pvt->pci_ta)
goto enodev;
- if (saw_chan_mask != 0x0f && /* -EN */
- saw_chan_mask != 0x33 && /* -EP */
- saw_chan_mask != 0xff) /* -EX */
+ if (saw_chan_mask != 0x0f && /* -EN/-EX */
+ saw_chan_mask != 0x03) /* -EP */
goto enodev;
return 0;
@@ -2593,32 +2552,27 @@ static int haswell_mci_bind_devs(struct mem_ctl_info *mci,
pvt->pci_sad1 = pdev;
break;
case PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA0:
- pvt->pci_ha0 = pdev;
+ case PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA1:
+ pvt->pci_ha = pdev;
break;
case PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA0_TA:
+ case PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA1_TA:
pvt->pci_ta = pdev;
break;
- case PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA0_THERMAL:
+ case PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA0_TM:
+ case PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA1_TM:
pvt->pci_ras = pdev;
break;
case PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA0_TAD0:
case PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA0_TAD1:
case PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA0_TAD2:
case PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA0_TAD3:
- {
- int id = pdev->device - PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA0_TAD0;
-
- pvt->pci_tad[id] = pdev;
- saw_chan_mask |= 1 << id;
- }
- break;
case PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA1_TAD0:
case PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA1_TAD1:
case PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA1_TAD2:
case PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA1_TAD3:
{
- int id = pdev->device - PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA1_TAD0 + 4;
-
+ int id = TAD_DEV_TO_CHAN(pdev->device);
pvt->pci_tad[id] = pdev;
saw_chan_mask |= 1 << id;
}
@@ -2630,12 +2584,6 @@ static int haswell_mci_bind_devs(struct mem_ctl_info *mci,
if (!pvt->pci_ddrio)
pvt->pci_ddrio = pdev;
break;
- case PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA1:
- pvt->pci_ha1 = pdev;
- break;
- case PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA1_TA:
- pvt->pci_ha1_ta = pdev;
- break;
default:
break;
}
@@ -2647,13 +2595,12 @@ static int haswell_mci_bind_devs(struct mem_ctl_info *mci,
}
/* Check if everything were registered */
- if (!pvt->pci_sad0 || !pvt->pci_ha0 || !pvt->pci_sad1 ||
+ if (!pvt->pci_sad0 || !pvt->pci_ha || !pvt->pci_sad1 ||
!pvt->pci_ras || !pvt->pci_ta || !pvt->info.pci_vtd)
goto enodev;
- if (saw_chan_mask != 0x0f && /* -EN */
- saw_chan_mask != 0x33 && /* -EP */
- saw_chan_mask != 0xff) /* -EX */
+ if (saw_chan_mask != 0x0f && /* -EN/-EX */
+ saw_chan_mask != 0x03) /* -EP */
goto enodev;
return 0;
@@ -2690,30 +2637,27 @@ static int broadwell_mci_bind_devs(struct mem_ctl_info *mci,
pvt->pci_sad1 = pdev;
break;
case PCI_DEVICE_ID_INTEL_BROADWELL_IMC_HA0:
- pvt->pci_ha0 = pdev;
+ case PCI_DEVICE_ID_INTEL_BROADWELL_IMC_HA1:
+ pvt->pci_ha = pdev;
break;
case PCI_DEVICE_ID_INTEL_BROADWELL_IMC_HA0_TA:
+ case PCI_DEVICE_ID_INTEL_BROADWELL_IMC_HA1_TA:
pvt->pci_ta = pdev;
break;
- case PCI_DEVICE_ID_INTEL_BROADWELL_IMC_HA0_THERMAL:
+ case PCI_DEVICE_ID_INTEL_BROADWELL_IMC_HA0_TM:
+ case PCI_DEVICE_ID_INTEL_BROADWELL_IMC_HA1_TM:
pvt->pci_ras = pdev;
break;
case PCI_DEVICE_ID_INTEL_BROADWELL_IMC_HA0_TAD0:
case PCI_DEVICE_ID_INTEL_BROADWELL_IMC_HA0_TAD1:
case PCI_DEVICE_ID_INTEL_BROADWELL_IMC_HA0_TAD2:
case PCI_DEVICE_ID_INTEL_BROADWELL_IMC_HA0_TAD3:
- {
- int id = pdev->device - PCI_DEVICE_ID_INTEL_BROADWELL_IMC_HA0_TAD0;
- pvt->pci_tad[id] = pdev;
- saw_chan_mask |= 1 << id;
- }
- break;
case PCI_DEVICE_ID_INTEL_BROADWELL_IMC_HA1_TAD0:
case PCI_DEVICE_ID_INTEL_BROADWELL_IMC_HA1_TAD1:
case PCI_DEVICE_ID_INTEL_BROADWELL_IMC_HA1_TAD2:
case PCI_DEVICE_ID_INTEL_BROADWELL_IMC_HA1_TAD3:
{
- int id = pdev->device - PCI_DEVICE_ID_INTEL_BROADWELL_IMC_HA1_TAD0 + 4;
+ int id = TAD_DEV_TO_CHAN(pdev->device);
pvt->pci_tad[id] = pdev;
saw_chan_mask |= 1 << id;
}
@@ -2721,12 +2665,6 @@ static int broadwell_mci_bind_devs(struct mem_ctl_info *mci,
case PCI_DEVICE_ID_INTEL_BROADWELL_IMC_DDRIO0:
pvt->pci_ddrio = pdev;
break;
- case PCI_DEVICE_ID_INTEL_BROADWELL_IMC_HA1:
- pvt->pci_ha1 = pdev;
- break;
- case PCI_DEVICE_ID_INTEL_BROADWELL_IMC_HA1_TA:
- pvt->pci_ha1_ta = pdev;
- break;
default:
break;
}
@@ -2738,13 +2676,12 @@ static int broadwell_mci_bind_devs(struct mem_ctl_info *mci,
}
/* Check if everything were registered */
- if (!pvt->pci_sad0 || !pvt->pci_ha0 || !pvt->pci_sad1 ||
+ if (!pvt->pci_sad0 || !pvt->pci_ha || !pvt->pci_sad1 ||
!pvt->pci_ras || !pvt->pci_ta || !pvt->info.pci_vtd)
goto enodev;
- if (saw_chan_mask != 0x0f && /* -EN */
- saw_chan_mask != 0x33 && /* -EP */
- saw_chan_mask != 0xff) /* -EX */
+ if (saw_chan_mask != 0x0f && /* -EN/-EX */
+ saw_chan_mask != 0x03) /* -EP */
goto enodev;
return 0;
@@ -2812,7 +2749,7 @@ static int knl_mci_bind_devs(struct mem_ctl_info *mci,
pvt->knl.pci_cha[devidx] = pdev;
break;
- case PCI_DEVICE_ID_INTEL_KNL_IMC_CHANNEL:
+ case PCI_DEVICE_ID_INTEL_KNL_IMC_CHAN:
devidx = -1;
/*
@@ -3006,7 +2943,7 @@ static void sbridge_mce_output_error(struct mem_ctl_info *mci,
if (rc < 0)
goto err_parsing;
- new_mci = get_mci_for_node_id(socket);
+ new_mci = get_mci_for_node_id(socket, ha);
if (!new_mci) {
strcpy(msg, "Error: socket got corrupted!");
goto err_parsing;
@@ -3053,7 +2990,7 @@ static void sbridge_mce_output_error(struct mem_ctl_info *mci,
/* Call the helper to output message */
edac_mc_handle_error(tp_event, mci, core_err_cnt,
m->addr >> PAGE_SHIFT, m->addr & ~PAGE_MASK, 0,
- 4*ha+channel, dimm, -1,
+ channel, dimm, -1,
optype, msg);
return;
err_parsing:
@@ -3078,7 +3015,7 @@ static int sbridge_mce_check_error(struct notifier_block *nb, unsigned long val,
if (edac_get_report_status() == EDAC_REPORTING_DISABLED)
return NOTIFY_DONE;
- mci = get_mci_for_node_id(mce->socketid);
+ mci = get_mci_for_node_id(mce->socketid, IMC0);
if (!mci)
return NOTIFY_DONE;
pvt = mci->pvt_info;
@@ -3159,11 +3096,6 @@ static int sbridge_register_mci(struct sbridge_dev *sbridge_dev, enum type type)
struct pci_dev *pdev = sbridge_dev->pdev[0];
int rc;
- /* Check the number of active and not disabled channels */
- rc = check_if_ecc_is_active(sbridge_dev->bus, type);
- if (unlikely(rc < 0))
- return rc;
-
/* allocate a new MC control structure */
layers[0].type = EDAC_MC_LAYER_CHANNEL;
layers[0].size = type == KNIGHTS_LANDING ?
@@ -3192,7 +3124,7 @@ static int sbridge_register_mci(struct sbridge_dev *sbridge_dev, enum type type)
MEM_FLAG_DDR4 : MEM_FLAG_DDR3;
mci->edac_ctl_cap = EDAC_FLAG_NONE;
mci->edac_cap = EDAC_FLAG_NONE;
- mci->mod_name = "sbridge_edac.c";
+ mci->mod_name = "sb_edac.c";
mci->mod_ver = SBRIDGE_REVISION;
mci->dev_name = pci_name(pdev);
mci->ctl_page_to_phys = NULL;
@@ -3215,12 +3147,14 @@ static int sbridge_register_mci(struct sbridge_dev *sbridge_dev, enum type type)
pvt->info.max_interleave = ARRAY_SIZE(ibridge_interleave_list);
pvt->info.interleave_pkg = ibridge_interleave_pkg;
pvt->info.get_width = ibridge_get_width;
- mci->ctl_name = kasprintf(GFP_KERNEL, "Ivy Bridge Socket#%d", mci->mc_idx);
/* Store pci devices at mci for faster access */
rc = ibridge_mci_bind_devs(mci, sbridge_dev);
if (unlikely(rc < 0))
goto fail0;
+ get_source_id(mci);
+ mci->ctl_name = kasprintf(GFP_KERNEL, "Ivy Bridge SrcID#%d_Ha#%d",
+ pvt->sbridge_dev->source_id, pvt->sbridge_dev->dom);
break;
case SANDY_BRIDGE:
pvt->info.rankcfgr = SB_RANK_CFG_A;
@@ -3238,12 +3172,14 @@ static int sbridge_register_mci(struct sbridge_dev *sbridge_dev, enum type type)
pvt->info.max_interleave = ARRAY_SIZE(sbridge_interleave_list);
pvt->info.interleave_pkg = sbridge_interleave_pkg;
pvt->info.get_width = sbridge_get_width;
- mci->ctl_name = kasprintf(GFP_KERNEL, "Sandy Bridge Socket#%d", mci->mc_idx);
/* Store pci devices at mci for faster access */
rc = sbridge_mci_bind_devs(mci, sbridge_dev);
if (unlikely(rc < 0))
goto fail0;
+ get_source_id(mci);
+ mci->ctl_name = kasprintf(GFP_KERNEL, "Sandy Bridge SrcID#%d_Ha#%d",
+ pvt->sbridge_dev->source_id, pvt->sbridge_dev->dom);
break;
case HASWELL:
/* rankcfgr isn't used */
@@ -3261,12 +3197,14 @@ static int sbridge_register_mci(struct sbridge_dev *sbridge_dev, enum type type)
pvt->info.max_interleave = ARRAY_SIZE(ibridge_interleave_list);
pvt->info.interleave_pkg = ibridge_interleave_pkg;
pvt->info.get_width = ibridge_get_width;
- mci->ctl_name = kasprintf(GFP_KERNEL, "Haswell Socket#%d", mci->mc_idx);
/* Store pci devices at mci for faster access */
rc = haswell_mci_bind_devs(mci, sbridge_dev);
if (unlikely(rc < 0))
goto fail0;
+ get_source_id(mci);
+ mci->ctl_name = kasprintf(GFP_KERNEL, "Haswell SrcID#%d_Ha#%d",
+ pvt->sbridge_dev->source_id, pvt->sbridge_dev->dom);
break;
case BROADWELL:
/* rankcfgr isn't used */
@@ -3284,12 +3222,14 @@ static int sbridge_register_mci(struct sbridge_dev *sbridge_dev, enum type type)
pvt->info.max_interleave = ARRAY_SIZE(ibridge_interleave_list);
pvt->info.interleave_pkg = ibridge_interleave_pkg;
pvt->info.get_width = broadwell_get_width;
- mci->ctl_name = kasprintf(GFP_KERNEL, "Broadwell Socket#%d", mci->mc_idx);
/* Store pci devices at mci for faster access */
rc = broadwell_mci_bind_devs(mci, sbridge_dev);
if (unlikely(rc < 0))
goto fail0;
+ get_source_id(mci);
+ mci->ctl_name = kasprintf(GFP_KERNEL, "Broadwell SrcID#%d_Ha#%d",
+ pvt->sbridge_dev->source_id, pvt->sbridge_dev->dom);
break;
case KNIGHTS_LANDING:
/* pvt->info.rankcfgr == ??? */
@@ -3307,17 +3247,22 @@ static int sbridge_register_mci(struct sbridge_dev *sbridge_dev, enum type type)
pvt->info.max_interleave = ARRAY_SIZE(knl_interleave_list);
pvt->info.interleave_pkg = ibridge_interleave_pkg;
pvt->info.get_width = knl_get_width;
- mci->ctl_name = kasprintf(GFP_KERNEL,
- "Knights Landing Socket#%d", mci->mc_idx);
rc = knl_mci_bind_devs(mci, sbridge_dev);
if (unlikely(rc < 0))
goto fail0;
+ get_source_id(mci);
+ mci->ctl_name = kasprintf(GFP_KERNEL, "Knights Landing SrcID#%d_Ha#%d",
+ pvt->sbridge_dev->source_id, pvt->sbridge_dev->dom);
break;
}
/* Get dimm basic config and the memory layout */
- get_dimm_config(mci);
+ rc = get_dimm_config(mci);
+ if (rc < 0) {
+ edac_dbg(0, "MC: failed to get_dimm_config()\n");
+ goto fail;
+ }
get_memory_layout(mci);
/* record ptr to the generic device */
@@ -3327,13 +3272,14 @@ static int sbridge_register_mci(struct sbridge_dev *sbridge_dev, enum type type)
if (unlikely(edac_mc_add_mc(mci))) {
edac_dbg(0, "MC: failed edac_mc_add_mc()\n");
rc = -EINVAL;
- goto fail0;
+ goto fail;
}
return 0;
-fail0:
+fail:
kfree(mci->ctl_name);
+fail0:
edac_mc_free(mci);
sbridge_dev->mci = NULL;
return rc;
diff --git a/drivers/edac/thunderx_edac.c b/drivers/edac/thunderx_edac.c
index 86d585cb6d32..2d352b40ae1c 100644
--- a/drivers/edac/thunderx_edac.c
+++ b/drivers/edac/thunderx_edac.c
@@ -2080,7 +2080,7 @@ static int thunderx_l2c_probe(struct pci_dev *pdev,
if (IS_ENABLED(CONFIG_EDAC_DEBUG)) {
l2c->debugfs = edac_debugfs_create_dir(pdev->dev.kobj.name);
- thunderx_create_debugfs_nodes(l2c->debugfs, l2c_devattr,
+ ret = thunderx_create_debugfs_nodes(l2c->debugfs, l2c_devattr,
l2c, dfs_entries);
if (ret != dfs_entries) {
diff --git a/drivers/extcon/Kconfig b/drivers/extcon/Kconfig
index 32f2dc8e4702..6d50071f07d5 100644
--- a/drivers/extcon/Kconfig
+++ b/drivers/extcon/Kconfig
@@ -115,6 +115,7 @@ config EXTCON_PALMAS
config EXTCON_QCOM_SPMI_MISC
tristate "Qualcomm USB extcon support"
+ depends on ARCH_QCOM || COMPILE_TEST
help
Say Y here to enable SPMI PMIC based USB cable detection
support on Qualcomm PMICs such as PM8941.
diff --git a/drivers/extcon/extcon-arizona.c b/drivers/extcon/extcon-arizona.c
index e2d78cd7030d..f84da4a17724 100644
--- a/drivers/extcon/extcon-arizona.c
+++ b/drivers/extcon/extcon-arizona.c
@@ -1271,9 +1271,7 @@ static int arizona_extcon_get_micd_configs(struct device *dev,
goto out;
nconfs /= entries_per_config;
-
- micd_configs = devm_kzalloc(dev,
- nconfs * sizeof(struct arizona_micd_range),
+ micd_configs = devm_kcalloc(dev, nconfs, sizeof(*micd_configs),
GFP_KERNEL);
if (!micd_configs) {
ret = -ENOMEM;
diff --git a/drivers/extcon/extcon-intel-int3496.c b/drivers/extcon/extcon-intel-int3496.c
index 9d17984bbbd4..d9f9afe45961 100644
--- a/drivers/extcon/extcon-intel-int3496.c
+++ b/drivers/extcon/extcon-intel-int3496.c
@@ -94,8 +94,7 @@ static int int3496_probe(struct platform_device *pdev)
struct int3496_data *data;
int ret;
- ret = acpi_dev_add_driver_gpios(ACPI_COMPANION(dev),
- acpi_int3496_default_gpios);
+ ret = devm_acpi_dev_add_driver_gpios(dev, acpi_int3496_default_gpios);
if (ret) {
dev_err(dev, "can't add GPIO ACPI mapping\n");
return ret;
@@ -169,8 +168,6 @@ static int int3496_remove(struct platform_device *pdev)
devm_free_irq(&pdev->dev, data->usb_id_irq, data);
cancel_delayed_work_sync(&data->work);
- acpi_dev_remove_driver_gpios(ACPI_COMPANION(&pdev->dev));
-
return 0;
}
diff --git a/drivers/extcon/extcon.c b/drivers/extcon/extcon.c
index f422a78ba342..8eccf7b14937 100644
--- a/drivers/extcon/extcon.c
+++ b/drivers/extcon/extcon.c
@@ -964,12 +964,12 @@ EXPORT_SYMBOL_GPL(extcon_unregister_notifier);
/**
* extcon_register_notifier_all() - Register a notifier block for all connectors
- * @edev: the extcon device that has the external connecotr.
+ * @edev: the extcon device that has the external connector.
* @nb: a notifier block to be registered.
*
- * This fucntion registers a notifier block in order to receive the state
+ * This function registers a notifier block in order to receive the state
* change of all supported external connectors from extcon device.
- * And The second parameter given to the callback of nb (val) is
+ * And the second parameter given to the callback of nb (val) is
* the current state and third parameter is the edev pointer.
*
* Returns 0 if success or error number if fail
@@ -1252,9 +1252,8 @@ int extcon_dev_register(struct extcon_dev *edev)
}
spin_lock_init(&edev->lock);
-
- edev->nh = devm_kzalloc(&edev->dev,
- sizeof(*edev->nh) * edev->max_supported, GFP_KERNEL);
+ edev->nh = devm_kcalloc(&edev->dev, edev->max_supported,
+ sizeof(*edev->nh), GFP_KERNEL);
if (!edev->nh) {
ret = -ENOMEM;
goto err_dev;
diff --git a/drivers/firmware/dmi-id.c b/drivers/firmware/dmi-id.c
index 44c01390d035..951b6c79f166 100644
--- a/drivers/firmware/dmi-id.c
+++ b/drivers/firmware/dmi-id.c
@@ -47,6 +47,7 @@ DEFINE_DMI_ATTR_WITH_SHOW(product_name, 0444, DMI_PRODUCT_NAME);
DEFINE_DMI_ATTR_WITH_SHOW(product_version, 0444, DMI_PRODUCT_VERSION);
DEFINE_DMI_ATTR_WITH_SHOW(product_serial, 0400, DMI_PRODUCT_SERIAL);
DEFINE_DMI_ATTR_WITH_SHOW(product_uuid, 0400, DMI_PRODUCT_UUID);
+DEFINE_DMI_ATTR_WITH_SHOW(product_family, 0444, DMI_PRODUCT_FAMILY);
DEFINE_DMI_ATTR_WITH_SHOW(board_vendor, 0444, DMI_BOARD_VENDOR);
DEFINE_DMI_ATTR_WITH_SHOW(board_name, 0444, DMI_BOARD_NAME);
DEFINE_DMI_ATTR_WITH_SHOW(board_version, 0444, DMI_BOARD_VERSION);
@@ -191,6 +192,7 @@ static void __init dmi_id_init_attr_table(void)
ADD_DMI_ATTR(product_version, DMI_PRODUCT_VERSION);
ADD_DMI_ATTR(product_serial, DMI_PRODUCT_SERIAL);
ADD_DMI_ATTR(product_uuid, DMI_PRODUCT_UUID);
+ ADD_DMI_ATTR(product_family, DMI_PRODUCT_FAMILY);
ADD_DMI_ATTR(board_vendor, DMI_BOARD_VENDOR);
ADD_DMI_ATTR(board_name, DMI_BOARD_NAME);
ADD_DMI_ATTR(board_version, DMI_BOARD_VERSION);
diff --git a/drivers/firmware/dmi_scan.c b/drivers/firmware/dmi_scan.c
index 54be60ead08f..783041964439 100644
--- a/drivers/firmware/dmi_scan.c
+++ b/drivers/firmware/dmi_scan.c
@@ -144,7 +144,7 @@ static int __init dmi_walk_early(void (*decode)(const struct dmi_header *,
buf = dmi_early_remap(dmi_base, orig_dmi_len);
if (buf == NULL)
- return -1;
+ return -ENOMEM;
dmi_decode_table(buf, decode, NULL);
@@ -178,7 +178,7 @@ static void __init dmi_save_ident(const struct dmi_header *dm, int slot,
const char *d = (const char *) dm;
const char *p;
- if (dmi_ident[slot])
+ if (dmi_ident[slot] || dm->length <= string)
return;
p = dmi_string(dm, d[string]);
@@ -191,13 +191,14 @@ static void __init dmi_save_ident(const struct dmi_header *dm, int slot,
static void __init dmi_save_uuid(const struct dmi_header *dm, int slot,
int index)
{
- const u8 *d = (u8 *) dm + index;
+ const u8 *d;
char *s;
int is_ff = 1, is_00 = 1, i;
- if (dmi_ident[slot])
+ if (dmi_ident[slot] || dm->length <= index + 16)
return;
+ d = (u8 *) dm + index;
for (i = 0; i < 16 && (is_ff || is_00); i++) {
if (d[i] != 0x00)
is_00 = 0;
@@ -228,16 +229,17 @@ static void __init dmi_save_uuid(const struct dmi_header *dm, int slot,
static void __init dmi_save_type(const struct dmi_header *dm, int slot,
int index)
{
- const u8 *d = (u8 *) dm + index;
+ const u8 *d;
char *s;
- if (dmi_ident[slot])
+ if (dmi_ident[slot] || dm->length <= index)
return;
s = dmi_alloc(4);
if (!s)
return;
+ d = (u8 *) dm + index;
sprintf(s, "%u", *d & 0x7F);
dmi_ident[slot] = s;
}
@@ -278,9 +280,13 @@ static void __init dmi_save_devices(const struct dmi_header *dm)
static void __init dmi_save_oem_strings_devices(const struct dmi_header *dm)
{
- int i, count = *(u8 *)(dm + 1);
+ int i, count;
struct dmi_device *dev;
+ if (dm->length < 0x05)
+ return;
+
+ count = *(u8 *)(dm + 1);
for (i = 1; i <= count; i++) {
const char *devname = dmi_string(dm, i);
@@ -353,6 +359,9 @@ static void __init dmi_save_extended_devices(const struct dmi_header *dm)
const char *name;
const u8 *d = (u8 *)dm;
+ if (dm->length < 0x0B)
+ return;
+
/* Skip disabled device */
if ((d[0x5] & 0x80) == 0)
return;
@@ -387,7 +396,7 @@ static void __init save_mem_devices(const struct dmi_header *dm, void *v)
const char *d = (const char *)dm;
static int nr;
- if (dm->type != DMI_ENTRY_MEM_DEVICE)
+ if (dm->type != DMI_ENTRY_MEM_DEVICE || dm->length < 0x12)
return;
if (nr >= dmi_memdev_nr) {
pr_warn(FW_BUG "Too many DIMM entries in SMBIOS table\n");
@@ -430,6 +439,7 @@ static void __init dmi_decode(const struct dmi_header *dm, void *dummy)
dmi_save_ident(dm, DMI_PRODUCT_VERSION, 6);
dmi_save_ident(dm, DMI_PRODUCT_SERIAL, 7);
dmi_save_uuid(dm, DMI_PRODUCT_UUID, 8);
+ dmi_save_ident(dm, DMI_PRODUCT_FAMILY, 26);
break;
case 2: /* Base Board Information */
dmi_save_ident(dm, DMI_BOARD_VENDOR, 4);
@@ -649,6 +659,21 @@ void __init dmi_scan_machine(void)
goto error;
/*
+ * Same logic as above, look for a 64-bit entry point
+ * first, and if not found, fall back to 32-bit entry point.
+ */
+ memcpy_fromio(buf, p, 16);
+ for (q = p + 16; q < p + 0x10000; q += 16) {
+ memcpy_fromio(buf + 16, q, 16);
+ if (!dmi_smbios3_present(buf)) {
+ dmi_available = 1;
+ dmi_early_unmap(p, 0x10000);
+ goto out;
+ }
+ memcpy(buf, buf + 16, 16);
+ }
+
+ /*
* Iterate over all possible DMI header addresses q.
* Maintain the 32 bytes around q in buf. On the
* first iteration, substitute zero for the
@@ -658,7 +683,7 @@ void __init dmi_scan_machine(void)
memset(buf, 0, 16);
for (q = p; q < p + 0x10000; q += 16) {
memcpy_fromio(buf + 16, q, 16);
- if (!dmi_smbios3_present(buf) || !dmi_present(buf)) {
+ if (!dmi_present(buf)) {
dmi_available = 1;
dmi_early_unmap(p, 0x10000);
goto out;
@@ -992,7 +1017,8 @@ EXPORT_SYMBOL(dmi_get_date);
* @decode: Callback function
* @private_data: Private data to be passed to the callback function
*
- * Returns -1 when the DMI table can't be reached, 0 on success.
+ * Returns 0 on success, -ENXIO if DMI is not selected or not present,
+ * or a different negative error code if DMI walking fails.
*/
int dmi_walk(void (*decode)(const struct dmi_header *, void *),
void *private_data)
@@ -1000,11 +1026,11 @@ int dmi_walk(void (*decode)(const struct dmi_header *, void *),
u8 *buf;
if (!dmi_available)
- return -1;
+ return -ENXIO;
buf = dmi_remap(dmi_base, dmi_len);
if (buf == NULL)
- return -1;
+ return -ENOMEM;
dmi_decode_table(buf, decode, private_data);
diff --git a/drivers/firmware/efi/Kconfig b/drivers/firmware/efi/Kconfig
index 2e78b0b96d74..394db40ed374 100644
--- a/drivers/firmware/efi/Kconfig
+++ b/drivers/firmware/efi/Kconfig
@@ -112,6 +112,15 @@ config EFI_CAPSULE_LOADER
Most users should say N.
+config EFI_CAPSULE_QUIRK_QUARK_CSH
+ boolean "Add support for Quark capsules with non-standard headers"
+ depends on X86 && !64BIT
+ select EFI_CAPSULE_LOADER
+ default y
+ help
+ Add support for processing Quark X1000 EFI capsules, whose header
+ layout deviates from the layout mandated by the UEFI specification.
+
config EFI_TEST
tristate "EFI Runtime Service Tests Support"
depends on EFI
diff --git a/drivers/firmware/efi/arm-runtime.c b/drivers/firmware/efi/arm-runtime.c
index 974c5a31a005..1cc41c3d6315 100644
--- a/drivers/firmware/efi/arm-runtime.c
+++ b/drivers/firmware/efi/arm-runtime.c
@@ -11,6 +11,7 @@
*
*/
+#include <linux/dmi.h>
#include <linux/efi.h>
#include <linux/io.h>
#include <linux/memblock.h>
@@ -166,3 +167,18 @@ void efi_virtmap_unload(void)
efi_set_pgd(current->active_mm);
preempt_enable();
}
+
+
+static int __init arm_dmi_init(void)
+{
+ /*
+ * On arm64/ARM, DMI depends on UEFI, and dmi_scan_machine() needs to
+ * be called early because dmi_id_init(), which is an arch_initcall
+ * itself, depends on dmi_scan_machine() having been called already.
+ */
+ dmi_scan_machine();
+ if (dmi_available)
+ dmi_set_dump_stack_arch_desc();
+ return 0;
+}
+core_initcall(arm_dmi_init);
diff --git a/drivers/firmware/efi/capsule-loader.c b/drivers/firmware/efi/capsule-loader.c
index 9ae6c116c474..ec8ac5c4dd84 100644
--- a/drivers/firmware/efi/capsule-loader.c
+++ b/drivers/firmware/efi/capsule-loader.c
@@ -20,15 +20,9 @@
#define NO_FURTHER_WRITE_ACTION -1
-struct capsule_info {
- bool header_obtained;
- int reset_type;
- long index;
- size_t count;
- size_t total_size;
- struct page **pages;
- size_t page_bytes_remain;
-};
+#ifndef phys_to_page
+#define phys_to_page(x) pfn_to_page((x) >> PAGE_SHIFT)
+#endif
/**
* efi_free_all_buff_pages - free all previous allocated buffer pages
@@ -41,65 +35,70 @@ struct capsule_info {
static void efi_free_all_buff_pages(struct capsule_info *cap_info)
{
while (cap_info->index > 0)
- __free_page(cap_info->pages[--cap_info->index]);
+ __free_page(phys_to_page(cap_info->pages[--cap_info->index]));
cap_info->index = NO_FURTHER_WRITE_ACTION;
}
-/**
- * efi_capsule_setup_info - obtain the efi capsule header in the binary and
- * setup capsule_info structure
- * @cap_info: pointer to current instance of capsule_info structure
- * @kbuff: a mapped first page buffer pointer
- * @hdr_bytes: the total received number of bytes for efi header
- **/
-static ssize_t efi_capsule_setup_info(struct capsule_info *cap_info,
- void *kbuff, size_t hdr_bytes)
+int __efi_capsule_setup_info(struct capsule_info *cap_info)
{
- efi_capsule_header_t *cap_hdr;
size_t pages_needed;
int ret;
void *temp_page;
- /* Only process data block that is larger than efi header size */
- if (hdr_bytes < sizeof(efi_capsule_header_t))
- return 0;
-
- /* Reset back to the correct offset of header */
- cap_hdr = kbuff - cap_info->count;
- pages_needed = ALIGN(cap_hdr->imagesize, PAGE_SIZE) >> PAGE_SHIFT;
+ pages_needed = ALIGN(cap_info->total_size, PAGE_SIZE) / PAGE_SIZE;
if (pages_needed == 0) {
- pr_err("%s: pages count invalid\n", __func__);
+ pr_err("invalid capsule size");
return -EINVAL;
}
/* Check if the capsule binary supported */
- ret = efi_capsule_supported(cap_hdr->guid, cap_hdr->flags,
- cap_hdr->imagesize,
+ ret = efi_capsule_supported(cap_info->header.guid,
+ cap_info->header.flags,
+ cap_info->header.imagesize,
&cap_info->reset_type);
if (ret) {
- pr_err("%s: efi_capsule_supported() failed\n",
- __func__);
+ pr_err("capsule not supported\n");
return ret;
}
- cap_info->total_size = cap_hdr->imagesize;
temp_page = krealloc(cap_info->pages,
pages_needed * sizeof(void *),
GFP_KERNEL | __GFP_ZERO);
- if (!temp_page) {
- pr_debug("%s: krealloc() failed\n", __func__);
+ if (!temp_page)
return -ENOMEM;
- }
cap_info->pages = temp_page;
- cap_info->header_obtained = true;
return 0;
}
/**
+ * efi_capsule_setup_info - obtain the efi capsule header in the binary and
+ * setup capsule_info structure
+ * @cap_info: pointer to current instance of capsule_info structure
+ * @kbuff: a mapped first page buffer pointer
+ * @hdr_bytes: the total received number of bytes for efi header
+ *
+ * Platforms with non-standard capsule update mechanisms can override
+ * this __weak function so they can perform any required capsule
+ * image munging. See quark_quirk_function() for an example.
+ **/
+int __weak efi_capsule_setup_info(struct capsule_info *cap_info, void *kbuff,
+ size_t hdr_bytes)
+{
+ /* Only process data block that is larger than efi header size */
+ if (hdr_bytes < sizeof(efi_capsule_header_t))
+ return 0;
+
+ memcpy(&cap_info->header, kbuff, sizeof(cap_info->header));
+ cap_info->total_size = cap_info->header.imagesize;
+
+ return __efi_capsule_setup_info(cap_info);
+}
+
+/**
* efi_capsule_submit_update - invoke the efi_capsule_update API once binary
* upload done
* @cap_info: pointer to current instance of capsule_info structure
@@ -107,26 +106,17 @@ static ssize_t efi_capsule_setup_info(struct capsule_info *cap_info,
static ssize_t efi_capsule_submit_update(struct capsule_info *cap_info)
{
int ret;
- void *cap_hdr_temp;
-
- cap_hdr_temp = vmap(cap_info->pages, cap_info->index,
- VM_MAP, PAGE_KERNEL);
- if (!cap_hdr_temp) {
- pr_debug("%s: vmap() failed\n", __func__);
- return -EFAULT;
- }
- ret = efi_capsule_update(cap_hdr_temp, cap_info->pages);
- vunmap(cap_hdr_temp);
+ ret = efi_capsule_update(&cap_info->header, cap_info->pages);
if (ret) {
- pr_err("%s: efi_capsule_update() failed\n", __func__);
+ pr_err("capsule update failed\n");
return ret;
}
/* Indicate capsule binary uploading is done */
cap_info->index = NO_FURTHER_WRITE_ACTION;
- pr_info("%s: Successfully upload capsule file with reboot type '%s'\n",
- __func__, !cap_info->reset_type ? "RESET_COLD" :
+ pr_info("Successfully upload capsule file with reboot type '%s'\n",
+ !cap_info->reset_type ? "RESET_COLD" :
cap_info->reset_type == 1 ? "RESET_WARM" :
"RESET_SHUTDOWN");
return 0;
@@ -171,37 +161,30 @@ static ssize_t efi_capsule_write(struct file *file, const char __user *buff,
if (!cap_info->page_bytes_remain) {
page = alloc_page(GFP_KERNEL);
if (!page) {
- pr_debug("%s: alloc_page() failed\n", __func__);
ret = -ENOMEM;
goto failed;
}
- cap_info->pages[cap_info->index++] = page;
+ cap_info->pages[cap_info->index++] = page_to_phys(page);
cap_info->page_bytes_remain = PAGE_SIZE;
+ } else {
+ page = phys_to_page(cap_info->pages[cap_info->index - 1]);
}
- page = cap_info->pages[cap_info->index - 1];
-
kbuff = kmap(page);
- if (!kbuff) {
- pr_debug("%s: kmap() failed\n", __func__);
- ret = -EFAULT;
- goto failed;
- }
kbuff += PAGE_SIZE - cap_info->page_bytes_remain;
/* Copy capsule binary data from user space to kernel space buffer */
write_byte = min_t(size_t, count, cap_info->page_bytes_remain);
if (copy_from_user(kbuff, buff, write_byte)) {
- pr_debug("%s: copy_from_user() failed\n", __func__);
ret = -EFAULT;
goto fail_unmap;
}
cap_info->page_bytes_remain -= write_byte;
/* Setup capsule binary info structure */
- if (!cap_info->header_obtained) {
- ret = efi_capsule_setup_info(cap_info, kbuff,
+ if (cap_info->header.headersize == 0) {
+ ret = efi_capsule_setup_info(cap_info, kbuff - cap_info->count,
cap_info->count + write_byte);
if (ret)
goto fail_unmap;
@@ -211,11 +194,10 @@ static ssize_t efi_capsule_write(struct file *file, const char __user *buff,
kunmap(page);
/* Submit the full binary to efi_capsule_update() API */
- if (cap_info->header_obtained &&
+ if (cap_info->header.headersize > 0 &&
cap_info->count >= cap_info->total_size) {
if (cap_info->count > cap_info->total_size) {
- pr_err("%s: upload size exceeded header defined size\n",
- __func__);
+ pr_err("capsule upload size exceeded header defined size\n");
ret = -EINVAL;
goto failed;
}
@@ -249,7 +231,7 @@ static int efi_capsule_flush(struct file *file, fl_owner_t id)
struct capsule_info *cap_info = file->private_data;
if (cap_info->index > 0) {
- pr_err("%s: capsule upload not complete\n", __func__);
+ pr_err("capsule upload not complete\n");
efi_free_all_buff_pages(cap_info);
ret = -ECANCELED;
}
@@ -328,8 +310,7 @@ static int __init efi_capsule_loader_init(void)
ret = misc_register(&efi_capsule_misc);
if (ret)
- pr_err("%s: Failed to register misc char file note\n",
- __func__);
+ pr_err("Unable to register capsule loader device\n");
return ret;
}
diff --git a/drivers/firmware/efi/capsule.c b/drivers/firmware/efi/capsule.c
index 6eedff45e6d7..901b9306bf94 100644
--- a/drivers/firmware/efi/capsule.c
+++ b/drivers/firmware/efi/capsule.c
@@ -214,7 +214,7 @@ efi_capsule_update_locked(efi_capsule_header_t *capsule,
*
* Return 0 on success, a converted EFI status code on failure.
*/
-int efi_capsule_update(efi_capsule_header_t *capsule, struct page **pages)
+int efi_capsule_update(efi_capsule_header_t *capsule, phys_addr_t *pages)
{
u32 imagesize = capsule->imagesize;
efi_guid_t guid = capsule->guid;
@@ -247,16 +247,13 @@ int efi_capsule_update(efi_capsule_header_t *capsule, struct page **pages)
efi_capsule_block_desc_t *sglist;
sglist = kmap(sg_pages[i]);
- if (!sglist) {
- rv = -ENOMEM;
- goto out;
- }
for (j = 0; j < SGLIST_PER_PAGE && count > 0; j++) {
- u64 sz = min_t(u64, imagesize, PAGE_SIZE);
+ u64 sz = min_t(u64, imagesize,
+ PAGE_SIZE - (u64)*pages % PAGE_SIZE);
sglist[j].length = sz;
- sglist[j].data = page_to_phys(*pages++);
+ sglist[j].data = *pages++;
imagesize -= sz;
count--;
diff --git a/drivers/firmware/efi/efi-bgrt.c b/drivers/firmware/efi/efi-bgrt.c
index 04ca8764f0c0..b58233e4ed71 100644
--- a/drivers/firmware/efi/efi-bgrt.c
+++ b/drivers/firmware/efi/efi-bgrt.c
@@ -27,6 +27,26 @@ struct bmp_header {
u32 size;
} __packed;
+static bool efi_bgrt_addr_valid(u64 addr)
+{
+ efi_memory_desc_t *md;
+
+ for_each_efi_memory_desc(md) {
+ u64 size;
+ u64 end;
+
+ if (md->type != EFI_BOOT_SERVICES_DATA)
+ continue;
+
+ size = md->num_pages << EFI_PAGE_SHIFT;
+ end = md->phys_addr + size;
+ if (addr >= md->phys_addr && addr < end)
+ return true;
+ }
+
+ return false;
+}
+
void __init efi_bgrt_init(struct acpi_table_header *table)
{
void *image;
@@ -36,6 +56,9 @@ void __init efi_bgrt_init(struct acpi_table_header *table)
if (acpi_disabled)
return;
+ if (!efi_enabled(EFI_MEMMAP))
+ return;
+
if (table->length < sizeof(bgrt_tab)) {
pr_notice("Ignoring BGRT: invalid length %u (expected %zu)\n",
table->length, sizeof(bgrt_tab));
@@ -62,6 +85,10 @@ void __init efi_bgrt_init(struct acpi_table_header *table)
goto out;
}
+ if (!efi_bgrt_addr_valid(bgrt->image_address)) {
+ pr_notice("Ignoring BGRT: invalid image address\n");
+ goto out;
+ }
image = early_memremap(bgrt->image_address, sizeof(bmp_header));
if (!image) {
pr_notice("Ignoring BGRT: failed to map image header memory\n");
diff --git a/drivers/firmware/efi/efi-pstore.c b/drivers/firmware/efi/efi-pstore.c
index ab3a951a17e6..ef1fafdad400 100644
--- a/drivers/firmware/efi/efi-pstore.c
+++ b/drivers/firmware/efi/efi-pstore.c
@@ -53,6 +53,7 @@ static int efi_pstore_read_func(struct efivar_entry *entry,
if (sscanf(name, "dump-type%u-%u-%d-%lu-%c",
&record->type, &part, &cnt, &time, &data_type) == 5) {
record->id = generic_id(time, part, cnt);
+ record->part = part;
record->count = cnt;
record->time.tv_sec = time;
record->time.tv_nsec = 0;
@@ -64,6 +65,7 @@ static int efi_pstore_read_func(struct efivar_entry *entry,
} else if (sscanf(name, "dump-type%u-%u-%d-%lu",
&record->type, &part, &cnt, &time) == 4) {
record->id = generic_id(time, part, cnt);
+ record->part = part;
record->count = cnt;
record->time.tv_sec = time;
record->time.tv_nsec = 0;
@@ -77,6 +79,7 @@ static int efi_pstore_read_func(struct efivar_entry *entry,
* multiple logs, remains.
*/
record->id = generic_id(time, part, 0);
+ record->part = part;
record->count = 0;
record->time.tv_sec = time;
record->time.tv_nsec = 0;
@@ -241,9 +244,15 @@ static int efi_pstore_write(struct pstore_record *record)
efi_guid_t vendor = LINUX_EFI_CRASH_GUID;
int i, ret = 0;
+ record->time.tv_sec = get_seconds();
+ record->time.tv_nsec = 0;
+
+ record->id = generic_id(record->time.tv_sec, record->part,
+ record->count);
+
snprintf(name, sizeof(name), "dump-type%u-%u-%d-%lu-%c",
record->type, record->part, record->count,
- get_seconds(), record->compressed ? 'C' : 'D');
+ record->time.tv_sec, record->compressed ? 'C' : 'D');
for (i = 0; i < DUMP_NAME_LEN; i++)
efi_name[i] = name[i];
@@ -255,7 +264,6 @@ static int efi_pstore_write(struct pstore_record *record)
if (record->reason == KMSG_DUMP_OOPS)
efivar_run_worker();
- record->id = record->part;
return ret;
};
@@ -287,7 +295,7 @@ static int efi_pstore_erase_func(struct efivar_entry *entry, void *data)
* holding multiple logs, remains.
*/
snprintf(name_old, sizeof(name_old), "dump-type%u-%u-%lu",
- ed->record->type, (unsigned int)ed->record->id,
+ ed->record->type, ed->record->part,
ed->record->time.tv_sec);
for (i = 0; i < DUMP_NAME_LEN; i++)
@@ -320,10 +328,7 @@ static int efi_pstore_erase(struct pstore_record *record)
char name[DUMP_NAME_LEN];
efi_char16_t efi_name[DUMP_NAME_LEN];
int found, i;
- unsigned int part;
- do_div(record->id, 1000);
- part = do_div(record->id, 100);
snprintf(name, sizeof(name), "dump-type%u-%u-%d-%lu",
record->type, record->part, record->count,
record->time.tv_sec);
diff --git a/drivers/firmware/efi/efi.c b/drivers/firmware/efi/efi.c
index b372aad3b449..045d6d311bde 100644
--- a/drivers/firmware/efi/efi.c
+++ b/drivers/firmware/efi/efi.c
@@ -528,7 +528,8 @@ int __init efi_config_parse_tables(void *config_tables, int count, int sz,
}
}
- efi_memattr_init();
+ if (efi_enabled(EFI_MEMMAP))
+ efi_memattr_init();
/* Parse the EFI Properties table if it exists */
if (efi.properties_table != EFI_INVALID_TABLE_ADDR) {
diff --git a/drivers/firmware/efi/libstub/secureboot.c b/drivers/firmware/efi/libstub/secureboot.c
index 8c34d50a4d80..959777ec8a77 100644
--- a/drivers/firmware/efi/libstub/secureboot.c
+++ b/drivers/firmware/efi/libstub/secureboot.c
@@ -16,10 +16,10 @@
/* BIOS variables */
static const efi_guid_t efi_variable_guid = EFI_GLOBAL_VARIABLE_GUID;
-static const efi_char16_t const efi_SecureBoot_name[] = {
+static const efi_char16_t efi_SecureBoot_name[] = {
'S', 'e', 'c', 'u', 'r', 'e', 'B', 'o', 'o', 't', 0
};
-static const efi_char16_t const efi_SetupMode_name[] = {
+static const efi_char16_t efi_SetupMode_name[] = {
'S', 'e', 't', 'u', 'p', 'M', 'o', 'd', 'e', 0
};
diff --git a/drivers/firmware/efi/test/efi_test.c b/drivers/firmware/efi/test/efi_test.c
index 8cd578f62059..08129b7b80ab 100644
--- a/drivers/firmware/efi/test/efi_test.c
+++ b/drivers/firmware/efi/test/efi_test.c
@@ -71,18 +71,13 @@ copy_ucs2_from_user_len(efi_char16_t **dst, efi_char16_t __user *src,
if (!access_ok(VERIFY_READ, src, 1))
return -EFAULT;
- buf = kmalloc(len, GFP_KERNEL);
- if (!buf) {
+ buf = memdup_user(src, len);
+ if (IS_ERR(buf)) {
*dst = NULL;
- return -ENOMEM;
+ return PTR_ERR(buf);
}
*dst = buf;
- if (copy_from_user(*dst, src, len)) {
- kfree(buf);
- return -EFAULT;
- }
-
return 0;
}
diff --git a/drivers/firmware/google/vpd.c b/drivers/firmware/google/vpd.c
index 1e7860f02f4f..31058d400bda 100644
--- a/drivers/firmware/google/vpd.c
+++ b/drivers/firmware/google/vpd.c
@@ -136,12 +136,12 @@ static int vpd_section_attrib_add(const u8 *key, s32 key_len,
info->value = value;
INIT_LIST_HEAD(&info->list);
- list_add_tail(&info->list, &sec->attribs);
ret = sysfs_create_bin_file(sec->kobj, &info->bin_attr);
if (ret)
goto free_info_key;
+ list_add_tail(&info->list, &sec->attribs);
return 0;
free_info_key:
@@ -158,8 +158,8 @@ static void vpd_section_attrib_destroy(struct vpd_section *sec)
struct vpd_attrib_info *temp;
list_for_each_entry_safe(info, temp, &sec->attribs, list) {
- kfree(info->key);
sysfs_remove_bin_file(sec->kobj, &info->bin_attr);
+ kfree(info->key);
kfree(info);
}
}
@@ -244,7 +244,7 @@ static int vpd_section_destroy(struct vpd_section *sec)
{
if (sec->enabled) {
vpd_section_attrib_destroy(sec);
- kobject_del(sec->kobj);
+ kobject_put(sec->kobj);
sysfs_remove_bin_file(vpd_kobj, &sec->bin_attr);
kfree(sec->raw_name);
iounmap(sec->baseaddr);
@@ -331,7 +331,7 @@ static void __exit vpd_platform_exit(void)
{
vpd_section_destroy(&ro_vpd);
vpd_section_destroy(&rw_vpd);
- kobject_del(vpd_kobj);
+ kobject_put(vpd_kobj);
}
module_init(vpd_platform_init);
diff --git a/drivers/gpio/gpio-aspeed.c b/drivers/gpio/gpio-aspeed.c
index ccea609676ee..4ca436e66bdb 100644
--- a/drivers/gpio/gpio-aspeed.c
+++ b/drivers/gpio/gpio-aspeed.c
@@ -646,6 +646,9 @@ static int enable_debounce(struct gpio_chip *chip, unsigned int offset,
int rc;
int i;
+ if (!gpio->clk)
+ return -EINVAL;
+
rc = usecs_to_cycles(gpio, usecs, &requested_cycles);
if (rc < 0) {
dev_warn(chip->parent, "Failed to convert %luus to cycles at %luHz: %d\n",
diff --git a/drivers/gpio/gpio-crystalcove.c b/drivers/gpio/gpio-crystalcove.c
index 2197368cc899..e60156ec0c18 100644
--- a/drivers/gpio/gpio-crystalcove.c
+++ b/drivers/gpio/gpio-crystalcove.c
@@ -90,8 +90,18 @@ static inline int to_reg(int gpio, enum ctrl_register reg_type)
{
int reg;
- if (gpio == 94)
- return GPIOPANELCTL;
+ if (gpio >= CRYSTALCOVE_GPIO_NUM) {
+ /*
+ * Virtual GPIO called from ACPI, for now we only support
+ * the panel ctl.
+ */
+ switch (gpio) {
+ case 0x5e:
+ return GPIOPANELCTL;
+ default:
+ return -EOPNOTSUPP;
+ }
+ }
if (reg_type == CTRL_IN) {
if (gpio < 8)
@@ -130,36 +140,36 @@ static void crystalcove_update_irq_ctrl(struct crystalcove_gpio *cg, int gpio)
static int crystalcove_gpio_dir_in(struct gpio_chip *chip, unsigned gpio)
{
struct crystalcove_gpio *cg = gpiochip_get_data(chip);
+ int reg = to_reg(gpio, CTRL_OUT);
- if (gpio > CRYSTALCOVE_VGPIO_NUM)
+ if (reg < 0)
return 0;
- return regmap_write(cg->regmap, to_reg(gpio, CTRL_OUT),
- CTLO_INPUT_SET);
+ return regmap_write(cg->regmap, reg, CTLO_INPUT_SET);
}
static int crystalcove_gpio_dir_out(struct gpio_chip *chip, unsigned gpio,
int value)
{
struct crystalcove_gpio *cg = gpiochip_get_data(chip);
+ int reg = to_reg(gpio, CTRL_OUT);
- if (gpio > CRYSTALCOVE_VGPIO_NUM)
+ if (reg < 0)
return 0;
- return regmap_write(cg->regmap, to_reg(gpio, CTRL_OUT),
- CTLO_OUTPUT_SET | value);
+ return regmap_write(cg->regmap, reg, CTLO_OUTPUT_SET | value);
}
static int crystalcove_gpio_get(struct gpio_chip *chip, unsigned gpio)
{
struct crystalcove_gpio *cg = gpiochip_get_data(chip);
- int ret;
unsigned int val;
+ int ret, reg = to_reg(gpio, CTRL_IN);
- if (gpio > CRYSTALCOVE_VGPIO_NUM)
+ if (reg < 0)
return 0;
- ret = regmap_read(cg->regmap, to_reg(gpio, CTRL_IN), &val);
+ ret = regmap_read(cg->regmap, reg, &val);
if (ret)
return ret;
@@ -170,14 +180,15 @@ static void crystalcove_gpio_set(struct gpio_chip *chip,
unsigned gpio, int value)
{
struct crystalcove_gpio *cg = gpiochip_get_data(chip);
+ int reg = to_reg(gpio, CTRL_OUT);
- if (gpio > CRYSTALCOVE_VGPIO_NUM)
+ if (reg < 0)
return;
if (value)
- regmap_update_bits(cg->regmap, to_reg(gpio, CTRL_OUT), 1, 1);
+ regmap_update_bits(cg->regmap, reg, 1, 1);
else
- regmap_update_bits(cg->regmap, to_reg(gpio, CTRL_OUT), 1, 0);
+ regmap_update_bits(cg->regmap, reg, 1, 0);
}
static int crystalcove_irq_type(struct irq_data *data, unsigned type)
@@ -185,6 +196,9 @@ static int crystalcove_irq_type(struct irq_data *data, unsigned type)
struct crystalcove_gpio *cg =
gpiochip_get_data(irq_data_get_irq_chip_data(data));
+ if (data->hwirq >= CRYSTALCOVE_GPIO_NUM)
+ return 0;
+
switch (type) {
case IRQ_TYPE_NONE:
cg->intcnt_value = CTLI_INTCNT_DIS;
@@ -235,8 +249,10 @@ static void crystalcove_irq_unmask(struct irq_data *data)
struct crystalcove_gpio *cg =
gpiochip_get_data(irq_data_get_irq_chip_data(data));
- cg->set_irq_mask = false;
- cg->update |= UPDATE_IRQ_MASK;
+ if (data->hwirq < CRYSTALCOVE_GPIO_NUM) {
+ cg->set_irq_mask = false;
+ cg->update |= UPDATE_IRQ_MASK;
+ }
}
static void crystalcove_irq_mask(struct irq_data *data)
@@ -244,8 +260,10 @@ static void crystalcove_irq_mask(struct irq_data *data)
struct crystalcove_gpio *cg =
gpiochip_get_data(irq_data_get_irq_chip_data(data));
- cg->set_irq_mask = true;
- cg->update |= UPDATE_IRQ_MASK;
+ if (data->hwirq < CRYSTALCOVE_GPIO_NUM) {
+ cg->set_irq_mask = true;
+ cg->update |= UPDATE_IRQ_MASK;
+ }
}
static struct irq_chip crystalcove_irqchip = {
diff --git a/drivers/gpio/gpio-mvebu.c b/drivers/gpio/gpio-mvebu.c
index 19a92efabbef..c83ea68be792 100644
--- a/drivers/gpio/gpio-mvebu.c
+++ b/drivers/gpio/gpio-mvebu.c
@@ -721,7 +721,7 @@ static int mvebu_pwm_probe(struct platform_device *pdev,
u32 set;
if (!of_device_is_compatible(mvchip->chip.of_node,
- "marvell,armada-370-xp-gpio"))
+ "marvell,armada-370-gpio"))
return 0;
if (IS_ERR(mvchip->clk))
@@ -747,7 +747,7 @@ static int mvebu_pwm_probe(struct platform_device *pdev,
set = U32_MAX;
else
return -EINVAL;
- writel_relaxed(0, mvebu_gpioreg_blink_counter_select(mvchip));
+ writel_relaxed(set, mvebu_gpioreg_blink_counter_select(mvchip));
mvpwm = devm_kzalloc(dev, sizeof(struct mvebu_pwm), GFP_KERNEL);
if (!mvpwm)
@@ -768,6 +768,13 @@ static int mvebu_pwm_probe(struct platform_device *pdev,
mvpwm->chip.dev = dev;
mvpwm->chip.ops = &mvebu_pwm_ops;
mvpwm->chip.npwm = mvchip->chip.ngpio;
+ /*
+ * There may already be some PWM allocated, so we can't force
+ * mvpwm->chip.base to a fixed point like mvchip->chip.base.
+ * So, we let pwmchip_add() do the numbering and take the next free
+ * region.
+ */
+ mvpwm->chip.base = -1;
spin_lock_init(&mvpwm->lock);
@@ -845,7 +852,7 @@ static const struct of_device_id mvebu_gpio_of_match[] = {
.data = (void *) MVEBU_GPIO_SOC_VARIANT_ARMADAXP,
},
{
- .compatible = "marvell,armada-370-xp-gpio",
+ .compatible = "marvell,armada-370-gpio",
.data = (void *) MVEBU_GPIO_SOC_VARIANT_ORION,
},
{
@@ -1121,7 +1128,7 @@ static int mvebu_gpio_probe(struct platform_device *pdev)
mvchip);
}
- /* Armada 370/XP has simple PWM support for GPIO lines */
+ /* Some MVEBU SoCs have simple PWM support for GPIO lines */
if (IS_ENABLED(CONFIG_PWM))
return mvebu_pwm_probe(pdev, mvchip, id);
diff --git a/drivers/gpio/gpiolib-acpi.c b/drivers/gpio/gpiolib-acpi.c
index 2185232da823..8fa5fcd00e9a 100644
--- a/drivers/gpio/gpiolib-acpi.c
+++ b/drivers/gpio/gpiolib-acpi.c
@@ -201,7 +201,7 @@ static acpi_status acpi_gpiochip_request_interrupt(struct acpi_resource *ares,
handler = acpi_gpio_irq_handler_evt;
}
if (!handler)
- return AE_BAD_PARAMETER;
+ return AE_OK;
pin = acpi_gpiochip_pin_to_gpio_offset(chip->gpiodev, pin);
if (pin < 0)
diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c
index 5db44139cef8..a42a1eea5714 100644
--- a/drivers/gpio/gpiolib.c
+++ b/drivers/gpio/gpiolib.c
@@ -708,7 +708,8 @@ static irqreturn_t lineevent_irq_thread(int irq, void *p)
ge.timestamp = ktime_get_real_ns();
- if (le->eflags & GPIOEVENT_REQUEST_BOTH_EDGES) {
+ if (le->eflags & GPIOEVENT_REQUEST_RISING_EDGE
+ && le->eflags & GPIOEVENT_REQUEST_FALLING_EDGE) {
int level = gpiod_get_value_cansleep(le->desc);
if (level)
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.c
index 1cf78f4dd339..1e8e1123ddf4 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.c
@@ -693,6 +693,10 @@ int amdgpu_atombios_get_clock_info(struct amdgpu_device *adev)
DRM_INFO("Changing default dispclk from %dMhz to 600Mhz\n",
adev->clock.default_dispclk / 100);
adev->clock.default_dispclk = 60000;
+ } else if (adev->clock.default_dispclk <= 60000) {
+ DRM_INFO("Changing default dispclk from %dMhz to 625Mhz\n",
+ adev->clock.default_dispclk / 100);
+ adev->clock.default_dispclk = 62500;
}
adev->clock.dp_extclk =
le16_to_cpu(firmware_info->info_21.usUniphyDPModeExtClkFreq);
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c
index f2d705e6a75a..ab6b0d0febab 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c
@@ -449,6 +449,7 @@ static const struct pci_device_id pciidlist[] = {
{0x1002, 0x6986, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_POLARIS12},
{0x1002, 0x6987, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_POLARIS12},
{0x1002, 0x6995, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_POLARIS12},
+ {0x1002, 0x6997, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_POLARIS12},
{0x1002, 0x699F, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_POLARIS12},
/* Vega 10 */
{0x1002, 0x6860, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_VEGA10|AMD_EXP_HW_SUPPORT},
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_fb.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_fb.c
index 236d9950221b..c0d8c6ff6380 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_fb.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_fb.c
@@ -425,10 +425,15 @@ bool amdgpu_fbdev_robj_is_fb(struct amdgpu_device *adev, struct amdgpu_bo *robj)
void amdgpu_fbdev_restore_mode(struct amdgpu_device *adev)
{
- struct amdgpu_fbdev *afbdev = adev->mode_info.rfbdev;
+ struct amdgpu_fbdev *afbdev;
struct drm_fb_helper *fb_helper;
int ret;
+ if (!adev)
+ return;
+
+ afbdev = adev->mode_info.rfbdev;
+
if (!afbdev)
return;
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c
index 07ff3b1514f1..8ecf82c5fe74 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c
@@ -634,7 +634,7 @@ int amdgpu_vm_flush(struct amdgpu_ring *ring, struct amdgpu_job *job)
mutex_unlock(&id_mgr->lock);
}
- if (gds_switch_needed) {
+ if (ring->funcs->emit_gds_switch && gds_switch_needed) {
id->gds_base = job->gds_base;
id->gds_size = job->gds_size;
id->gws_base = job->gws_base;
@@ -672,6 +672,7 @@ void amdgpu_vm_reset_id(struct amdgpu_device *adev, unsigned vmhub,
struct amdgpu_vm_id_manager *id_mgr = &adev->vm_manager.id_mgr[vmhub];
struct amdgpu_vm_id *id = &id_mgr->ids[vmid];
+ atomic64_set(&id->owner, 0);
id->gds_base = 0;
id->gds_size = 0;
id->gws_base = 0;
@@ -681,6 +682,26 @@ void amdgpu_vm_reset_id(struct amdgpu_device *adev, unsigned vmhub,
}
/**
+ * amdgpu_vm_reset_all_id - reset VMID to zero
+ *
+ * @adev: amdgpu device structure
+ *
+ * Reset VMID to force flush on next use
+ */
+void amdgpu_vm_reset_all_ids(struct amdgpu_device *adev)
+{
+ unsigned i, j;
+
+ for (i = 0; i < AMDGPU_MAX_VMHUBS; ++i) {
+ struct amdgpu_vm_id_manager *id_mgr =
+ &adev->vm_manager.id_mgr[i];
+
+ for (j = 1; j < id_mgr->num_ids; ++j)
+ amdgpu_vm_reset_id(adev, i, j);
+ }
+}
+
+/**
* amdgpu_vm_bo_find - find the bo_va for a specific vm & bo
*
* @vm: requested vm
@@ -2270,7 +2291,6 @@ void amdgpu_vm_manager_init(struct amdgpu_device *adev)
for (i = 0; i < AMDGPU_MAX_RINGS; ++i)
adev->vm_manager.seqno[i] = 0;
-
atomic_set(&adev->vm_manager.vm_pte_next_ring, 0);
atomic64_set(&adev->vm_manager.client_counter, 0);
spin_lock_init(&adev->vm_manager.prt_lock);
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.h
index d97e28b4bdc4..e1d951ece433 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.h
@@ -204,6 +204,7 @@ int amdgpu_vm_grab_id(struct amdgpu_vm *vm, struct amdgpu_ring *ring,
int amdgpu_vm_flush(struct amdgpu_ring *ring, struct amdgpu_job *job);
void amdgpu_vm_reset_id(struct amdgpu_device *adev, unsigned vmhub,
unsigned vmid);
+void amdgpu_vm_reset_all_ids(struct amdgpu_device *adev);
int amdgpu_vm_update_directories(struct amdgpu_device *adev,
struct amdgpu_vm *vm);
int amdgpu_vm_clear_freed(struct amdgpu_device *adev,
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vram_mgr.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_vram_mgr.c
index a4831fe0223b..a2c59a08b2bd 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vram_mgr.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vram_mgr.c
@@ -220,9 +220,9 @@ static void amdgpu_vram_mgr_debug(struct ttm_mem_type_manager *man,
}
const struct ttm_mem_type_manager_func amdgpu_vram_mgr_func = {
- amdgpu_vram_mgr_init,
- amdgpu_vram_mgr_fini,
- amdgpu_vram_mgr_new,
- amdgpu_vram_mgr_del,
- amdgpu_vram_mgr_debug
+ .init = amdgpu_vram_mgr_init,
+ .takedown = amdgpu_vram_mgr_fini,
+ .get_node = amdgpu_vram_mgr_new,
+ .put_node = amdgpu_vram_mgr_del,
+ .debug = amdgpu_vram_mgr_debug
};
diff --git a/drivers/gpu/drm/amd/amdgpu/atombios_crtc.c b/drivers/gpu/drm/amd/amdgpu/atombios_crtc.c
index 8c9bc75a9c2d..8a0818b23ea4 100644
--- a/drivers/gpu/drm/amd/amdgpu/atombios_crtc.c
+++ b/drivers/gpu/drm/amd/amdgpu/atombios_crtc.c
@@ -165,7 +165,7 @@ void amdgpu_atombios_crtc_powergate(struct drm_crtc *crtc, int state)
struct drm_device *dev = crtc->dev;
struct amdgpu_device *adev = dev->dev_private;
int index = GetIndexIntoMasterTable(COMMAND, EnableDispPowerGating);
- ENABLE_DISP_POWER_GATING_PARAMETERS_V2_1 args;
+ ENABLE_DISP_POWER_GATING_PS_ALLOCATION args;
memset(&args, 0, sizeof(args));
@@ -178,7 +178,7 @@ void amdgpu_atombios_crtc_powergate(struct drm_crtc *crtc, int state)
void amdgpu_atombios_crtc_powergate_init(struct amdgpu_device *adev)
{
int index = GetIndexIntoMasterTable(COMMAND, EnableDispPowerGating);
- ENABLE_DISP_POWER_GATING_PARAMETERS_V2_1 args;
+ ENABLE_DISP_POWER_GATING_PS_ALLOCATION args;
memset(&args, 0, sizeof(args));
diff --git a/drivers/gpu/drm/amd/amdgpu/ci_dpm.c b/drivers/gpu/drm/amd/amdgpu/ci_dpm.c
index 6dc1410b380f..ec93714e4524 100644
--- a/drivers/gpu/drm/amd/amdgpu/ci_dpm.c
+++ b/drivers/gpu/drm/amd/amdgpu/ci_dpm.c
@@ -906,6 +906,12 @@ static bool ci_dpm_vblank_too_short(struct amdgpu_device *adev)
u32 vblank_time = amdgpu_dpm_get_vblank_time(adev);
u32 switch_limit = adev->mc.vram_type == AMDGPU_VRAM_TYPE_GDDR5 ? 450 : 300;
+ /* disable mclk switching if the refresh is >120Hz, even if the
+ * blanking period would allow it
+ */
+ if (amdgpu_dpm_get_vrefresh(adev) > 120)
+ return true;
+
if (vblank_time < switch_limit)
return true;
else
diff --git a/drivers/gpu/drm/amd/amdgpu/dce_v10_0.c b/drivers/gpu/drm/amd/amdgpu/dce_v10_0.c
index 0cdeb6a2e4a0..5dffa27afa45 100644
--- a/drivers/gpu/drm/amd/amdgpu/dce_v10_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/dce_v10_0.c
@@ -1207,8 +1207,11 @@ static void dce_v10_0_program_watermarks(struct amdgpu_device *adev,
u32 tmp, wm_mask, lb_vblank_lead_lines = 0;
if (amdgpu_crtc->base.enabled && num_heads && mode) {
- active_time = 1000000UL * (u32)mode->crtc_hdisplay / (u32)mode->clock;
- line_time = min((u32) (1000000UL * (u32)mode->crtc_htotal / (u32)mode->clock), (u32)65535);
+ active_time = (u32) div_u64((u64)mode->crtc_hdisplay * 1000000,
+ (u32)mode->clock);
+ line_time = (u32) div_u64((u64)mode->crtc_htotal * 1000000,
+ (u32)mode->clock);
+ line_time = min(line_time, (u32)65535);
/* watermark for high clocks */
if (adev->pm.dpm_enabled) {
diff --git a/drivers/gpu/drm/amd/amdgpu/dce_v11_0.c b/drivers/gpu/drm/amd/amdgpu/dce_v11_0.c
index 773654a19749..47bbc87f96d2 100644
--- a/drivers/gpu/drm/amd/amdgpu/dce_v11_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/dce_v11_0.c
@@ -1176,8 +1176,11 @@ static void dce_v11_0_program_watermarks(struct amdgpu_device *adev,
u32 tmp, wm_mask, lb_vblank_lead_lines = 0;
if (amdgpu_crtc->base.enabled && num_heads && mode) {
- active_time = 1000000UL * (u32)mode->crtc_hdisplay / (u32)mode->clock;
- line_time = min((u32) (1000000UL * (u32)mode->crtc_htotal / (u32)mode->clock), (u32)65535);
+ active_time = (u32) div_u64((u64)mode->crtc_hdisplay * 1000000,
+ (u32)mode->clock);
+ line_time = (u32) div_u64((u64)mode->crtc_htotal * 1000000,
+ (u32)mode->clock);
+ line_time = min(line_time, (u32)65535);
/* watermark for high clocks */
if (adev->pm.dpm_enabled) {
diff --git a/drivers/gpu/drm/amd/amdgpu/dce_v6_0.c b/drivers/gpu/drm/amd/amdgpu/dce_v6_0.c
index 1f3552967ba3..d8c9a959493e 100644
--- a/drivers/gpu/drm/amd/amdgpu/dce_v6_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/dce_v6_0.c
@@ -983,8 +983,11 @@ static void dce_v6_0_program_watermarks(struct amdgpu_device *adev,
fixed20_12 a, b, c;
if (amdgpu_crtc->base.enabled && num_heads && mode) {
- active_time = 1000000UL * (u32)mode->crtc_hdisplay / (u32)mode->clock;
- line_time = min((u32) (1000000UL * (u32)mode->crtc_htotal / (u32)mode->clock), (u32)65535);
+ active_time = (u32) div_u64((u64)mode->crtc_hdisplay * 1000000,
+ (u32)mode->clock);
+ line_time = (u32) div_u64((u64)mode->crtc_htotal * 1000000,
+ (u32)mode->clock);
+ line_time = min(line_time, (u32)65535);
priority_a_cnt = 0;
priority_b_cnt = 0;
diff --git a/drivers/gpu/drm/amd/amdgpu/dce_v8_0.c b/drivers/gpu/drm/amd/amdgpu/dce_v8_0.c
index 3c558c170e5e..db30c6ba563a 100644
--- a/drivers/gpu/drm/amd/amdgpu/dce_v8_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/dce_v8_0.c
@@ -1091,8 +1091,11 @@ static void dce_v8_0_program_watermarks(struct amdgpu_device *adev,
u32 tmp, wm_mask, lb_vblank_lead_lines = 0;
if (amdgpu_crtc->base.enabled && num_heads && mode) {
- active_time = 1000000UL * (u32)mode->crtc_hdisplay / (u32)mode->clock;
- line_time = min((u32) (1000000UL * (u32)mode->crtc_htotal / (u32)mode->clock), (u32)65535);
+ active_time = (u32) div_u64((u64)mode->crtc_hdisplay * 1000000,
+ (u32)mode->clock);
+ line_time = (u32) div_u64((u64)mode->crtc_htotal * 1000000,
+ (u32)mode->clock);
+ line_time = min(line_time, (u32)65535);
/* watermark for high clocks */
if (adev->pm.dpm_enabled) {
diff --git a/drivers/gpu/drm/amd/amdgpu/gmc_v6_0.c b/drivers/gpu/drm/amd/amdgpu/gmc_v6_0.c
index a572979f186c..d860939152df 100644
--- a/drivers/gpu/drm/amd/amdgpu/gmc_v6_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/gmc_v6_0.c
@@ -950,10 +950,6 @@ static int gmc_v6_0_suspend(void *handle)
{
struct amdgpu_device *adev = (struct amdgpu_device *)handle;
- if (adev->vm_manager.enabled) {
- gmc_v6_0_vm_fini(adev);
- adev->vm_manager.enabled = false;
- }
gmc_v6_0_hw_fini(adev);
return 0;
@@ -968,16 +964,9 @@ static int gmc_v6_0_resume(void *handle)
if (r)
return r;
- if (!adev->vm_manager.enabled) {
- r = gmc_v6_0_vm_init(adev);
- if (r) {
- dev_err(adev->dev, "vm manager initialization failed (%d).\n", r);
- return r;
- }
- adev->vm_manager.enabled = true;
- }
+ amdgpu_vm_reset_all_ids(adev);
- return r;
+ return 0;
}
static bool gmc_v6_0_is_idle(void *handle)
diff --git a/drivers/gpu/drm/amd/amdgpu/gmc_v7_0.c b/drivers/gpu/drm/amd/amdgpu/gmc_v7_0.c
index a9083a16a250..2750e5c23813 100644
--- a/drivers/gpu/drm/amd/amdgpu/gmc_v7_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/gmc_v7_0.c
@@ -1117,10 +1117,6 @@ static int gmc_v7_0_suspend(void *handle)
{
struct amdgpu_device *adev = (struct amdgpu_device *)handle;
- if (adev->vm_manager.enabled) {
- gmc_v7_0_vm_fini(adev);
- adev->vm_manager.enabled = false;
- }
gmc_v7_0_hw_fini(adev);
return 0;
@@ -1135,16 +1131,9 @@ static int gmc_v7_0_resume(void *handle)
if (r)
return r;
- if (!adev->vm_manager.enabled) {
- r = gmc_v7_0_vm_init(adev);
- if (r) {
- dev_err(adev->dev, "vm manager initialization failed (%d).\n", r);
- return r;
- }
- adev->vm_manager.enabled = true;
- }
+ amdgpu_vm_reset_all_ids(adev);
- return r;
+ return 0;
}
static bool gmc_v7_0_is_idle(void *handle)
diff --git a/drivers/gpu/drm/amd/amdgpu/gmc_v8_0.c b/drivers/gpu/drm/amd/amdgpu/gmc_v8_0.c
index 4ac99784160a..f56b4089ee9f 100644
--- a/drivers/gpu/drm/amd/amdgpu/gmc_v8_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/gmc_v8_0.c
@@ -1209,10 +1209,6 @@ static int gmc_v8_0_suspend(void *handle)
{
struct amdgpu_device *adev = (struct amdgpu_device *)handle;
- if (adev->vm_manager.enabled) {
- gmc_v8_0_vm_fini(adev);
- adev->vm_manager.enabled = false;
- }
gmc_v8_0_hw_fini(adev);
return 0;
@@ -1227,16 +1223,9 @@ static int gmc_v8_0_resume(void *handle)
if (r)
return r;
- if (!adev->vm_manager.enabled) {
- r = gmc_v8_0_vm_init(adev);
- if (r) {
- dev_err(adev->dev, "vm manager initialization failed (%d).\n", r);
- return r;
- }
- adev->vm_manager.enabled = true;
- }
+ amdgpu_vm_reset_all_ids(adev);
- return r;
+ return 0;
}
static bool gmc_v8_0_is_idle(void *handle)
diff --git a/drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c b/drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c
index dc1e1c1d6b24..f936332a069d 100644
--- a/drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c
@@ -791,10 +791,6 @@ static int gmc_v9_0_suspend(void *handle)
{
struct amdgpu_device *adev = (struct amdgpu_device *)handle;
- if (adev->vm_manager.enabled) {
- gmc_v9_0_vm_fini(adev);
- adev->vm_manager.enabled = false;
- }
gmc_v9_0_hw_fini(adev);
return 0;
@@ -809,17 +805,9 @@ static int gmc_v9_0_resume(void *handle)
if (r)
return r;
- if (!adev->vm_manager.enabled) {
- r = gmc_v9_0_vm_init(adev);
- if (r) {
- dev_err(adev->dev,
- "vm manager initialization failed (%d).\n", r);
- return r;
- }
- adev->vm_manager.enabled = true;
- }
+ amdgpu_vm_reset_all_ids(adev);
- return r;
+ return 0;
}
static bool gmc_v9_0_is_idle(void *handle)
diff --git a/drivers/gpu/drm/amd/amdgpu/vce_v3_0.c b/drivers/gpu/drm/amd/amdgpu/vce_v3_0.c
index fb0819359909..90332f55cfba 100644
--- a/drivers/gpu/drm/amd/amdgpu/vce_v3_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/vce_v3_0.c
@@ -77,13 +77,26 @@ static int vce_v3_0_set_clockgating_state(void *handle,
static uint64_t vce_v3_0_ring_get_rptr(struct amdgpu_ring *ring)
{
struct amdgpu_device *adev = ring->adev;
+ u32 v;
+
+ mutex_lock(&adev->grbm_idx_mutex);
+ if (adev->vce.harvest_config == 0 ||
+ adev->vce.harvest_config == AMDGPU_VCE_HARVEST_VCE1)
+ WREG32(mmGRBM_GFX_INDEX, GET_VCE_INSTANCE(0));
+ else if (adev->vce.harvest_config == AMDGPU_VCE_HARVEST_VCE0)
+ WREG32(mmGRBM_GFX_INDEX, GET_VCE_INSTANCE(1));
if (ring == &adev->vce.ring[0])
- return RREG32(mmVCE_RB_RPTR);
+ v = RREG32(mmVCE_RB_RPTR);
else if (ring == &adev->vce.ring[1])
- return RREG32(mmVCE_RB_RPTR2);
+ v = RREG32(mmVCE_RB_RPTR2);
else
- return RREG32(mmVCE_RB_RPTR3);
+ v = RREG32(mmVCE_RB_RPTR3);
+
+ WREG32(mmGRBM_GFX_INDEX, mmGRBM_GFX_INDEX_DEFAULT);
+ mutex_unlock(&adev->grbm_idx_mutex);
+
+ return v;
}
/**
@@ -96,13 +109,26 @@ static uint64_t vce_v3_0_ring_get_rptr(struct amdgpu_ring *ring)
static uint64_t vce_v3_0_ring_get_wptr(struct amdgpu_ring *ring)
{
struct amdgpu_device *adev = ring->adev;
+ u32 v;
+
+ mutex_lock(&adev->grbm_idx_mutex);
+ if (adev->vce.harvest_config == 0 ||
+ adev->vce.harvest_config == AMDGPU_VCE_HARVEST_VCE1)
+ WREG32(mmGRBM_GFX_INDEX, GET_VCE_INSTANCE(0));
+ else if (adev->vce.harvest_config == AMDGPU_VCE_HARVEST_VCE0)
+ WREG32(mmGRBM_GFX_INDEX, GET_VCE_INSTANCE(1));
if (ring == &adev->vce.ring[0])
- return RREG32(mmVCE_RB_WPTR);
+ v = RREG32(mmVCE_RB_WPTR);
else if (ring == &adev->vce.ring[1])
- return RREG32(mmVCE_RB_WPTR2);
+ v = RREG32(mmVCE_RB_WPTR2);
else
- return RREG32(mmVCE_RB_WPTR3);
+ v = RREG32(mmVCE_RB_WPTR3);
+
+ WREG32(mmGRBM_GFX_INDEX, mmGRBM_GFX_INDEX_DEFAULT);
+ mutex_unlock(&adev->grbm_idx_mutex);
+
+ return v;
}
/**
@@ -116,12 +142,22 @@ static void vce_v3_0_ring_set_wptr(struct amdgpu_ring *ring)
{
struct amdgpu_device *adev = ring->adev;
+ mutex_lock(&adev->grbm_idx_mutex);
+ if (adev->vce.harvest_config == 0 ||
+ adev->vce.harvest_config == AMDGPU_VCE_HARVEST_VCE1)
+ WREG32(mmGRBM_GFX_INDEX, GET_VCE_INSTANCE(0));
+ else if (adev->vce.harvest_config == AMDGPU_VCE_HARVEST_VCE0)
+ WREG32(mmGRBM_GFX_INDEX, GET_VCE_INSTANCE(1));
+
if (ring == &adev->vce.ring[0])
WREG32(mmVCE_RB_WPTR, lower_32_bits(ring->wptr));
else if (ring == &adev->vce.ring[1])
WREG32(mmVCE_RB_WPTR2, lower_32_bits(ring->wptr));
else
WREG32(mmVCE_RB_WPTR3, lower_32_bits(ring->wptr));
+
+ WREG32(mmGRBM_GFX_INDEX, mmGRBM_GFX_INDEX_DEFAULT);
+ mutex_unlock(&adev->grbm_idx_mutex);
}
static void vce_v3_0_override_vce_clock_gating(struct amdgpu_device *adev, bool override)
@@ -231,33 +267,38 @@ static int vce_v3_0_start(struct amdgpu_device *adev)
struct amdgpu_ring *ring;
int idx, r;
- ring = &adev->vce.ring[0];
- WREG32(mmVCE_RB_RPTR, lower_32_bits(ring->wptr));
- WREG32(mmVCE_RB_WPTR, lower_32_bits(ring->wptr));
- WREG32(mmVCE_RB_BASE_LO, ring->gpu_addr);
- WREG32(mmVCE_RB_BASE_HI, upper_32_bits(ring->gpu_addr));
- WREG32(mmVCE_RB_SIZE, ring->ring_size / 4);
-
- ring = &adev->vce.ring[1];
- WREG32(mmVCE_RB_RPTR2, lower_32_bits(ring->wptr));
- WREG32(mmVCE_RB_WPTR2, lower_32_bits(ring->wptr));
- WREG32(mmVCE_RB_BASE_LO2, ring->gpu_addr);
- WREG32(mmVCE_RB_BASE_HI2, upper_32_bits(ring->gpu_addr));
- WREG32(mmVCE_RB_SIZE2, ring->ring_size / 4);
-
- ring = &adev->vce.ring[2];
- WREG32(mmVCE_RB_RPTR3, lower_32_bits(ring->wptr));
- WREG32(mmVCE_RB_WPTR3, lower_32_bits(ring->wptr));
- WREG32(mmVCE_RB_BASE_LO3, ring->gpu_addr);
- WREG32(mmVCE_RB_BASE_HI3, upper_32_bits(ring->gpu_addr));
- WREG32(mmVCE_RB_SIZE3, ring->ring_size / 4);
-
mutex_lock(&adev->grbm_idx_mutex);
for (idx = 0; idx < 2; ++idx) {
if (adev->vce.harvest_config & (1 << idx))
continue;
WREG32(mmGRBM_GFX_INDEX, GET_VCE_INSTANCE(idx));
+
+ /* Program instance 0 reg space for two instances or instance 0 case
+ program instance 1 reg space for only instance 1 available case */
+ if (idx != 1 || adev->vce.harvest_config == AMDGPU_VCE_HARVEST_VCE0) {
+ ring = &adev->vce.ring[0];
+ WREG32(mmVCE_RB_RPTR, lower_32_bits(ring->wptr));
+ WREG32(mmVCE_RB_WPTR, lower_32_bits(ring->wptr));
+ WREG32(mmVCE_RB_BASE_LO, ring->gpu_addr);
+ WREG32(mmVCE_RB_BASE_HI, upper_32_bits(ring->gpu_addr));
+ WREG32(mmVCE_RB_SIZE, ring->ring_size / 4);
+
+ ring = &adev->vce.ring[1];
+ WREG32(mmVCE_RB_RPTR2, lower_32_bits(ring->wptr));
+ WREG32(mmVCE_RB_WPTR2, lower_32_bits(ring->wptr));
+ WREG32(mmVCE_RB_BASE_LO2, ring->gpu_addr);
+ WREG32(mmVCE_RB_BASE_HI2, upper_32_bits(ring->gpu_addr));
+ WREG32(mmVCE_RB_SIZE2, ring->ring_size / 4);
+
+ ring = &adev->vce.ring[2];
+ WREG32(mmVCE_RB_RPTR3, lower_32_bits(ring->wptr));
+ WREG32(mmVCE_RB_WPTR3, lower_32_bits(ring->wptr));
+ WREG32(mmVCE_RB_BASE_LO3, ring->gpu_addr);
+ WREG32(mmVCE_RB_BASE_HI3, upper_32_bits(ring->gpu_addr));
+ WREG32(mmVCE_RB_SIZE3, ring->ring_size / 4);
+ }
+
vce_v3_0_mc_resume(adev, idx);
WREG32_FIELD(VCE_STATUS, JOB_BUSY, 1);
diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/smu7_hwmgr.c b/drivers/gpu/drm/amd/powerplay/hwmgr/smu7_hwmgr.c
index a74a3db3056c..102eb6d029fa 100644
--- a/drivers/gpu/drm/amd/powerplay/hwmgr/smu7_hwmgr.c
+++ b/drivers/gpu/drm/amd/powerplay/hwmgr/smu7_hwmgr.c
@@ -2655,6 +2655,28 @@ static int smu7_get_power_state_size(struct pp_hwmgr *hwmgr)
return sizeof(struct smu7_power_state);
}
+static int smu7_vblank_too_short(struct pp_hwmgr *hwmgr,
+ uint32_t vblank_time_us)
+{
+ struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
+ uint32_t switch_limit_us;
+
+ switch (hwmgr->chip_id) {
+ case CHIP_POLARIS10:
+ case CHIP_POLARIS11:
+ case CHIP_POLARIS12:
+ switch_limit_us = data->is_memory_gddr5 ? 190 : 150;
+ break;
+ default:
+ switch_limit_us = data->is_memory_gddr5 ? 450 : 150;
+ break;
+ }
+
+ if (vblank_time_us < switch_limit_us)
+ return true;
+ else
+ return false;
+}
static int smu7_apply_state_adjust_rules(struct pp_hwmgr *hwmgr,
struct pp_power_state *request_ps,
@@ -2669,6 +2691,7 @@ static int smu7_apply_state_adjust_rules(struct pp_hwmgr *hwmgr,
bool disable_mclk_switching;
bool disable_mclk_switching_for_frame_lock;
struct cgs_display_info info = {0};
+ struct cgs_mode_info mode_info = {0};
const struct phm_clock_and_voltage_limits *max_limits;
uint32_t i;
struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
@@ -2677,6 +2700,7 @@ static int smu7_apply_state_adjust_rules(struct pp_hwmgr *hwmgr,
int32_t count;
int32_t stable_pstate_sclk = 0, stable_pstate_mclk = 0;
+ info.mode_info = &mode_info;
data->battery_state = (PP_StateUILabel_Battery ==
request_ps->classification.ui_label);
@@ -2703,8 +2727,6 @@ static int smu7_apply_state_adjust_rules(struct pp_hwmgr *hwmgr,
cgs_get_active_displays_info(hwmgr->device, &info);
- /*TO DO result = PHM_CheckVBlankTime(hwmgr, &vblankTooShort);*/
-
minimum_clocks.engineClock = hwmgr->display_config.min_core_set_clock;
minimum_clocks.memoryClock = hwmgr->display_config.min_mem_set_clock;
@@ -2769,8 +2791,10 @@ static int smu7_apply_state_adjust_rules(struct pp_hwmgr *hwmgr,
PHM_PlatformCaps_DisableMclkSwitchingForFrameLock);
- disable_mclk_switching = (1 < info.display_count) ||
- disable_mclk_switching_for_frame_lock;
+ disable_mclk_switching = ((1 < info.display_count) ||
+ disable_mclk_switching_for_frame_lock ||
+ smu7_vblank_too_short(hwmgr, mode_info.vblank_time_us) ||
+ (mode_info.refresh_rate > 120));
sclk = smu7_ps->performance_levels[0].engine_clock;
mclk = smu7_ps->performance_levels[0].memory_clock;
diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/vega10_hwmgr.c b/drivers/gpu/drm/amd/powerplay/hwmgr/vega10_hwmgr.c
index ad30f5d3a10d..2614af2f553f 100644
--- a/drivers/gpu/drm/amd/powerplay/hwmgr/vega10_hwmgr.c
+++ b/drivers/gpu/drm/amd/powerplay/hwmgr/vega10_hwmgr.c
@@ -4186,7 +4186,7 @@ static int vega10_force_clock_level(struct pp_hwmgr *hwmgr,
enum pp_clock_type type, uint32_t mask)
{
struct vega10_hwmgr *data = (struct vega10_hwmgr *)(hwmgr->backend);
- uint32_t i;
+ int i;
if (hwmgr->dpm_level != AMD_DPM_FORCED_LEVEL_MANUAL)
return -EINVAL;
diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/vega10_thermal.c b/drivers/gpu/drm/amd/powerplay/hwmgr/vega10_thermal.c
index d5f53d04fa08..83e40fe51b62 100644
--- a/drivers/gpu/drm/amd/powerplay/hwmgr/vega10_thermal.c
+++ b/drivers/gpu/drm/amd/powerplay/hwmgr/vega10_thermal.c
@@ -709,17 +709,17 @@ static int tf_vega10_thermal_disable_alert(struct pp_hwmgr *hwmgr,
static struct phm_master_table_item
vega10_thermal_start_thermal_controller_master_list[] = {
- {NULL, tf_vega10_thermal_initialize},
- {NULL, tf_vega10_thermal_set_temperature_range},
- {NULL, tf_vega10_thermal_enable_alert},
+ { .tableFunction = tf_vega10_thermal_initialize },
+ { .tableFunction = tf_vega10_thermal_set_temperature_range },
+ { .tableFunction = tf_vega10_thermal_enable_alert },
/* We should restrict performance levels to low before we halt the SMC.
* On the other hand we are still in boot state when we do this
* so it would be pointless.
* If this assumption changes we have to revisit this table.
*/
- {NULL, tf_vega10_thermal_setup_fan_table},
- {NULL, tf_vega10_thermal_start_smc_fan_control},
- {NULL, NULL}
+ { .tableFunction = tf_vega10_thermal_setup_fan_table },
+ { .tableFunction = tf_vega10_thermal_start_smc_fan_control },
+ { }
};
static struct phm_master_table_header
@@ -731,10 +731,10 @@ vega10_thermal_start_thermal_controller_master = {
static struct phm_master_table_item
vega10_thermal_set_temperature_range_master_list[] = {
- {NULL, tf_vega10_thermal_disable_alert},
- {NULL, tf_vega10_thermal_set_temperature_range},
- {NULL, tf_vega10_thermal_enable_alert},
- {NULL, NULL}
+ { .tableFunction = tf_vega10_thermal_disable_alert },
+ { .tableFunction = tf_vega10_thermal_set_temperature_range },
+ { .tableFunction = tf_vega10_thermal_enable_alert },
+ { }
};
struct phm_master_table_header
diff --git a/drivers/gpu/drm/bridge/synopsys/Kconfig b/drivers/gpu/drm/bridge/synopsys/Kconfig
index 40d2827a6d19..53e78d092d18 100644
--- a/drivers/gpu/drm/bridge/synopsys/Kconfig
+++ b/drivers/gpu/drm/bridge/synopsys/Kconfig
@@ -1,6 +1,7 @@
config DRM_DW_HDMI
tristate
select DRM_KMS_HELPER
+ select REGMAP_MMIO
config DRM_DW_HDMI_AHB_AUDIO
tristate "Synopsys Designware AHB Audio interface"
diff --git a/drivers/gpu/drm/drm_atomic_helper.c b/drivers/gpu/drm/drm_atomic_helper.c
index 8be9719284b0..aa885a614e27 100644
--- a/drivers/gpu/drm/drm_atomic_helper.c
+++ b/drivers/gpu/drm/drm_atomic_helper.c
@@ -508,6 +508,8 @@ drm_atomic_helper_check_modeset(struct drm_device *dev,
bool has_connectors =
!!new_crtc_state->connector_mask;
+ WARN_ON(!drm_modeset_is_locked(&crtc->mutex));
+
if (!drm_mode_equal(&old_crtc_state->mode, &new_crtc_state->mode)) {
DRM_DEBUG_ATOMIC("[CRTC:%d:%s] mode changed\n",
crtc->base.id, crtc->name);
@@ -551,6 +553,8 @@ drm_atomic_helper_check_modeset(struct drm_device *dev,
for_each_oldnew_connector_in_state(state, connector, old_connector_state, new_connector_state, i) {
const struct drm_connector_helper_funcs *funcs = connector->helper_private;
+ WARN_ON(!drm_modeset_is_locked(&dev->mode_config.connection_mutex));
+
/*
* This only sets crtc->connectors_changed for routing changes,
* drivers must set crtc->connectors_changed themselves when
@@ -650,6 +654,8 @@ drm_atomic_helper_check_planes(struct drm_device *dev,
for_each_oldnew_plane_in_state(state, plane, old_plane_state, new_plane_state, i) {
const struct drm_plane_helper_funcs *funcs;
+ WARN_ON(!drm_modeset_is_locked(&plane->mutex));
+
funcs = plane->helper_private;
drm_atomic_helper_plane_changed(state, old_plane_state, new_plane_state, plane);
@@ -2663,7 +2669,12 @@ int drm_atomic_helper_resume(struct drm_device *dev,
drm_modeset_acquire_init(&ctx, 0);
while (1) {
+ err = drm_modeset_lock_all_ctx(dev, &ctx);
+ if (err)
+ goto out;
+
err = drm_atomic_helper_commit_duplicated_state(state, &ctx);
+out:
if (err != -EDEADLK)
break;
diff --git a/drivers/gpu/drm/drm_connector.c b/drivers/gpu/drm/drm_connector.c
index 9f847615ac74..48ca2457df8c 100644
--- a/drivers/gpu/drm/drm_connector.c
+++ b/drivers/gpu/drm/drm_connector.c
@@ -1229,21 +1229,6 @@ int drm_mode_getconnector(struct drm_device *dev, void *data,
if (!connector)
return -ENOENT;
- drm_modeset_lock(&dev->mode_config.connection_mutex, NULL);
- encoder = drm_connector_get_encoder(connector);
- if (encoder)
- out_resp->encoder_id = encoder->base.id;
- else
- out_resp->encoder_id = 0;
-
- ret = drm_mode_object_get_properties(&connector->base, file_priv->atomic,
- (uint32_t __user *)(unsigned long)(out_resp->props_ptr),
- (uint64_t __user *)(unsigned long)(out_resp->prop_values_ptr),
- &out_resp->count_props);
- drm_modeset_unlock(&dev->mode_config.connection_mutex);
- if (ret)
- goto out_unref;
-
for (i = 0; i < DRM_CONNECTOR_MAX_ENCODER; i++)
if (connector->encoder_ids[i] != 0)
encoders_count++;
@@ -1256,7 +1241,7 @@ int drm_mode_getconnector(struct drm_device *dev, void *data,
if (put_user(connector->encoder_ids[i],
encoder_ptr + copied)) {
ret = -EFAULT;
- goto out_unref;
+ goto out;
}
copied++;
}
@@ -1300,15 +1285,32 @@ int drm_mode_getconnector(struct drm_device *dev, void *data,
if (copy_to_user(mode_ptr + copied,
&u_mode, sizeof(u_mode))) {
ret = -EFAULT;
+ mutex_unlock(&dev->mode_config.mutex);
+
goto out;
}
copied++;
}
}
out_resp->count_modes = mode_count;
-out:
mutex_unlock(&dev->mode_config.mutex);
-out_unref:
+
+ drm_modeset_lock(&dev->mode_config.connection_mutex, NULL);
+ encoder = drm_connector_get_encoder(connector);
+ if (encoder)
+ out_resp->encoder_id = encoder->base.id;
+ else
+ out_resp->encoder_id = 0;
+
+ /* Only grab properties after probing, to make sure EDID and other
+ * properties reflect the latest status. */
+ ret = drm_mode_object_get_properties(&connector->base, file_priv->atomic,
+ (uint32_t __user *)(unsigned long)(out_resp->props_ptr),
+ (uint64_t __user *)(unsigned long)(out_resp->prop_values_ptr),
+ &out_resp->count_props);
+ drm_modeset_unlock(&dev->mode_config.connection_mutex);
+
+out:
drm_connector_put(connector);
return ret;
diff --git a/drivers/gpu/drm/drm_dp_helper.c b/drivers/gpu/drm/drm_dp_helper.c
index 3e5f52110ea1..213fb837e1c4 100644
--- a/drivers/gpu/drm/drm_dp_helper.c
+++ b/drivers/gpu/drm/drm_dp_helper.c
@@ -1208,3 +1208,86 @@ int drm_dp_stop_crc(struct drm_dp_aux *aux)
return 0;
}
EXPORT_SYMBOL(drm_dp_stop_crc);
+
+struct dpcd_quirk {
+ u8 oui[3];
+ bool is_branch;
+ u32 quirks;
+};
+
+#define OUI(first, second, third) { (first), (second), (third) }
+
+static const struct dpcd_quirk dpcd_quirk_list[] = {
+ /* Analogix 7737 needs reduced M and N at HBR2 link rates */
+ { OUI(0x00, 0x22, 0xb9), true, BIT(DP_DPCD_QUIRK_LIMITED_M_N) },
+};
+
+#undef OUI
+
+/*
+ * Get a bit mask of DPCD quirks for the sink/branch device identified by
+ * ident. The quirk data is shared but it's up to the drivers to act on the
+ * data.
+ *
+ * For now, only the OUI (first three bytes) is used, but this may be extended
+ * to device identification string and hardware/firmware revisions later.
+ */
+static u32
+drm_dp_get_quirks(const struct drm_dp_dpcd_ident *ident, bool is_branch)
+{
+ const struct dpcd_quirk *quirk;
+ u32 quirks = 0;
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(dpcd_quirk_list); i++) {
+ quirk = &dpcd_quirk_list[i];
+
+ if (quirk->is_branch != is_branch)
+ continue;
+
+ if (memcmp(quirk->oui, ident->oui, sizeof(ident->oui)) != 0)
+ continue;
+
+ quirks |= quirk->quirks;
+ }
+
+ return quirks;
+}
+
+/**
+ * drm_dp_read_desc - read sink/branch descriptor from DPCD
+ * @aux: DisplayPort AUX channel
+ * @desc: Device decriptor to fill from DPCD
+ * @is_branch: true for branch devices, false for sink devices
+ *
+ * Read DPCD 0x400 (sink) or 0x500 (branch) into @desc. Also debug log the
+ * identification.
+ *
+ * Returns 0 on success or a negative error code on failure.
+ */
+int drm_dp_read_desc(struct drm_dp_aux *aux, struct drm_dp_desc *desc,
+ bool is_branch)
+{
+ struct drm_dp_dpcd_ident *ident = &desc->ident;
+ unsigned int offset = is_branch ? DP_BRANCH_OUI : DP_SINK_OUI;
+ int ret, dev_id_len;
+
+ ret = drm_dp_dpcd_read(aux, offset, ident, sizeof(*ident));
+ if (ret < 0)
+ return ret;
+
+ desc->quirks = drm_dp_get_quirks(ident, is_branch);
+
+ dev_id_len = strnlen(ident->device_id, sizeof(ident->device_id));
+
+ DRM_DEBUG_KMS("DP %s: OUI %*phD dev-ID %*pE HW-rev %d.%d SW-rev %d.%d quirks 0x%04x\n",
+ is_branch ? "branch" : "sink",
+ (int)sizeof(ident->oui), ident->oui,
+ dev_id_len, ident->device_id,
+ ident->hw_rev >> 4, ident->hw_rev & 0xf,
+ ident->sw_major_rev, ident->sw_minor_rev,
+ desc->quirks);
+
+ return 0;
+}
+EXPORT_SYMBOL(drm_dp_read_desc);
diff --git a/drivers/gpu/drm/drm_drv.c b/drivers/gpu/drm/drm_drv.c
index b5c6bb46a425..37b8ad3e30d8 100644
--- a/drivers/gpu/drm/drm_drv.c
+++ b/drivers/gpu/drm/drm_drv.c
@@ -358,7 +358,12 @@ EXPORT_SYMBOL(drm_put_dev);
void drm_unplug_dev(struct drm_device *dev)
{
/* for a USB device */
- drm_dev_unregister(dev);
+ if (drm_core_check_feature(dev, DRIVER_MODESET))
+ drm_modeset_unregister_all(dev);
+
+ drm_minor_unregister(dev, DRM_MINOR_PRIMARY);
+ drm_minor_unregister(dev, DRM_MINOR_RENDER);
+ drm_minor_unregister(dev, DRM_MINOR_CONTROL);
mutex_lock(&drm_global_mutex);
diff --git a/drivers/gpu/drm/drm_plane.c b/drivers/gpu/drm/drm_plane.c
index fedd4d60d9cd..5dc8c4350602 100644
--- a/drivers/gpu/drm/drm_plane.c
+++ b/drivers/gpu/drm/drm_plane.c
@@ -948,8 +948,6 @@ retry:
}
out:
- if (ret && crtc->funcs->page_flip_target)
- drm_crtc_vblank_put(crtc);
if (fb)
drm_framebuffer_put(fb);
if (crtc->primary->old_fb)
@@ -964,5 +962,8 @@ out:
drm_modeset_drop_locks(&ctx);
drm_modeset_acquire_fini(&ctx);
+ if (ret && crtc->funcs->page_flip_target)
+ drm_crtc_vblank_put(crtc);
+
return ret;
}
diff --git a/drivers/gpu/drm/etnaviv/etnaviv_gem.h b/drivers/gpu/drm/etnaviv/etnaviv_gem.h
index c4a091e87426..e437fba1209d 100644
--- a/drivers/gpu/drm/etnaviv/etnaviv_gem.h
+++ b/drivers/gpu/drm/etnaviv/etnaviv_gem.h
@@ -106,9 +106,10 @@ struct etnaviv_gem_submit {
struct etnaviv_gpu *gpu;
struct ww_acquire_ctx ticket;
struct dma_fence *fence;
+ u32 flags;
unsigned int nr_bos;
struct etnaviv_gem_submit_bo bos[0];
- u32 flags;
+ /* No new members here, the previous one is variable-length! */
};
int etnaviv_gem_wait_bo(struct etnaviv_gpu *gpu, struct drm_gem_object *obj,
diff --git a/drivers/gpu/drm/etnaviv/etnaviv_gem_submit.c b/drivers/gpu/drm/etnaviv/etnaviv_gem_submit.c
index de80ee1b71df..1013765274da 100644
--- a/drivers/gpu/drm/etnaviv/etnaviv_gem_submit.c
+++ b/drivers/gpu/drm/etnaviv/etnaviv_gem_submit.c
@@ -172,7 +172,7 @@ static int submit_fence_sync(const struct etnaviv_gem_submit *submit)
for (i = 0; i < submit->nr_bos; i++) {
struct etnaviv_gem_object *etnaviv_obj = submit->bos[i].obj;
bool write = submit->bos[i].flags & ETNA_SUBMIT_BO_WRITE;
- bool explicit = !(submit->flags & ETNA_SUBMIT_NO_IMPLICIT);
+ bool explicit = !!(submit->flags & ETNA_SUBMIT_NO_IMPLICIT);
ret = etnaviv_gpu_fence_sync_obj(etnaviv_obj, context, write,
explicit);
diff --git a/drivers/gpu/drm/exynos/exynos_drm_drv.c b/drivers/gpu/drm/exynos/exynos_drm_drv.c
index 09d3c4c3c858..50294a7bd29d 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_drv.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_drv.c
@@ -82,14 +82,9 @@ err_file_priv_free:
return ret;
}
-static void exynos_drm_preclose(struct drm_device *dev,
- struct drm_file *file)
-{
- exynos_drm_subdrv_close(dev, file);
-}
-
static void exynos_drm_postclose(struct drm_device *dev, struct drm_file *file)
{
+ exynos_drm_subdrv_close(dev, file);
kfree(file->driver_priv);
file->driver_priv = NULL;
}
@@ -145,7 +140,6 @@ static struct drm_driver exynos_drm_driver = {
.driver_features = DRIVER_MODESET | DRIVER_GEM | DRIVER_PRIME
| DRIVER_ATOMIC | DRIVER_RENDER,
.open = exynos_drm_open,
- .preclose = exynos_drm_preclose,
.lastclose = exynos_drm_lastclose,
.postclose = exynos_drm_postclose,
.gem_free_object_unlocked = exynos_drm_gem_free_object,
diff --git a/drivers/gpu/drm/exynos/exynos_drm_drv.h b/drivers/gpu/drm/exynos/exynos_drm_drv.h
index cb3176930596..39c740572034 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_drv.h
+++ b/drivers/gpu/drm/exynos/exynos_drm_drv.h
@@ -160,12 +160,9 @@ struct exynos_drm_clk {
* drm framework doesn't support multiple irq yet.
* we can refer to the crtc to current hardware interrupt occurred through
* this pipe value.
- * @enabled: if the crtc is enabled or not
- * @event: vblank event that is currently queued for flip
- * @wait_update: wait all pending planes updates to finish
- * @pending_update: number of pending plane updates in this crtc
* @ops: pointer to callbacks for exynos drm specific functionality
* @ctx: A pointer to the crtc's implementation specific context
+ * @pipe_clk: A pointer to the crtc's pipeline clock.
*/
struct exynos_drm_crtc {
struct drm_crtc base;
diff --git a/drivers/gpu/drm/exynos/exynos_drm_dsi.c b/drivers/gpu/drm/exynos/exynos_drm_dsi.c
index fc4fda738906..d404de86d5f9 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_dsi.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_dsi.c
@@ -1633,7 +1633,6 @@ static int exynos_dsi_parse_dt(struct exynos_dsi *dsi)
{
struct device *dev = dsi->dev;
struct device_node *node = dev->of_node;
- struct device_node *ep;
int ret;
ret = exynos_dsi_of_read_u32(node, "samsung,pll-clock-frequency",
@@ -1641,32 +1640,21 @@ static int exynos_dsi_parse_dt(struct exynos_dsi *dsi)
if (ret < 0)
return ret;
- ep = of_graph_get_endpoint_by_regs(node, DSI_PORT_OUT, 0);
- if (!ep) {
- dev_err(dev, "no output port with endpoint specified\n");
- return -EINVAL;
- }
-
- ret = exynos_dsi_of_read_u32(ep, "samsung,burst-clock-frequency",
+ ret = exynos_dsi_of_read_u32(node, "samsung,burst-clock-frequency",
&dsi->burst_clk_rate);
if (ret < 0)
- goto end;
+ return ret;
- ret = exynos_dsi_of_read_u32(ep, "samsung,esc-clock-frequency",
+ ret = exynos_dsi_of_read_u32(node, "samsung,esc-clock-frequency",
&dsi->esc_clk_rate);
if (ret < 0)
- goto end;
-
- of_node_put(ep);
+ return ret;
dsi->bridge_node = of_graph_get_remote_node(node, DSI_PORT_OUT, 0);
if (!dsi->bridge_node)
return -EINVAL;
-end:
- of_node_put(ep);
-
- return ret;
+ return 0;
}
static int exynos_dsi_bind(struct device *dev, struct device *master,
@@ -1817,6 +1805,10 @@ static int exynos_dsi_probe(struct platform_device *pdev)
static int exynos_dsi_remove(struct platform_device *pdev)
{
+ struct exynos_dsi *dsi = platform_get_drvdata(pdev);
+
+ of_node_put(dsi->bridge_node);
+
pm_runtime_disable(&pdev->dev);
component_del(&pdev->dev, &exynos_dsi_component_ops);
diff --git a/drivers/gpu/drm/gma500/psb_intel_lvds.c b/drivers/gpu/drm/gma500/psb_intel_lvds.c
index 0066fe7e622e..be3eefec5152 100644
--- a/drivers/gpu/drm/gma500/psb_intel_lvds.c
+++ b/drivers/gpu/drm/gma500/psb_intel_lvds.c
@@ -759,20 +759,23 @@ void psb_intel_lvds_init(struct drm_device *dev,
if (scan->type & DRM_MODE_TYPE_PREFERRED) {
mode_dev->panel_fixed_mode =
drm_mode_duplicate(dev, scan);
+ DRM_DEBUG_KMS("Using mode from DDC\n");
goto out; /* FIXME: check for quirks */
}
}
/* Failed to get EDID, what about VBT? do we need this? */
- if (mode_dev->vbt_mode)
+ if (dev_priv->lfp_lvds_vbt_mode) {
mode_dev->panel_fixed_mode =
- drm_mode_duplicate(dev, mode_dev->vbt_mode);
+ drm_mode_duplicate(dev, dev_priv->lfp_lvds_vbt_mode);
- if (!mode_dev->panel_fixed_mode)
- if (dev_priv->lfp_lvds_vbt_mode)
- mode_dev->panel_fixed_mode =
- drm_mode_duplicate(dev,
- dev_priv->lfp_lvds_vbt_mode);
+ if (mode_dev->panel_fixed_mode) {
+ mode_dev->panel_fixed_mode->type |=
+ DRM_MODE_TYPE_PREFERRED;
+ DRM_DEBUG_KMS("Using mode from VBT\n");
+ goto out;
+ }
+ }
/*
* If we didn't get EDID, try checking if the panel is already turned
@@ -789,6 +792,7 @@ void psb_intel_lvds_init(struct drm_device *dev,
if (mode_dev->panel_fixed_mode) {
mode_dev->panel_fixed_mode->type |=
DRM_MODE_TYPE_PREFERRED;
+ DRM_DEBUG_KMS("Using pre-programmed mode\n");
goto out; /* FIXME: check for quirks */
}
}
diff --git a/drivers/gpu/drm/hisilicon/kirin/dw_drm_dsi.c b/drivers/gpu/drm/hisilicon/kirin/dw_drm_dsi.c
index 5abc69c9630f..f77dcfaade6c 100644
--- a/drivers/gpu/drm/hisilicon/kirin/dw_drm_dsi.c
+++ b/drivers/gpu/drm/hisilicon/kirin/dw_drm_dsi.c
@@ -760,7 +760,7 @@ static int dsi_parse_dt(struct platform_device *pdev, struct dw_dsi *dsi)
* Get the endpoint node. In our case, dsi has one output port1
* to which the external HDMI bridge is connected.
*/
- ret = drm_of_find_panel_or_bridge(np, 0, 0, NULL, &dsi->bridge);
+ ret = drm_of_find_panel_or_bridge(np, 1, 0, NULL, &dsi->bridge);
if (ret)
return ret;
diff --git a/drivers/gpu/drm/i915/gvt/execlist.c b/drivers/gpu/drm/i915/gvt/execlist.c
index dca989eb2d42..24fe04d6307b 100644
--- a/drivers/gpu/drm/i915/gvt/execlist.c
+++ b/drivers/gpu/drm/i915/gvt/execlist.c
@@ -779,8 +779,26 @@ static void init_vgpu_execlist(struct intel_vgpu *vgpu, int ring_id)
vgpu_vreg(vgpu, ctx_status_ptr_reg) = ctx_status_ptr.dw;
}
+static void clean_workloads(struct intel_vgpu *vgpu, unsigned long engine_mask)
+{
+ struct drm_i915_private *dev_priv = vgpu->gvt->dev_priv;
+ struct intel_engine_cs *engine;
+ struct intel_vgpu_workload *pos, *n;
+ unsigned int tmp;
+
+ /* free the unsubmited workloads in the queues. */
+ for_each_engine_masked(engine, dev_priv, engine_mask, tmp) {
+ list_for_each_entry_safe(pos, n,
+ &vgpu->workload_q_head[engine->id], list) {
+ list_del_init(&pos->list);
+ free_workload(pos);
+ }
+ }
+}
+
void intel_vgpu_clean_execlist(struct intel_vgpu *vgpu)
{
+ clean_workloads(vgpu, ALL_ENGINES);
kmem_cache_destroy(vgpu->workloads);
}
@@ -811,17 +829,9 @@ void intel_vgpu_reset_execlist(struct intel_vgpu *vgpu,
{
struct drm_i915_private *dev_priv = vgpu->gvt->dev_priv;
struct intel_engine_cs *engine;
- struct intel_vgpu_workload *pos, *n;
unsigned int tmp;
- for_each_engine_masked(engine, dev_priv, engine_mask, tmp) {
- /* free the unsubmited workload in the queue */
- list_for_each_entry_safe(pos, n,
- &vgpu->workload_q_head[engine->id], list) {
- list_del_init(&pos->list);
- free_workload(pos);
- }
-
+ clean_workloads(vgpu, engine_mask);
+ for_each_engine_masked(engine, dev_priv, engine_mask, tmp)
init_vgpu_execlist(vgpu, engine->id);
- }
}
diff --git a/drivers/gpu/drm/i915/gvt/handlers.c b/drivers/gpu/drm/i915/gvt/handlers.c
index c995e540ff96..0ffd69654592 100644
--- a/drivers/gpu/drm/i915/gvt/handlers.c
+++ b/drivers/gpu/drm/i915/gvt/handlers.c
@@ -1366,18 +1366,28 @@ static int skl_misc_ctl_write(struct intel_vgpu *vgpu, unsigned int offset,
void *p_data, unsigned int bytes)
{
struct drm_i915_private *dev_priv = vgpu->gvt->dev_priv;
- i915_reg_t reg = {.reg = offset};
+ u32 v = *(u32 *)p_data;
+
+ if (!IS_SKYLAKE(dev_priv) && !IS_KABYLAKE(dev_priv))
+ return intel_vgpu_default_mmio_write(vgpu,
+ offset, p_data, bytes);
switch (offset) {
case 0x4ddc:
- vgpu_vreg(vgpu, offset) = 0x8000003c;
- /* WaCompressedResourceSamplerPbeMediaNewHashMode:skl */
- I915_WRITE(reg, vgpu_vreg(vgpu, offset));
+ /* bypass WaCompressedResourceSamplerPbeMediaNewHashMode */
+ vgpu_vreg(vgpu, offset) = v & ~(1 << 31);
break;
case 0x42080:
- vgpu_vreg(vgpu, offset) = 0x8000;
- /* WaCompressedResourceDisplayNewHashMode:skl */
- I915_WRITE(reg, vgpu_vreg(vgpu, offset));
+ /* bypass WaCompressedResourceDisplayNewHashMode */
+ vgpu_vreg(vgpu, offset) = v & ~(1 << 15);
+ break;
+ case 0xe194:
+ /* bypass WaCompressedResourceSamplerPbeMediaNewHashMode */
+ vgpu_vreg(vgpu, offset) = v & ~(1 << 8);
+ break;
+ case 0x7014:
+ /* bypass WaCompressedResourceSamplerPbeMediaNewHashMode */
+ vgpu_vreg(vgpu, offset) = v & ~(1 << 13);
break;
default:
return -EINVAL;
@@ -1634,7 +1644,8 @@ static int init_generic_mmio_info(struct intel_gvt *gvt)
MMIO_DFH(GAM_ECOCHK, D_ALL, F_CMD_ACCESS, NULL, NULL);
MMIO_DFH(GEN7_COMMON_SLICE_CHICKEN1, D_ALL, F_MODE_MASK | F_CMD_ACCESS,
NULL, NULL);
- MMIO_DFH(COMMON_SLICE_CHICKEN2, D_ALL, F_MODE_MASK | F_CMD_ACCESS, NULL, NULL);
+ MMIO_DFH(COMMON_SLICE_CHICKEN2, D_ALL, F_MODE_MASK | F_CMD_ACCESS, NULL,
+ skl_misc_ctl_write);
MMIO_DFH(0x9030, D_ALL, F_CMD_ACCESS, NULL, NULL);
MMIO_DFH(0x20a0, D_ALL, F_CMD_ACCESS, NULL, NULL);
MMIO_DFH(0x2420, D_ALL, F_CMD_ACCESS, NULL, NULL);
@@ -2568,7 +2579,8 @@ static int init_broadwell_mmio_info(struct intel_gvt *gvt)
MMIO_D(0x6e570, D_BDW_PLUS);
MMIO_D(0x65f10, D_BDW_PLUS);
- MMIO_DFH(0xe194, D_BDW_PLUS, F_MODE_MASK | F_CMD_ACCESS, NULL, NULL);
+ MMIO_DFH(0xe194, D_BDW_PLUS, F_MODE_MASK | F_CMD_ACCESS, NULL,
+ skl_misc_ctl_write);
MMIO_DFH(0xe188, D_BDW_PLUS, F_MODE_MASK | F_CMD_ACCESS, NULL, NULL);
MMIO_DFH(HALF_SLICE_CHICKEN2, D_BDW_PLUS, F_MODE_MASK | F_CMD_ACCESS, NULL, NULL);
MMIO_DFH(0x2580, D_BDW_PLUS, F_MODE_MASK | F_CMD_ACCESS, NULL, NULL);
diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c
index d689e511744e..4bd1467c17b1 100644
--- a/drivers/gpu/drm/i915/i915_debugfs.c
+++ b/drivers/gpu/drm/i915/i915_debugfs.c
@@ -292,6 +292,8 @@ static int per_file_stats(int id, void *ptr, void *data)
struct file_stats *stats = data;
struct i915_vma *vma;
+ lockdep_assert_held(&obj->base.dev->struct_mutex);
+
stats->count++;
stats->total += obj->base.size;
if (!obj->bind_count)
@@ -476,6 +478,8 @@ static int i915_gem_object_info(struct seq_file *m, void *data)
struct drm_i915_gem_request *request;
struct task_struct *task;
+ mutex_lock(&dev->struct_mutex);
+
memset(&stats, 0, sizeof(stats));
stats.file_priv = file->driver_priv;
spin_lock(&file->table_lock);
@@ -487,7 +491,6 @@ static int i915_gem_object_info(struct seq_file *m, void *data)
* still alive (e.g. get_pid(current) => fork() => exit()).
* Therefore, we need to protect this ->comm access using RCU.
*/
- mutex_lock(&dev->struct_mutex);
request = list_first_entry_or_null(&file_priv->mm.request_list,
struct drm_i915_gem_request,
client_link);
@@ -497,6 +500,7 @@ static int i915_gem_object_info(struct seq_file *m, void *data)
PIDTYPE_PID);
print_file_stats(m, task ? task->comm : "<unknown>", stats);
rcu_read_unlock();
+
mutex_unlock(&dev->struct_mutex);
}
mutex_unlock(&dev->filelist_mutex);
diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c
index 3036d4835b0f..48428672fc6e 100644
--- a/drivers/gpu/drm/i915/i915_drv.c
+++ b/drivers/gpu/drm/i915/i915_drv.c
@@ -1235,6 +1235,15 @@ int i915_driver_load(struct pci_dev *pdev, const struct pci_device_id *ent)
goto out_fini;
pci_set_drvdata(pdev, &dev_priv->drm);
+ /*
+ * Disable the system suspend direct complete optimization, which can
+ * leave the device suspended skipping the driver's suspend handlers
+ * if the device was already runtime suspended. This is needed due to
+ * the difference in our runtime and system suspend sequence and
+ * becaue the HDA driver may require us to enable the audio power
+ * domain during system suspend.
+ */
+ pdev->dev_flags |= PCI_DEV_FLAGS_NEEDS_RESUME;
ret = i915_driver_init_early(dev_priv, ent);
if (ret < 0)
@@ -1272,10 +1281,6 @@ int i915_driver_load(struct pci_dev *pdev, const struct pci_device_id *ent)
dev_priv->ipc_enabled = false;
- /* Everything is in place, we can now relax! */
- DRM_INFO("Initialized %s %d.%d.%d %s for %s on minor %d\n",
- driver.name, driver.major, driver.minor, driver.patchlevel,
- driver.date, pci_name(pdev), dev_priv->drm.primary->index);
if (IS_ENABLED(CONFIG_DRM_I915_DEBUG))
DRM_INFO("DRM_I915_DEBUG enabled\n");
if (IS_ENABLED(CONFIG_DRM_I915_DEBUG_GEM))
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index c9b0949f6c1a..2c453a4e97d5 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -562,7 +562,8 @@ struct intel_link_m_n {
void intel_link_compute_m_n(int bpp, int nlanes,
int pixel_clock, int link_clock,
- struct intel_link_m_n *m_n);
+ struct intel_link_m_n *m_n,
+ bool reduce_m_n);
/* Interface history:
*
@@ -2990,6 +2991,16 @@ static inline bool intel_scanout_needs_vtd_wa(struct drm_i915_private *dev_priv)
return false;
}
+static inline bool
+intel_ggtt_update_needs_vtd_wa(struct drm_i915_private *dev_priv)
+{
+#ifdef CONFIG_INTEL_IOMMU
+ if (IS_BROXTON(dev_priv) && intel_iommu_gfx_mapped)
+ return true;
+#endif
+ return false;
+}
+
int intel_sanitize_enable_ppgtt(struct drm_i915_private *dev_priv,
int enable_ppgtt);
diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c
index b6ac3df18b58..615f0a855222 100644
--- a/drivers/gpu/drm/i915/i915_gem.c
+++ b/drivers/gpu/drm/i915/i915_gem.c
@@ -2285,8 +2285,8 @@ i915_gem_object_get_pages_gtt(struct drm_i915_gem_object *obj)
struct page *page;
unsigned long last_pfn = 0; /* suppress gcc warning */
unsigned int max_segment;
+ gfp_t noreclaim;
int ret;
- gfp_t gfp;
/* Assert that the object is not currently in any GPU domain. As it
* wasn't in the GTT, there shouldn't be any way it could have been in
@@ -2315,22 +2315,31 @@ rebuild_st:
* Fail silently without starting the shrinker
*/
mapping = obj->base.filp->f_mapping;
- gfp = mapping_gfp_constraint(mapping, ~(__GFP_IO | __GFP_RECLAIM));
- gfp |= __GFP_NORETRY | __GFP_NOWARN;
+ noreclaim = mapping_gfp_constraint(mapping,
+ ~(__GFP_IO | __GFP_RECLAIM));
+ noreclaim |= __GFP_NORETRY | __GFP_NOWARN;
+
sg = st->sgl;
st->nents = 0;
for (i = 0; i < page_count; i++) {
- page = shmem_read_mapping_page_gfp(mapping, i, gfp);
- if (unlikely(IS_ERR(page))) {
- i915_gem_shrink(dev_priv,
- page_count,
- I915_SHRINK_BOUND |
- I915_SHRINK_UNBOUND |
- I915_SHRINK_PURGEABLE);
+ const unsigned int shrink[] = {
+ I915_SHRINK_BOUND | I915_SHRINK_UNBOUND | I915_SHRINK_PURGEABLE,
+ 0,
+ }, *s = shrink;
+ gfp_t gfp = noreclaim;
+
+ do {
page = shmem_read_mapping_page_gfp(mapping, i, gfp);
- }
- if (unlikely(IS_ERR(page))) {
- gfp_t reclaim;
+ if (likely(!IS_ERR(page)))
+ break;
+
+ if (!*s) {
+ ret = PTR_ERR(page);
+ goto err_sg;
+ }
+
+ i915_gem_shrink(dev_priv, 2 * page_count, *s++);
+ cond_resched();
/* We've tried hard to allocate the memory by reaping
* our own buffer, now let the real VM do its job and
@@ -2340,15 +2349,26 @@ rebuild_st:
* defer the oom here by reporting the ENOMEM back
* to userspace.
*/
- reclaim = mapping_gfp_mask(mapping);
- reclaim |= __GFP_NORETRY; /* reclaim, but no oom */
-
- page = shmem_read_mapping_page_gfp(mapping, i, reclaim);
- if (IS_ERR(page)) {
- ret = PTR_ERR(page);
- goto err_sg;
+ if (!*s) {
+ /* reclaim and warn, but no oom */
+ gfp = mapping_gfp_mask(mapping);
+
+ /* Our bo are always dirty and so we require
+ * kswapd to reclaim our pages (direct reclaim
+ * does not effectively begin pageout of our
+ * buffers on its own). However, direct reclaim
+ * only waits for kswapd when under allocation
+ * congestion. So as a result __GFP_RECLAIM is
+ * unreliable and fails to actually reclaim our
+ * dirty pages -- unless you try over and over
+ * again with !__GFP_NORETRY. However, we still
+ * want to fail this allocation rather than
+ * trigger the out-of-memory killer and for
+ * this we want the future __GFP_MAYFAIL.
+ */
}
- }
+ } while (1);
+
if (!i ||
sg->length >= max_segment ||
page_to_pfn(page) != last_pfn + 1) {
@@ -3298,6 +3318,10 @@ int i915_gem_wait_for_idle(struct drm_i915_private *i915, unsigned int flags)
{
int ret;
+ /* If the device is asleep, we have no requests outstanding */
+ if (!READ_ONCE(i915->gt.awake))
+ return 0;
+
if (flags & I915_WAIT_LOCKED) {
struct i915_gem_timeline *tl;
@@ -4218,6 +4242,7 @@ i915_gem_object_create(struct drm_i915_private *dev_priv, u64 size)
mapping = obj->base.filp->f_mapping;
mapping_set_gfp_mask(mapping, mask);
+ GEM_BUG_ON(!(mapping_gfp_mask(mapping) & __GFP_RECLAIM));
i915_gem_object_init(obj, &i915_gem_object_ops);
diff --git a/drivers/gpu/drm/i915/i915_gem_execbuffer.c b/drivers/gpu/drm/i915/i915_gem_execbuffer.c
index a3e59c8ef27b..9ad13eeed904 100644
--- a/drivers/gpu/drm/i915/i915_gem_execbuffer.c
+++ b/drivers/gpu/drm/i915/i915_gem_execbuffer.c
@@ -546,11 +546,12 @@ repeat:
}
static int
-i915_gem_execbuffer_relocate_entry(struct drm_i915_gem_object *obj,
+i915_gem_execbuffer_relocate_entry(struct i915_vma *vma,
struct eb_vmas *eb,
struct drm_i915_gem_relocation_entry *reloc,
struct reloc_cache *cache)
{
+ struct drm_i915_gem_object *obj = vma->obj;
struct drm_i915_private *dev_priv = to_i915(obj->base.dev);
struct drm_gem_object *target_obj;
struct drm_i915_gem_object *target_i915_obj;
@@ -628,6 +629,16 @@ i915_gem_execbuffer_relocate_entry(struct drm_i915_gem_object *obj,
return -EINVAL;
}
+ /*
+ * If we write into the object, we need to force the synchronisation
+ * barrier, either with an asynchronous clflush or if we executed the
+ * patching using the GPU (though that should be serialised by the
+ * timeline). To be completely sure, and since we are required to
+ * do relocations we are already stalling, disable the user's opt
+ * of our synchronisation.
+ */
+ vma->exec_entry->flags &= ~EXEC_OBJECT_ASYNC;
+
ret = relocate_entry(obj, reloc, cache, target_offset);
if (ret)
return ret;
@@ -678,7 +689,7 @@ i915_gem_execbuffer_relocate_vma(struct i915_vma *vma,
do {
u64 offset = r->presumed_offset;
- ret = i915_gem_execbuffer_relocate_entry(vma->obj, eb, r, &cache);
+ ret = i915_gem_execbuffer_relocate_entry(vma, eb, r, &cache);
if (ret)
goto out;
@@ -726,7 +737,7 @@ i915_gem_execbuffer_relocate_vma_slow(struct i915_vma *vma,
reloc_cache_init(&cache, eb->i915);
for (i = 0; i < entry->relocation_count; i++) {
- ret = i915_gem_execbuffer_relocate_entry(vma->obj, eb, &relocs[i], &cache);
+ ret = i915_gem_execbuffer_relocate_entry(vma, eb, &relocs[i], &cache);
if (ret)
break;
}
diff --git a/drivers/gpu/drm/i915/i915_gem_gtt.c b/drivers/gpu/drm/i915/i915_gem_gtt.c
index a0563e18d753..f1989b8792dd 100644
--- a/drivers/gpu/drm/i915/i915_gem_gtt.c
+++ b/drivers/gpu/drm/i915/i915_gem_gtt.c
@@ -2191,6 +2191,101 @@ static void gen8_ggtt_clear_range(struct i915_address_space *vm,
gen8_set_pte(&gtt_base[i], scratch_pte);
}
+static void bxt_vtd_ggtt_wa(struct i915_address_space *vm)
+{
+ struct drm_i915_private *dev_priv = vm->i915;
+
+ /*
+ * Make sure the internal GAM fifo has been cleared of all GTT
+ * writes before exiting stop_machine(). This guarantees that
+ * any aperture accesses waiting to start in another process
+ * cannot back up behind the GTT writes causing a hang.
+ * The register can be any arbitrary GAM register.
+ */
+ POSTING_READ(GFX_FLSH_CNTL_GEN6);
+}
+
+struct insert_page {
+ struct i915_address_space *vm;
+ dma_addr_t addr;
+ u64 offset;
+ enum i915_cache_level level;
+};
+
+static int bxt_vtd_ggtt_insert_page__cb(void *_arg)
+{
+ struct insert_page *arg = _arg;
+
+ gen8_ggtt_insert_page(arg->vm, arg->addr, arg->offset, arg->level, 0);
+ bxt_vtd_ggtt_wa(arg->vm);
+
+ return 0;
+}
+
+static void bxt_vtd_ggtt_insert_page__BKL(struct i915_address_space *vm,
+ dma_addr_t addr,
+ u64 offset,
+ enum i915_cache_level level,
+ u32 unused)
+{
+ struct insert_page arg = { vm, addr, offset, level };
+
+ stop_machine(bxt_vtd_ggtt_insert_page__cb, &arg, NULL);
+}
+
+struct insert_entries {
+ struct i915_address_space *vm;
+ struct sg_table *st;
+ u64 start;
+ enum i915_cache_level level;
+};
+
+static int bxt_vtd_ggtt_insert_entries__cb(void *_arg)
+{
+ struct insert_entries *arg = _arg;
+
+ gen8_ggtt_insert_entries(arg->vm, arg->st, arg->start, arg->level, 0);
+ bxt_vtd_ggtt_wa(arg->vm);
+
+ return 0;
+}
+
+static void bxt_vtd_ggtt_insert_entries__BKL(struct i915_address_space *vm,
+ struct sg_table *st,
+ u64 start,
+ enum i915_cache_level level,
+ u32 unused)
+{
+ struct insert_entries arg = { vm, st, start, level };
+
+ stop_machine(bxt_vtd_ggtt_insert_entries__cb, &arg, NULL);
+}
+
+struct clear_range {
+ struct i915_address_space *vm;
+ u64 start;
+ u64 length;
+};
+
+static int bxt_vtd_ggtt_clear_range__cb(void *_arg)
+{
+ struct clear_range *arg = _arg;
+
+ gen8_ggtt_clear_range(arg->vm, arg->start, arg->length);
+ bxt_vtd_ggtt_wa(arg->vm);
+
+ return 0;
+}
+
+static void bxt_vtd_ggtt_clear_range__BKL(struct i915_address_space *vm,
+ u64 start,
+ u64 length)
+{
+ struct clear_range arg = { vm, start, length };
+
+ stop_machine(bxt_vtd_ggtt_clear_range__cb, &arg, NULL);
+}
+
static void gen6_ggtt_clear_range(struct i915_address_space *vm,
u64 start, u64 length)
{
@@ -2313,7 +2408,7 @@ static int aliasing_gtt_bind_vma(struct i915_vma *vma,
appgtt->base.allocate_va_range) {
ret = appgtt->base.allocate_va_range(&appgtt->base,
vma->node.start,
- vma->node.size);
+ vma->size);
if (ret)
goto err_pages;
}
@@ -2785,6 +2880,14 @@ static int gen8_gmch_probe(struct i915_ggtt *ggtt)
ggtt->base.insert_entries = gen8_ggtt_insert_entries;
+ /* Serialize GTT updates with aperture access on BXT if VT-d is on. */
+ if (intel_ggtt_update_needs_vtd_wa(dev_priv)) {
+ ggtt->base.insert_entries = bxt_vtd_ggtt_insert_entries__BKL;
+ ggtt->base.insert_page = bxt_vtd_ggtt_insert_page__BKL;
+ if (ggtt->base.clear_range != nop_clear_range)
+ ggtt->base.clear_range = bxt_vtd_ggtt_clear_range__BKL;
+ }
+
ggtt->invalidate = gen6_ggtt_invalidate;
return ggtt_probe_common(ggtt, size);
@@ -2997,7 +3100,8 @@ void i915_ggtt_enable_guc(struct drm_i915_private *i915)
void i915_ggtt_disable_guc(struct drm_i915_private *i915)
{
- i915->ggtt.invalidate = gen6_ggtt_invalidate;
+ if (i915->ggtt.invalidate == guc_ggtt_invalidate)
+ i915->ggtt.invalidate = gen6_ggtt_invalidate;
}
void i915_gem_restore_gtt_mappings(struct drm_i915_private *dev_priv)
diff --git a/drivers/gpu/drm/i915/i915_gem_request.c b/drivers/gpu/drm/i915/i915_gem_request.c
index 5ddbc9499775..a74d0ac737cb 100644
--- a/drivers/gpu/drm/i915/i915_gem_request.c
+++ b/drivers/gpu/drm/i915/i915_gem_request.c
@@ -623,7 +623,7 @@ i915_gem_request_alloc(struct intel_engine_cs *engine,
* GPU processing the request, we never over-estimate the
* position of the head.
*/
- req->head = req->ring->tail;
+ req->head = req->ring->emit;
/* Check that we didn't interrupt ourselves with a new request */
GEM_BUG_ON(req->timeline->seqno != req->fence.seqno);
diff --git a/drivers/gpu/drm/i915/i915_gem_request.h b/drivers/gpu/drm/i915/i915_gem_request.h
index 129c58bb4805..a4a920c4c454 100644
--- a/drivers/gpu/drm/i915/i915_gem_request.h
+++ b/drivers/gpu/drm/i915/i915_gem_request.h
@@ -123,7 +123,7 @@ struct drm_i915_gem_request {
* It is used by the driver to then queue the request for execution.
*/
struct i915_sw_fence submit;
- wait_queue_t submitq;
+ wait_queue_entry_t submitq;
wait_queue_head_t execute;
/* A list of everyone we wait upon, and everyone who waits upon us.
diff --git a/drivers/gpu/drm/i915/i915_gem_shrinker.c b/drivers/gpu/drm/i915/i915_gem_shrinker.c
index 129ed303a6c4..57d9f7f4ef15 100644
--- a/drivers/gpu/drm/i915/i915_gem_shrinker.c
+++ b/drivers/gpu/drm/i915/i915_gem_shrinker.c
@@ -59,9 +59,6 @@ static void i915_gem_shrinker_unlock(struct drm_device *dev, bool unlock)
return;
mutex_unlock(&dev->struct_mutex);
-
- /* expedite the RCU grace period to free some request slabs */
- synchronize_rcu_expedited();
}
static bool any_vma_pinned(struct drm_i915_gem_object *obj)
@@ -274,8 +271,6 @@ unsigned long i915_gem_shrink_all(struct drm_i915_private *dev_priv)
I915_SHRINK_ACTIVE);
intel_runtime_pm_put(dev_priv);
- synchronize_rcu(); /* wait for our earlier RCU delayed slab frees */
-
return freed;
}
diff --git a/drivers/gpu/drm/i915/i915_gem_tiling.c b/drivers/gpu/drm/i915/i915_gem_tiling.c
index a0d6d4317a49..fb5231f98c0d 100644
--- a/drivers/gpu/drm/i915/i915_gem_tiling.c
+++ b/drivers/gpu/drm/i915/i915_gem_tiling.c
@@ -278,7 +278,7 @@ i915_gem_object_set_tiling(struct drm_i915_gem_object *obj,
obj->mm.quirked = false;
}
if (!i915_gem_object_is_tiled(obj)) {
- GEM_BUG_ON(!obj->mm.quirked);
+ GEM_BUG_ON(obj->mm.quirked);
__i915_gem_object_pin_pages(obj);
obj->mm.quirked = true;
}
diff --git a/drivers/gpu/drm/i915/i915_guc_submission.c b/drivers/gpu/drm/i915/i915_guc_submission.c
index 1642fff9cf13..ab5140ba108d 100644
--- a/drivers/gpu/drm/i915/i915_guc_submission.c
+++ b/drivers/gpu/drm/i915/i915_guc_submission.c
@@ -480,9 +480,7 @@ static void guc_wq_item_append(struct i915_guc_client *client,
GEM_BUG_ON(freespace < wqi_size);
/* The GuC firmware wants the tail index in QWords, not bytes */
- tail = rq->tail;
- assert_ring_tail_valid(rq->ring, rq->tail);
- tail >>= 3;
+ tail = intel_ring_set_tail(rq->ring, rq->tail) >> 3;
GEM_BUG_ON(tail > WQ_RING_TAIL_MAX);
/* For now workqueue item is 4 DWs; workqueue buffer is 2 pages. So we
diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c
index fd97fe00cd0d..190f6aa5d15e 100644
--- a/drivers/gpu/drm/i915/i915_irq.c
+++ b/drivers/gpu/drm/i915/i915_irq.c
@@ -2953,7 +2953,6 @@ static void vlv_display_irq_postinstall(struct drm_i915_private *dev_priv)
u32 pipestat_mask;
u32 enable_mask;
enum pipe pipe;
- u32 val;
pipestat_mask = PLANE_FLIP_DONE_INT_STATUS_VLV |
PIPE_CRC_DONE_INTERRUPT_STATUS;
@@ -2964,18 +2963,16 @@ static void vlv_display_irq_postinstall(struct drm_i915_private *dev_priv)
enable_mask = I915_DISPLAY_PORT_INTERRUPT |
I915_DISPLAY_PIPE_A_EVENT_INTERRUPT |
- I915_DISPLAY_PIPE_B_EVENT_INTERRUPT;
+ I915_DISPLAY_PIPE_B_EVENT_INTERRUPT |
+ I915_LPE_PIPE_A_INTERRUPT |
+ I915_LPE_PIPE_B_INTERRUPT;
+
if (IS_CHERRYVIEW(dev_priv))
- enable_mask |= I915_DISPLAY_PIPE_C_EVENT_INTERRUPT;
+ enable_mask |= I915_DISPLAY_PIPE_C_EVENT_INTERRUPT |
+ I915_LPE_PIPE_C_INTERRUPT;
WARN_ON(dev_priv->irq_mask != ~0);
- val = (I915_LPE_PIPE_A_INTERRUPT |
- I915_LPE_PIPE_B_INTERRUPT |
- I915_LPE_PIPE_C_INTERRUPT);
-
- enable_mask |= val;
-
dev_priv->irq_mask = ~enable_mask;
GEN5_IRQ_INIT(VLV_, dev_priv->irq_mask, enable_mask);
diff --git a/drivers/gpu/drm/i915/i915_pci.c b/drivers/gpu/drm/i915/i915_pci.c
index f87b0c4e564d..1a78363c7f4a 100644
--- a/drivers/gpu/drm/i915/i915_pci.c
+++ b/drivers/gpu/drm/i915/i915_pci.c
@@ -208,7 +208,7 @@ static const struct intel_device_info intel_ironlake_d_info = {
static const struct intel_device_info intel_ironlake_m_info = {
GEN5_FEATURES,
.platform = INTEL_IRONLAKE,
- .is_mobile = 1,
+ .is_mobile = 1, .has_fbc = 1,
};
#define GEN6_FEATURES \
@@ -390,7 +390,6 @@ static const struct intel_device_info intel_skylake_gt3_info = {
.has_hw_contexts = 1, \
.has_logical_ring_contexts = 1, \
.has_guc = 1, \
- .has_decoupled_mmio = 1, \
.has_aliasing_ppgtt = 1, \
.has_full_ppgtt = 1, \
.has_full_48bit_ppgtt = 1, \
diff --git a/drivers/gpu/drm/i915/i915_pvinfo.h b/drivers/gpu/drm/i915/i915_pvinfo.h
index c0cb2974caac..2cfe96d3e5d1 100644
--- a/drivers/gpu/drm/i915/i915_pvinfo.h
+++ b/drivers/gpu/drm/i915/i915_pvinfo.h
@@ -36,10 +36,6 @@
#define VGT_VERSION_MAJOR 1
#define VGT_VERSION_MINOR 0
-#define INTEL_VGT_IF_VERSION_ENCODE(major, minor) ((major) << 16 | (minor))
-#define INTEL_VGT_IF_VERSION \
- INTEL_VGT_IF_VERSION_ENCODE(VGT_VERSION_MAJOR, VGT_VERSION_MINOR)
-
/*
* notifications from guest to vgpu device model
*/
@@ -55,8 +51,8 @@ enum vgt_g2v_type {
struct vgt_if {
u64 magic; /* VGT_MAGIC */
- uint16_t version_major;
- uint16_t version_minor;
+ u16 version_major;
+ u16 version_minor;
u32 vgt_id; /* ID of vGT instance */
u32 rsv1[12]; /* pad to offset 0x40 */
/*
diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h
index 5a7c63e64381..65b837e96fe6 100644
--- a/drivers/gpu/drm/i915/i915_reg.h
+++ b/drivers/gpu/drm/i915/i915_reg.h
@@ -8280,7 +8280,7 @@ enum {
/* MIPI DSI registers */
-#define _MIPI_PORT(port, a, c) ((port) ? c : a) /* ports A and C only */
+#define _MIPI_PORT(port, a, c) (((port) == PORT_A) ? a : c) /* ports A and C only */
#define _MMIO_MIPI(port, a, c) _MMIO(_MIPI_PORT(port, a, c))
#define MIPIO_TXESC_CLK_DIV1 _MMIO(0x160004)
diff --git a/drivers/gpu/drm/i915/i915_sw_fence.c b/drivers/gpu/drm/i915/i915_sw_fence.c
index a277f8eb7beb..380de4360b8a 100644
--- a/drivers/gpu/drm/i915/i915_sw_fence.c
+++ b/drivers/gpu/drm/i915/i915_sw_fence.c
@@ -152,7 +152,7 @@ static void __i915_sw_fence_wake_up_all(struct i915_sw_fence *fence,
struct list_head *continuation)
{
wait_queue_head_t *x = &fence->wait;
- wait_queue_t *pos, *next;
+ wait_queue_entry_t *pos, *next;
unsigned long flags;
debug_fence_deactivate(fence);
@@ -160,31 +160,30 @@ static void __i915_sw_fence_wake_up_all(struct i915_sw_fence *fence,
/*
* To prevent unbounded recursion as we traverse the graph of
- * i915_sw_fences, we move the task_list from this, the next ready
- * fence, to the tail of the original fence's task_list
+ * i915_sw_fences, we move the entry list from this, the next ready
+ * fence, to the tail of the original fence's entry list
* (and so added to the list to be woken).
*/
spin_lock_irqsave_nested(&x->lock, flags, 1 + !!continuation);
if (continuation) {
- list_for_each_entry_safe(pos, next, &x->task_list, task_list) {
+ list_for_each_entry_safe(pos, next, &x->head, entry) {
if (pos->func == autoremove_wake_function)
pos->func(pos, TASK_NORMAL, 0, continuation);
else
- list_move_tail(&pos->task_list, continuation);
+ list_move_tail(&pos->entry, continuation);
}
} else {
LIST_HEAD(extra);
do {
- list_for_each_entry_safe(pos, next,
- &x->task_list, task_list)
+ list_for_each_entry_safe(pos, next, &x->head, entry)
pos->func(pos, TASK_NORMAL, 0, &extra);
if (list_empty(&extra))
break;
- list_splice_tail_init(&extra, &x->task_list);
+ list_splice_tail_init(&extra, &x->head);
} while (1);
}
spin_unlock_irqrestore(&x->lock, flags);
@@ -254,9 +253,9 @@ void i915_sw_fence_commit(struct i915_sw_fence *fence)
__i915_sw_fence_commit(fence);
}
-static int i915_sw_fence_wake(wait_queue_t *wq, unsigned mode, int flags, void *key)
+static int i915_sw_fence_wake(wait_queue_entry_t *wq, unsigned mode, int flags, void *key)
{
- list_del(&wq->task_list);
+ list_del(&wq->entry);
__i915_sw_fence_complete(wq->private, key);
i915_sw_fence_put(wq->private);
if (wq->flags & I915_SW_FENCE_FLAG_ALLOC)
@@ -267,7 +266,7 @@ static int i915_sw_fence_wake(wait_queue_t *wq, unsigned mode, int flags, void *
static bool __i915_sw_fence_check_if_after(struct i915_sw_fence *fence,
const struct i915_sw_fence * const signaler)
{
- wait_queue_t *wq;
+ wait_queue_entry_t *wq;
if (__test_and_set_bit(I915_SW_FENCE_CHECKED_BIT, &fence->flags))
return false;
@@ -275,7 +274,7 @@ static bool __i915_sw_fence_check_if_after(struct i915_sw_fence *fence,
if (fence == signaler)
return true;
- list_for_each_entry(wq, &fence->wait.task_list, task_list) {
+ list_for_each_entry(wq, &fence->wait.head, entry) {
if (wq->func != i915_sw_fence_wake)
continue;
@@ -288,12 +287,12 @@ static bool __i915_sw_fence_check_if_after(struct i915_sw_fence *fence,
static void __i915_sw_fence_clear_checked_bit(struct i915_sw_fence *fence)
{
- wait_queue_t *wq;
+ wait_queue_entry_t *wq;
if (!__test_and_clear_bit(I915_SW_FENCE_CHECKED_BIT, &fence->flags))
return;
- list_for_each_entry(wq, &fence->wait.task_list, task_list) {
+ list_for_each_entry(wq, &fence->wait.head, entry) {
if (wq->func != i915_sw_fence_wake)
continue;
@@ -320,7 +319,7 @@ static bool i915_sw_fence_check_if_after(struct i915_sw_fence *fence,
static int __i915_sw_fence_await_sw_fence(struct i915_sw_fence *fence,
struct i915_sw_fence *signaler,
- wait_queue_t *wq, gfp_t gfp)
+ wait_queue_entry_t *wq, gfp_t gfp)
{
unsigned long flags;
int pending;
@@ -350,7 +349,7 @@ static int __i915_sw_fence_await_sw_fence(struct i915_sw_fence *fence,
pending |= I915_SW_FENCE_FLAG_ALLOC;
}
- INIT_LIST_HEAD(&wq->task_list);
+ INIT_LIST_HEAD(&wq->entry);
wq->flags = pending;
wq->func = i915_sw_fence_wake;
wq->private = i915_sw_fence_get(fence);
@@ -359,7 +358,7 @@ static int __i915_sw_fence_await_sw_fence(struct i915_sw_fence *fence,
spin_lock_irqsave(&signaler->wait.lock, flags);
if (likely(!i915_sw_fence_done(signaler))) {
- __add_wait_queue_tail(&signaler->wait, wq);
+ __add_wait_queue_entry_tail(&signaler->wait, wq);
pending = 1;
} else {
i915_sw_fence_wake(wq, 0, 0, NULL);
@@ -372,7 +371,7 @@ static int __i915_sw_fence_await_sw_fence(struct i915_sw_fence *fence,
int i915_sw_fence_await_sw_fence(struct i915_sw_fence *fence,
struct i915_sw_fence *signaler,
- wait_queue_t *wq)
+ wait_queue_entry_t *wq)
{
return __i915_sw_fence_await_sw_fence(fence, signaler, wq, 0);
}
diff --git a/drivers/gpu/drm/i915/i915_sw_fence.h b/drivers/gpu/drm/i915/i915_sw_fence.h
index d31cefbbcc04..fd3c3bf6c8b7 100644
--- a/drivers/gpu/drm/i915/i915_sw_fence.h
+++ b/drivers/gpu/drm/i915/i915_sw_fence.h
@@ -66,7 +66,7 @@ void i915_sw_fence_commit(struct i915_sw_fence *fence);
int i915_sw_fence_await_sw_fence(struct i915_sw_fence *fence,
struct i915_sw_fence *after,
- wait_queue_t *wq);
+ wait_queue_entry_t *wq);
int i915_sw_fence_await_sw_fence_gfp(struct i915_sw_fence *fence,
struct i915_sw_fence *after,
gfp_t gfp);
diff --git a/drivers/gpu/drm/i915/i915_vgpu.c b/drivers/gpu/drm/i915/i915_vgpu.c
index 4ab8a973b61f..2e739018fb4c 100644
--- a/drivers/gpu/drm/i915/i915_vgpu.c
+++ b/drivers/gpu/drm/i915/i915_vgpu.c
@@ -60,8 +60,8 @@
*/
void i915_check_vgpu(struct drm_i915_private *dev_priv)
{
- uint64_t magic;
- uint32_t version;
+ u64 magic;
+ u16 version_major;
BUILD_BUG_ON(sizeof(struct vgt_if) != VGT_PVINFO_SIZE);
@@ -69,10 +69,8 @@ void i915_check_vgpu(struct drm_i915_private *dev_priv)
if (magic != VGT_MAGIC)
return;
- version = INTEL_VGT_IF_VERSION_ENCODE(
- __raw_i915_read16(dev_priv, vgtif_reg(version_major)),
- __raw_i915_read16(dev_priv, vgtif_reg(version_minor)));
- if (version != INTEL_VGT_IF_VERSION) {
+ version_major = __raw_i915_read16(dev_priv, vgtif_reg(version_major));
+ if (version_major < VGT_VERSION_MAJOR) {
DRM_INFO("VGT interface version mismatch!\n");
return;
}
diff --git a/drivers/gpu/drm/i915/i915_vma.c b/drivers/gpu/drm/i915/i915_vma.c
index 1aba47024656..f066e2d785f5 100644
--- a/drivers/gpu/drm/i915/i915_vma.c
+++ b/drivers/gpu/drm/i915/i915_vma.c
@@ -650,6 +650,11 @@ int i915_vma_unbind(struct i915_vma *vma)
break;
}
+ if (!ret) {
+ ret = i915_gem_active_retire(&vma->last_fence,
+ &vma->vm->i915->drm.struct_mutex);
+ }
+
__i915_vma_unpin(vma);
if (ret)
return ret;
diff --git a/drivers/gpu/drm/i915/intel_acpi.c b/drivers/gpu/drm/i915/intel_acpi.c
index eb638a1e69d2..42fb436f6cdc 100644
--- a/drivers/gpu/drm/i915/intel_acpi.c
+++ b/drivers/gpu/drm/i915/intel_acpi.c
@@ -15,13 +15,9 @@ static struct intel_dsm_priv {
acpi_handle dhandle;
} intel_dsm_priv;
-static const u8 intel_dsm_guid[] = {
- 0xd3, 0x73, 0xd8, 0x7e,
- 0xd0, 0xc2,
- 0x4f, 0x4e,
- 0xa8, 0x54,
- 0x0f, 0x13, 0x17, 0xb0, 0x1c, 0x2c
-};
+static const guid_t intel_dsm_guid =
+ GUID_INIT(0x7ed873d3, 0xc2d0, 0x4e4f,
+ 0xa8, 0x54, 0x0f, 0x13, 0x17, 0xb0, 0x1c, 0x2c);
static char *intel_dsm_port_name(u8 id)
{
@@ -80,7 +76,7 @@ static void intel_dsm_platform_mux_info(void)
int i;
union acpi_object *pkg, *connector_count;
- pkg = acpi_evaluate_dsm_typed(intel_dsm_priv.dhandle, intel_dsm_guid,
+ pkg = acpi_evaluate_dsm_typed(intel_dsm_priv.dhandle, &intel_dsm_guid,
INTEL_DSM_REVISION_ID, INTEL_DSM_FN_PLATFORM_MUX_INFO,
NULL, ACPI_TYPE_PACKAGE);
if (!pkg) {
@@ -118,7 +114,7 @@ static bool intel_dsm_pci_probe(struct pci_dev *pdev)
if (!dhandle)
return false;
- if (!acpi_check_dsm(dhandle, intel_dsm_guid, INTEL_DSM_REVISION_ID,
+ if (!acpi_check_dsm(dhandle, &intel_dsm_guid, INTEL_DSM_REVISION_ID,
1 << INTEL_DSM_FN_PLATFORM_MUX_INFO)) {
DRM_DEBUG_KMS("no _DSM method for intel device\n");
return false;
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index 3617927af269..9106ea32b048 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -120,7 +120,8 @@ static void intel_crtc_init_scalers(struct intel_crtc *crtc,
static void skylake_pfit_enable(struct intel_crtc *crtc);
static void ironlake_pfit_disable(struct intel_crtc *crtc, bool force);
static void ironlake_pfit_enable(struct intel_crtc *crtc);
-static void intel_modeset_setup_hw_state(struct drm_device *dev);
+static void intel_modeset_setup_hw_state(struct drm_device *dev,
+ struct drm_modeset_acquire_ctx *ctx);
static void intel_pre_disable_primary_noatomic(struct drm_crtc *crtc);
struct intel_limit {
@@ -3449,7 +3450,7 @@ __intel_display_resume(struct drm_device *dev,
struct drm_crtc *crtc;
int i, ret;
- intel_modeset_setup_hw_state(dev);
+ intel_modeset_setup_hw_state(dev, ctx);
i915_redisable_vga(to_i915(dev));
if (!state)
@@ -4598,7 +4599,7 @@ static void cpt_verify_modeset(struct drm_device *dev, int pipe)
static int
skl_update_scaler(struct intel_crtc_state *crtc_state, bool force_detach,
- unsigned scaler_user, int *scaler_id, unsigned int rotation,
+ unsigned int scaler_user, int *scaler_id,
int src_w, int src_h, int dst_w, int dst_h)
{
struct intel_crtc_scaler_state *scaler_state =
@@ -4607,9 +4608,12 @@ skl_update_scaler(struct intel_crtc_state *crtc_state, bool force_detach,
to_intel_crtc(crtc_state->base.crtc);
int need_scaling;
- need_scaling = drm_rotation_90_or_270(rotation) ?
- (src_h != dst_w || src_w != dst_h):
- (src_w != dst_w || src_h != dst_h);
+ /*
+ * Src coordinates are already rotated by 270 degrees for
+ * the 90/270 degree plane rotation cases (to match the
+ * GTT mapping), hence no need to account for rotation here.
+ */
+ need_scaling = src_w != dst_w || src_h != dst_h;
/*
* if plane is being disabled or scaler is no more required or force detach
@@ -4671,7 +4675,7 @@ int skl_update_scaler_crtc(struct intel_crtc_state *state)
const struct drm_display_mode *adjusted_mode = &state->base.adjusted_mode;
return skl_update_scaler(state, !state->base.active, SKL_CRTC_INDEX,
- &state->scaler_state.scaler_id, DRM_ROTATE_0,
+ &state->scaler_state.scaler_id,
state->pipe_src_w, state->pipe_src_h,
adjusted_mode->crtc_hdisplay, adjusted_mode->crtc_vdisplay);
}
@@ -4700,7 +4704,6 @@ static int skl_update_scaler_plane(struct intel_crtc_state *crtc_state,
ret = skl_update_scaler(crtc_state, force_detach,
drm_plane_index(&intel_plane->base),
&plane_state->scaler_id,
- plane_state->base.rotation,
drm_rect_width(&plane_state->base.src) >> 16,
drm_rect_height(&plane_state->base.src) >> 16,
drm_rect_width(&plane_state->base.dst),
@@ -5823,7 +5826,8 @@ static void i9xx_crtc_disable(struct intel_crtc_state *old_crtc_state,
intel_update_watermarks(intel_crtc);
}
-static void intel_crtc_disable_noatomic(struct drm_crtc *crtc)
+static void intel_crtc_disable_noatomic(struct drm_crtc *crtc,
+ struct drm_modeset_acquire_ctx *ctx)
{
struct intel_encoder *encoder;
struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
@@ -5853,7 +5857,7 @@ static void intel_crtc_disable_noatomic(struct drm_crtc *crtc)
return;
}
- state->acquire_ctx = crtc->dev->mode_config.acquire_ctx;
+ state->acquire_ctx = ctx;
/* Everything's already locked, -EDEADLK can't happen. */
crtc_state = intel_atomic_get_crtc_state(state, intel_crtc);
@@ -6101,7 +6105,7 @@ retry:
pipe_config->fdi_lanes = lane;
intel_link_compute_m_n(pipe_config->pipe_bpp, lane, fdi_dotclock,
- link_bw, &pipe_config->fdi_m_n);
+ link_bw, &pipe_config->fdi_m_n, false);
ret = ironlake_check_fdi_lanes(dev, intel_crtc->pipe, pipe_config);
if (ret == -EINVAL && pipe_config->pipe_bpp > 6*3) {
@@ -6277,7 +6281,8 @@ intel_reduce_m_n_ratio(uint32_t *num, uint32_t *den)
}
static void compute_m_n(unsigned int m, unsigned int n,
- uint32_t *ret_m, uint32_t *ret_n)
+ uint32_t *ret_m, uint32_t *ret_n,
+ bool reduce_m_n)
{
/*
* Reduce M/N as much as possible without loss in precision. Several DP
@@ -6285,9 +6290,11 @@ static void compute_m_n(unsigned int m, unsigned int n,
* values. The passed in values are more likely to have the least
* significant bits zero than M after rounding below, so do this first.
*/
- while ((m & 1) == 0 && (n & 1) == 0) {
- m >>= 1;
- n >>= 1;
+ if (reduce_m_n) {
+ while ((m & 1) == 0 && (n & 1) == 0) {
+ m >>= 1;
+ n >>= 1;
+ }
}
*ret_n = min_t(unsigned int, roundup_pow_of_two(n), DATA_LINK_N_MAX);
@@ -6298,16 +6305,19 @@ static void compute_m_n(unsigned int m, unsigned int n,
void
intel_link_compute_m_n(int bits_per_pixel, int nlanes,
int pixel_clock, int link_clock,
- struct intel_link_m_n *m_n)
+ struct intel_link_m_n *m_n,
+ bool reduce_m_n)
{
m_n->tu = 64;
compute_m_n(bits_per_pixel * pixel_clock,
link_clock * nlanes * 8,
- &m_n->gmch_m, &m_n->gmch_n);
+ &m_n->gmch_m, &m_n->gmch_n,
+ reduce_m_n);
compute_m_n(pixel_clock, link_clock,
- &m_n->link_m, &m_n->link_n);
+ &m_n->link_m, &m_n->link_n,
+ reduce_m_n);
}
static inline bool intel_panel_use_ssc(struct drm_i915_private *dev_priv)
@@ -12197,6 +12207,15 @@ static void update_scanline_offset(struct intel_crtc *crtc)
* type. For DP ports it behaves like most other platforms, but on HDMI
* there's an extra 1 line difference. So we need to add two instead of
* one to the value.
+ *
+ * On VLV/CHV DSI the scanline counter would appear to increment
+ * approx. 1/3 of a scanline before start of vblank. Unfortunately
+ * that means we can't tell whether we're in vblank or not while
+ * we're on that particular line. We must still set scanline_offset
+ * to 1 so that the vblank timestamps come out correct when we query
+ * the scanline counter from within the vblank interrupt handler.
+ * However if queried just before the start of vblank we'll get an
+ * answer that's slightly in the future.
*/
if (IS_GEN2(dev_priv)) {
const struct drm_display_mode *adjusted_mode = &crtc->config->base.adjusted_mode;
@@ -15013,7 +15032,7 @@ int intel_modeset_init(struct drm_device *dev)
intel_setup_outputs(dev_priv);
drm_modeset_lock_all(dev);
- intel_modeset_setup_hw_state(dev);
+ intel_modeset_setup_hw_state(dev, dev->mode_config.acquire_ctx);
drm_modeset_unlock_all(dev);
for_each_intel_crtc(dev, crtc) {
@@ -15050,13 +15069,13 @@ int intel_modeset_init(struct drm_device *dev)
return 0;
}
-static void intel_enable_pipe_a(struct drm_device *dev)
+static void intel_enable_pipe_a(struct drm_device *dev,
+ struct drm_modeset_acquire_ctx *ctx)
{
struct intel_connector *connector;
struct drm_connector_list_iter conn_iter;
struct drm_connector *crt = NULL;
struct intel_load_detect_pipe load_detect_temp;
- struct drm_modeset_acquire_ctx *ctx = dev->mode_config.acquire_ctx;
int ret;
/* We can't just switch on the pipe A, we need to set things up with a
@@ -15128,7 +15147,8 @@ static bool has_pch_trancoder(struct drm_i915_private *dev_priv,
(HAS_PCH_LPT_H(dev_priv) && pch_transcoder == TRANSCODER_A);
}
-static void intel_sanitize_crtc(struct intel_crtc *crtc)
+static void intel_sanitize_crtc(struct intel_crtc *crtc,
+ struct drm_modeset_acquire_ctx *ctx)
{
struct drm_device *dev = crtc->base.dev;
struct drm_i915_private *dev_priv = to_i915(dev);
@@ -15174,7 +15194,7 @@ static void intel_sanitize_crtc(struct intel_crtc *crtc)
plane = crtc->plane;
crtc->base.primary->state->visible = true;
crtc->plane = !plane;
- intel_crtc_disable_noatomic(&crtc->base);
+ intel_crtc_disable_noatomic(&crtc->base, ctx);
crtc->plane = plane;
}
@@ -15184,13 +15204,13 @@ static void intel_sanitize_crtc(struct intel_crtc *crtc)
* resume. Force-enable the pipe to fix this, the update_dpms
* call below we restore the pipe to the right state, but leave
* the required bits on. */
- intel_enable_pipe_a(dev);
+ intel_enable_pipe_a(dev, ctx);
}
/* Adjust the state of the output pipe according to whether we
* have active connectors/encoders. */
if (crtc->active && !intel_crtc_has_encoders(crtc))
- intel_crtc_disable_noatomic(&crtc->base);
+ intel_crtc_disable_noatomic(&crtc->base, ctx);
if (crtc->active || HAS_GMCH_DISPLAY(dev_priv)) {
/*
@@ -15488,7 +15508,8 @@ get_encoder_power_domains(struct drm_i915_private *dev_priv)
* and sanitizes it to the current state
*/
static void
-intel_modeset_setup_hw_state(struct drm_device *dev)
+intel_modeset_setup_hw_state(struct drm_device *dev,
+ struct drm_modeset_acquire_ctx *ctx)
{
struct drm_i915_private *dev_priv = to_i915(dev);
enum pipe pipe;
@@ -15508,7 +15529,7 @@ intel_modeset_setup_hw_state(struct drm_device *dev)
for_each_pipe(dev_priv, pipe) {
crtc = intel_get_crtc_for_pipe(dev_priv, pipe);
- intel_sanitize_crtc(crtc);
+ intel_sanitize_crtc(crtc, ctx);
intel_dump_pipe_config(crtc, crtc->config,
"[setup_hw_state]");
}
diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
index ee77b519835c..fc691b8b317c 100644
--- a/drivers/gpu/drm/i915/intel_dp.c
+++ b/drivers/gpu/drm/i915/intel_dp.c
@@ -1507,37 +1507,6 @@ static void intel_dp_print_rates(struct intel_dp *intel_dp)
DRM_DEBUG_KMS("common rates: %s\n", str);
}
-bool
-__intel_dp_read_desc(struct intel_dp *intel_dp, struct intel_dp_desc *desc)
-{
- u32 base = drm_dp_is_branch(intel_dp->dpcd) ? DP_BRANCH_OUI :
- DP_SINK_OUI;
-
- return drm_dp_dpcd_read(&intel_dp->aux, base, desc, sizeof(*desc)) ==
- sizeof(*desc);
-}
-
-bool intel_dp_read_desc(struct intel_dp *intel_dp)
-{
- struct intel_dp_desc *desc = &intel_dp->desc;
- bool oui_sup = intel_dp->dpcd[DP_DOWN_STREAM_PORT_COUNT] &
- DP_OUI_SUPPORT;
- int dev_id_len;
-
- if (!__intel_dp_read_desc(intel_dp, desc))
- return false;
-
- dev_id_len = strnlen(desc->device_id, sizeof(desc->device_id));
- DRM_DEBUG_KMS("DP %s: OUI %*phD%s dev-ID %*pE HW-rev %d.%d SW-rev %d.%d\n",
- drm_dp_is_branch(intel_dp->dpcd) ? "branch" : "sink",
- (int)sizeof(desc->oui), desc->oui, oui_sup ? "" : "(NS)",
- dev_id_len, desc->device_id,
- desc->hw_rev >> 4, desc->hw_rev & 0xf,
- desc->sw_major_rev, desc->sw_minor_rev);
-
- return true;
-}
-
static int rate_to_index(int find, const int *rates)
{
int i = 0;
@@ -1624,6 +1593,8 @@ intel_dp_compute_config(struct intel_encoder *encoder,
int common_rates[DP_MAX_SUPPORTED_RATES] = {};
int common_len;
uint8_t link_bw, rate_select;
+ bool reduce_m_n = drm_dp_has_quirk(&intel_dp->desc,
+ DP_DPCD_QUIRK_LIMITED_M_N);
common_len = intel_dp_common_rates(intel_dp, common_rates);
@@ -1753,7 +1724,8 @@ found:
intel_link_compute_m_n(bpp, lane_count,
adjusted_mode->crtc_clock,
pipe_config->port_clock,
- &pipe_config->dp_m_n);
+ &pipe_config->dp_m_n,
+ reduce_m_n);
if (intel_connector->panel.downclock_mode != NULL &&
dev_priv->drrs.type == SEAMLESS_DRRS_SUPPORT) {
@@ -1761,7 +1733,8 @@ found:
intel_link_compute_m_n(bpp, lane_count,
intel_connector->panel.downclock_mode->clock,
pipe_config->port_clock,
- &pipe_config->dp_m2_n2);
+ &pipe_config->dp_m2_n2,
+ reduce_m_n);
}
/*
@@ -3622,7 +3595,8 @@ intel_edp_init_dpcd(struct intel_dp *intel_dp)
if (!intel_dp_read_dpcd(intel_dp))
return false;
- intel_dp_read_desc(intel_dp);
+ drm_dp_read_desc(&intel_dp->aux, &intel_dp->desc,
+ drm_dp_is_branch(intel_dp->dpcd));
if (intel_dp->dpcd[DP_DPCD_REV] >= 0x11)
dev_priv->no_aux_handshake = intel_dp->dpcd[DP_MAX_DOWNSPREAD] &
@@ -4624,7 +4598,8 @@ intel_dp_long_pulse(struct intel_connector *intel_connector)
intel_dp_print_rates(intel_dp);
- intel_dp_read_desc(intel_dp);
+ drm_dp_read_desc(&intel_dp->aux, &intel_dp->desc,
+ drm_dp_is_branch(intel_dp->dpcd));
intel_dp_configure_mst(intel_dp);
diff --git a/drivers/gpu/drm/i915/intel_dp_aux_backlight.c b/drivers/gpu/drm/i915/intel_dp_aux_backlight.c
index 6532e226db29..40ba3134545e 100644
--- a/drivers/gpu/drm/i915/intel_dp_aux_backlight.c
+++ b/drivers/gpu/drm/i915/intel_dp_aux_backlight.c
@@ -119,8 +119,6 @@ static int intel_dp_aux_setup_backlight(struct intel_connector *connector,
struct intel_dp *intel_dp = enc_to_intel_dp(&connector->encoder->base);
struct intel_panel *panel = &connector->panel;
- intel_dp_aux_enable_backlight(connector);
-
if (intel_dp->edp_dpcd[2] & DP_EDP_BACKLIGHT_BRIGHTNESS_BYTE_COUNT)
panel->backlight.max = 0xFFFF;
else
diff --git a/drivers/gpu/drm/i915/intel_dp_mst.c b/drivers/gpu/drm/i915/intel_dp_mst.c
index c1f62eb07c07..989e25577ac0 100644
--- a/drivers/gpu/drm/i915/intel_dp_mst.c
+++ b/drivers/gpu/drm/i915/intel_dp_mst.c
@@ -44,6 +44,8 @@ static bool intel_dp_mst_compute_config(struct intel_encoder *encoder,
int lane_count, slots;
const struct drm_display_mode *adjusted_mode = &pipe_config->base.adjusted_mode;
int mst_pbn;
+ bool reduce_m_n = drm_dp_has_quirk(&intel_dp->desc,
+ DP_DPCD_QUIRK_LIMITED_M_N);
pipe_config->has_pch_encoder = false;
bpp = 24;
@@ -75,7 +77,8 @@ static bool intel_dp_mst_compute_config(struct intel_encoder *encoder,
intel_link_compute_m_n(bpp, lane_count,
adjusted_mode->crtc_clock,
pipe_config->port_clock,
- &pipe_config->dp_m_n);
+ &pipe_config->dp_m_n,
+ reduce_m_n);
pipe_config->dp_m_n.tu = slots;
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index aaee3949a422..f630c7af5020 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -906,14 +906,6 @@ enum link_m_n_set {
M2_N2
};
-struct intel_dp_desc {
- u8 oui[3];
- u8 device_id[6];
- u8 hw_rev;
- u8 sw_major_rev;
- u8 sw_minor_rev;
-} __packed;
-
struct intel_dp_compliance_data {
unsigned long edid;
uint8_t video_pattern;
@@ -957,7 +949,7 @@ struct intel_dp {
/* Max link BW for the sink as per DPCD registers */
int max_sink_link_bw;
/* sink or branch descriptor */
- struct intel_dp_desc desc;
+ struct drm_dp_desc desc;
struct drm_dp_aux aux;
enum intel_display_power_domain aux_power_domain;
uint8_t train_set[4];
@@ -1532,9 +1524,6 @@ static inline unsigned int intel_dp_unused_lane_mask(int lane_count)
}
bool intel_dp_read_dpcd(struct intel_dp *intel_dp);
-bool __intel_dp_read_desc(struct intel_dp *intel_dp,
- struct intel_dp_desc *desc);
-bool intel_dp_read_desc(struct intel_dp *intel_dp);
int intel_dp_link_required(int pixel_clock, int bpp);
int intel_dp_max_data_rate(int max_link_clock, int max_lanes);
bool intel_digital_port_connected(struct drm_i915_private *dev_priv,
diff --git a/drivers/gpu/drm/i915/intel_engine_cs.c b/drivers/gpu/drm/i915/intel_engine_cs.c
index 854e8e0c836b..f94eacff196c 100644
--- a/drivers/gpu/drm/i915/intel_engine_cs.c
+++ b/drivers/gpu/drm/i915/intel_engine_cs.c
@@ -1075,6 +1075,22 @@ int intel_ring_workarounds_emit(struct drm_i915_gem_request *req)
return 0;
}
+static bool ring_is_idle(struct intel_engine_cs *engine)
+{
+ struct drm_i915_private *dev_priv = engine->i915;
+ bool idle = true;
+
+ intel_runtime_pm_get(dev_priv);
+
+ /* No bit for gen2, so assume the CS parser is idle */
+ if (INTEL_GEN(dev_priv) > 2 && !(I915_READ_MODE(engine) & MODE_IDLE))
+ idle = false;
+
+ intel_runtime_pm_put(dev_priv);
+
+ return idle;
+}
+
/**
* intel_engine_is_idle() - Report if the engine has finished process all work
* @engine: the intel_engine_cs
@@ -1084,8 +1100,6 @@ int intel_ring_workarounds_emit(struct drm_i915_gem_request *req)
*/
bool intel_engine_is_idle(struct intel_engine_cs *engine)
{
- struct drm_i915_private *dev_priv = engine->i915;
-
/* Any inflight/incomplete requests? */
if (!i915_seqno_passed(intel_engine_get_seqno(engine),
intel_engine_last_submit(engine)))
@@ -1100,7 +1114,7 @@ bool intel_engine_is_idle(struct intel_engine_cs *engine)
return false;
/* Ring stopped? */
- if (INTEL_GEN(dev_priv) > 2 && !(I915_READ_MODE(engine) & MODE_IDLE))
+ if (!ring_is_idle(engine))
return false;
return true;
diff --git a/drivers/gpu/drm/i915/intel_fbc.c b/drivers/gpu/drm/i915/intel_fbc.c
index ded2add18b26..d93c58410bff 100644
--- a/drivers/gpu/drm/i915/intel_fbc.c
+++ b/drivers/gpu/drm/i915/intel_fbc.c
@@ -82,20 +82,10 @@ static unsigned int get_crtc_fence_y_offset(struct intel_crtc *crtc)
static void intel_fbc_get_plane_source_size(struct intel_fbc_state_cache *cache,
int *width, int *height)
{
- int w, h;
-
- if (drm_rotation_90_or_270(cache->plane.rotation)) {
- w = cache->plane.src_h;
- h = cache->plane.src_w;
- } else {
- w = cache->plane.src_w;
- h = cache->plane.src_h;
- }
-
if (width)
- *width = w;
+ *width = cache->plane.src_w;
if (height)
- *height = h;
+ *height = cache->plane.src_h;
}
static int intel_fbc_calculate_cfb_size(struct drm_i915_private *dev_priv,
@@ -746,6 +736,11 @@ static void intel_fbc_update_state_cache(struct intel_crtc *crtc,
cache->crtc.hsw_bdw_pixel_rate = crtc_state->pixel_rate;
cache->plane.rotation = plane_state->base.rotation;
+ /*
+ * Src coordinates are already rotated by 270 degrees for
+ * the 90/270 degree plane rotation cases (to match the
+ * GTT mapping), hence no need to account for rotation here.
+ */
cache->plane.src_w = drm_rect_width(&plane_state->base.src) >> 16;
cache->plane.src_h = drm_rect_height(&plane_state->base.src) >> 16;
cache->plane.visible = plane_state->base.visible;
diff --git a/drivers/gpu/drm/i915/intel_lpe_audio.c b/drivers/gpu/drm/i915/intel_lpe_audio.c
index 668f00480d97..292fedf30b00 100644
--- a/drivers/gpu/drm/i915/intel_lpe_audio.c
+++ b/drivers/gpu/drm/i915/intel_lpe_audio.c
@@ -149,44 +149,10 @@ static void lpe_audio_platdev_destroy(struct drm_i915_private *dev_priv)
static void lpe_audio_irq_unmask(struct irq_data *d)
{
- struct drm_i915_private *dev_priv = d->chip_data;
- unsigned long irqflags;
- u32 val = (I915_LPE_PIPE_A_INTERRUPT |
- I915_LPE_PIPE_B_INTERRUPT);
-
- if (IS_CHERRYVIEW(dev_priv))
- val |= I915_LPE_PIPE_C_INTERRUPT;
-
- spin_lock_irqsave(&dev_priv->irq_lock, irqflags);
-
- dev_priv->irq_mask &= ~val;
- I915_WRITE(VLV_IIR, val);
- I915_WRITE(VLV_IIR, val);
- I915_WRITE(VLV_IMR, dev_priv->irq_mask);
- POSTING_READ(VLV_IMR);
-
- spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags);
}
static void lpe_audio_irq_mask(struct irq_data *d)
{
- struct drm_i915_private *dev_priv = d->chip_data;
- unsigned long irqflags;
- u32 val = (I915_LPE_PIPE_A_INTERRUPT |
- I915_LPE_PIPE_B_INTERRUPT);
-
- if (IS_CHERRYVIEW(dev_priv))
- val |= I915_LPE_PIPE_C_INTERRUPT;
-
- spin_lock_irqsave(&dev_priv->irq_lock, irqflags);
-
- dev_priv->irq_mask |= val;
- I915_WRITE(VLV_IMR, dev_priv->irq_mask);
- I915_WRITE(VLV_IIR, val);
- I915_WRITE(VLV_IIR, val);
- POSTING_READ(VLV_IIR);
-
- spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags);
}
static struct irq_chip lpe_audio_irqchip = {
@@ -330,8 +296,6 @@ void intel_lpe_audio_teardown(struct drm_i915_private *dev_priv)
desc = irq_to_desc(dev_priv->lpe_audio.irq);
- lpe_audio_irq_mask(&desc->irq_data);
-
lpe_audio_platdev_destroy(dev_priv);
irq_free_desc(dev_priv->lpe_audio.irq);
diff --git a/drivers/gpu/drm/i915/intel_lrc.c b/drivers/gpu/drm/i915/intel_lrc.c
index c8f7c631fc1f..62f44d3e7c43 100644
--- a/drivers/gpu/drm/i915/intel_lrc.c
+++ b/drivers/gpu/drm/i915/intel_lrc.c
@@ -326,8 +326,7 @@ static u64 execlists_update_context(struct drm_i915_gem_request *rq)
rq->ctx->ppgtt ?: rq->i915->mm.aliasing_ppgtt;
u32 *reg_state = ce->lrc_reg_state;
- assert_ring_tail_valid(rq->ring, rq->tail);
- reg_state[CTX_RING_TAIL+1] = rq->tail;
+ reg_state[CTX_RING_TAIL+1] = intel_ring_set_tail(rq->ring, rq->tail);
/* True 32b PPGTT with dynamic page allocation: update PDP
* registers and point the unallocated PDPs to scratch page.
@@ -1989,7 +1988,7 @@ static int execlists_context_deferred_alloc(struct i915_gem_context *ctx,
ce->ring = ring;
ce->state = vma;
- ce->initialised = engine->init_context == NULL;
+ ce->initialised |= engine->init_context == NULL;
return 0;
@@ -2036,8 +2035,7 @@ void intel_lr_context_resume(struct drm_i915_private *dev_priv)
ce->state->obj->mm.dirty = true;
i915_gem_object_unpin_map(ce->state->obj);
- ce->ring->head = ce->ring->tail = 0;
- intel_ring_update_space(ce->ring);
+ intel_ring_reset(ce->ring, 0);
}
}
}
diff --git a/drivers/gpu/drm/i915/intel_lspcon.c b/drivers/gpu/drm/i915/intel_lspcon.c
index 71cbe9c08932..5abef482eacf 100644
--- a/drivers/gpu/drm/i915/intel_lspcon.c
+++ b/drivers/gpu/drm/i915/intel_lspcon.c
@@ -240,7 +240,7 @@ bool lspcon_init(struct intel_digital_port *intel_dig_port)
return false;
}
- intel_dp_read_desc(dp);
+ drm_dp_read_desc(&dp->aux, &dp->desc, drm_dp_is_branch(dp->dpcd));
DRM_DEBUG_KMS("Success: LSPCON init\n");
return true;
diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c
index 570bd603f401..078fd1bfa5ea 100644
--- a/drivers/gpu/drm/i915/intel_pm.c
+++ b/drivers/gpu/drm/i915/intel_pm.c
@@ -3373,20 +3373,26 @@ skl_plane_downscale_amount(const struct intel_crtc_state *cstate,
/* n.b., src is 16.16 fixed point, dst is whole integer */
if (plane->id == PLANE_CURSOR) {
+ /*
+ * Cursors only support 0/180 degree rotation,
+ * hence no need to account for rotation here.
+ */
src_w = pstate->base.src_w;
src_h = pstate->base.src_h;
dst_w = pstate->base.crtc_w;
dst_h = pstate->base.crtc_h;
} else {
+ /*
+ * Src coordinates are already rotated by 270 degrees for
+ * the 90/270 degree plane rotation cases (to match the
+ * GTT mapping), hence no need to account for rotation here.
+ */
src_w = drm_rect_width(&pstate->base.src);
src_h = drm_rect_height(&pstate->base.src);
dst_w = drm_rect_width(&pstate->base.dst);
dst_h = drm_rect_height(&pstate->base.dst);
}
- if (drm_rotation_90_or_270(pstate->base.rotation))
- swap(dst_w, dst_h);
-
downscale_h = max(src_h / dst_h, (uint32_t)DRM_PLANE_HELPER_NO_SCALING);
downscale_w = max(src_w / dst_w, (uint32_t)DRM_PLANE_HELPER_NO_SCALING);
@@ -3417,12 +3423,14 @@ skl_plane_relative_data_rate(const struct intel_crtc_state *cstate,
if (y && format != DRM_FORMAT_NV12)
return 0;
+ /*
+ * Src coordinates are already rotated by 270 degrees for
+ * the 90/270 degree plane rotation cases (to match the
+ * GTT mapping), hence no need to account for rotation here.
+ */
width = drm_rect_width(&intel_pstate->base.src) >> 16;
height = drm_rect_height(&intel_pstate->base.src) >> 16;
- if (drm_rotation_90_or_270(pstate->rotation))
- swap(width, height);
-
/* for planar format */
if (format == DRM_FORMAT_NV12) {
if (y) /* y-plane data rate */
@@ -3505,12 +3513,14 @@ skl_ddb_min_alloc(const struct drm_plane_state *pstate,
fb->modifier != I915_FORMAT_MOD_Yf_TILED)
return 8;
+ /*
+ * Src coordinates are already rotated by 270 degrees for
+ * the 90/270 degree plane rotation cases (to match the
+ * GTT mapping), hence no need to account for rotation here.
+ */
src_w = drm_rect_width(&intel_pstate->base.src) >> 16;
src_h = drm_rect_height(&intel_pstate->base.src) >> 16;
- if (drm_rotation_90_or_270(pstate->rotation))
- swap(src_w, src_h);
-
/* Halve UV plane width and height for NV12 */
if (fb->format->format == DRM_FORMAT_NV12 && !y) {
src_w /= 2;
@@ -3794,13 +3804,15 @@ static int skl_compute_plane_wm(const struct drm_i915_private *dev_priv,
width = intel_pstate->base.crtc_w;
height = intel_pstate->base.crtc_h;
} else {
+ /*
+ * Src coordinates are already rotated by 270 degrees for
+ * the 90/270 degree plane rotation cases (to match the
+ * GTT mapping), hence no need to account for rotation here.
+ */
width = drm_rect_width(&intel_pstate->base.src) >> 16;
height = drm_rect_height(&intel_pstate->base.src) >> 16;
}
- if (drm_rotation_90_or_270(pstate->rotation))
- swap(width, height);
-
cpp = fb->format->cpp[0];
plane_pixel_rate = skl_adjusted_plane_pixel_rate(cstate, intel_pstate);
@@ -4335,11 +4347,19 @@ skl_compute_wm(struct drm_atomic_state *state)
struct drm_crtc_state *cstate;
struct intel_atomic_state *intel_state = to_intel_atomic_state(state);
struct skl_wm_values *results = &intel_state->wm_results;
+ struct drm_device *dev = state->dev;
struct skl_pipe_wm *pipe_wm;
bool changed = false;
int ret, i;
/*
+ * When we distrust bios wm we always need to recompute to set the
+ * expected DDB allocations for each CRTC.
+ */
+ if (to_i915(dev)->wm.distrust_bios_wm)
+ changed = true;
+
+ /*
* If this transaction isn't actually touching any CRTC's, don't
* bother with watermark calculation. Note that if we pass this
* test, we're guaranteed to hold at least one CRTC state mutex,
@@ -4349,6 +4369,7 @@ skl_compute_wm(struct drm_atomic_state *state)
*/
for_each_new_crtc_in_state(state, crtc, cstate, i)
changed = true;
+
if (!changed)
return 0;
diff --git a/drivers/gpu/drm/i915/intel_psr.c b/drivers/gpu/drm/i915/intel_psr.c
index c3780d0d2baf..559f1ab42bfc 100644
--- a/drivers/gpu/drm/i915/intel_psr.c
+++ b/drivers/gpu/drm/i915/intel_psr.c
@@ -435,8 +435,9 @@ static bool intel_psr_match_conditions(struct intel_dp *intel_dp)
}
/* PSR2 is restricted to work with panel resolutions upto 3200x2000 */
- if (intel_crtc->config->pipe_src_w > 3200 ||
- intel_crtc->config->pipe_src_h > 2000) {
+ if (dev_priv->psr.psr2_support &&
+ (intel_crtc->config->pipe_src_w > 3200 ||
+ intel_crtc->config->pipe_src_h > 2000)) {
dev_priv->psr.psr2_support = false;
return false;
}
diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.c b/drivers/gpu/drm/i915/intel_ringbuffer.c
index 66a2b8b83972..513a0f4b469b 100644
--- a/drivers/gpu/drm/i915/intel_ringbuffer.c
+++ b/drivers/gpu/drm/i915/intel_ringbuffer.c
@@ -49,7 +49,7 @@ static int __intel_ring_space(int head, int tail, int size)
void intel_ring_update_space(struct intel_ring *ring)
{
- ring->space = __intel_ring_space(ring->head, ring->tail, ring->size);
+ ring->space = __intel_ring_space(ring->head, ring->emit, ring->size);
}
static int
@@ -774,8 +774,8 @@ static void i9xx_submit_request(struct drm_i915_gem_request *request)
i915_gem_request_submit(request);
- assert_ring_tail_valid(request->ring, request->tail);
- I915_WRITE_TAIL(request->engine, request->tail);
+ I915_WRITE_TAIL(request->engine,
+ intel_ring_set_tail(request->ring, request->tail));
}
static void i9xx_emit_breadcrumb(struct drm_i915_gem_request *req, u32 *cs)
@@ -1316,11 +1316,23 @@ err:
return PTR_ERR(addr);
}
+void intel_ring_reset(struct intel_ring *ring, u32 tail)
+{
+ GEM_BUG_ON(!list_empty(&ring->request_list));
+ ring->tail = tail;
+ ring->head = tail;
+ ring->emit = tail;
+ intel_ring_update_space(ring);
+}
+
void intel_ring_unpin(struct intel_ring *ring)
{
GEM_BUG_ON(!ring->vma);
GEM_BUG_ON(!ring->vaddr);
+ /* Discard any unused bytes beyond that submitted to hw. */
+ intel_ring_reset(ring, ring->tail);
+
if (i915_vma_is_map_and_fenceable(ring->vma))
i915_vma_unpin_iomap(ring->vma);
else
@@ -1562,8 +1574,9 @@ void intel_legacy_submission_resume(struct drm_i915_private *dev_priv)
struct intel_engine_cs *engine;
enum intel_engine_id id;
+ /* Restart from the beginning of the rings for convenience */
for_each_engine(engine, dev_priv, id)
- engine->buffer->head = engine->buffer->tail;
+ intel_ring_reset(engine->buffer, 0);
}
static int ring_request_alloc(struct drm_i915_gem_request *request)
@@ -1616,7 +1629,7 @@ static int wait_for_space(struct drm_i915_gem_request *req, int bytes)
unsigned space;
/* Would completion of this request free enough space? */
- space = __intel_ring_space(target->postfix, ring->tail,
+ space = __intel_ring_space(target->postfix, ring->emit,
ring->size);
if (space >= bytes)
break;
@@ -1641,8 +1654,8 @@ static int wait_for_space(struct drm_i915_gem_request *req, int bytes)
u32 *intel_ring_begin(struct drm_i915_gem_request *req, int num_dwords)
{
struct intel_ring *ring = req->ring;
- int remain_actual = ring->size - ring->tail;
- int remain_usable = ring->effective_size - ring->tail;
+ int remain_actual = ring->size - ring->emit;
+ int remain_usable = ring->effective_size - ring->emit;
int bytes = num_dwords * sizeof(u32);
int total_bytes, wait_bytes;
bool need_wrap = false;
@@ -1678,17 +1691,17 @@ u32 *intel_ring_begin(struct drm_i915_gem_request *req, int num_dwords)
if (unlikely(need_wrap)) {
GEM_BUG_ON(remain_actual > ring->space);
- GEM_BUG_ON(ring->tail + remain_actual > ring->size);
+ GEM_BUG_ON(ring->emit + remain_actual > ring->size);
/* Fill the tail with MI_NOOP */
- memset(ring->vaddr + ring->tail, 0, remain_actual);
- ring->tail = 0;
+ memset(ring->vaddr + ring->emit, 0, remain_actual);
+ ring->emit = 0;
ring->space -= remain_actual;
}
- GEM_BUG_ON(ring->tail > ring->size - bytes);
- cs = ring->vaddr + ring->tail;
- ring->tail += bytes;
+ GEM_BUG_ON(ring->emit > ring->size - bytes);
+ cs = ring->vaddr + ring->emit;
+ ring->emit += bytes;
ring->space -= bytes;
GEM_BUG_ON(ring->space < 0);
@@ -1699,7 +1712,7 @@ u32 *intel_ring_begin(struct drm_i915_gem_request *req, int num_dwords)
int intel_ring_cacheline_align(struct drm_i915_gem_request *req)
{
int num_dwords =
- (req->ring->tail & (CACHELINE_BYTES - 1)) / sizeof(uint32_t);
+ (req->ring->emit & (CACHELINE_BYTES - 1)) / sizeof(uint32_t);
u32 *cs;
if (num_dwords == 0)
diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.h b/drivers/gpu/drm/i915/intel_ringbuffer.h
index a82a0807f64d..f7144fe09613 100644
--- a/drivers/gpu/drm/i915/intel_ringbuffer.h
+++ b/drivers/gpu/drm/i915/intel_ringbuffer.h
@@ -145,6 +145,7 @@ struct intel_ring {
u32 head;
u32 tail;
+ u32 emit;
int space;
int size;
@@ -488,6 +489,8 @@ intel_write_status_page(struct intel_engine_cs *engine, int reg, u32 value)
struct intel_ring *
intel_engine_create_ring(struct intel_engine_cs *engine, int size);
int intel_ring_pin(struct intel_ring *ring, unsigned int offset_bias);
+void intel_ring_reset(struct intel_ring *ring, u32 tail);
+void intel_ring_update_space(struct intel_ring *ring);
void intel_ring_unpin(struct intel_ring *ring);
void intel_ring_free(struct intel_ring *ring);
@@ -511,7 +514,7 @@ intel_ring_advance(struct drm_i915_gem_request *req, u32 *cs)
* reserved for the command packet (i.e. the value passed to
* intel_ring_begin()).
*/
- GEM_BUG_ON((req->ring->vaddr + req->ring->tail) != cs);
+ GEM_BUG_ON((req->ring->vaddr + req->ring->emit) != cs);
}
static inline u32
@@ -540,7 +543,19 @@ assert_ring_tail_valid(const struct intel_ring *ring, unsigned int tail)
GEM_BUG_ON(tail >= ring->size);
}
-void intel_ring_update_space(struct intel_ring *ring);
+static inline unsigned int
+intel_ring_set_tail(struct intel_ring *ring, unsigned int tail)
+{
+ /* Whilst writes to the tail are strictly order, there is no
+ * serialisation between readers and the writers. The tail may be
+ * read by i915_gem_request_retire() just as it is being updated
+ * by execlists, as although the breadcrumb is complete, the context
+ * switch hasn't been seen.
+ */
+ assert_ring_tail_valid(ring, tail);
+ ring->tail = tail;
+ return tail;
+}
void intel_engine_init_global_seqno(struct intel_engine_cs *engine, u32 seqno);
diff --git a/drivers/gpu/drm/i915/intel_sprite.c b/drivers/gpu/drm/i915/intel_sprite.c
index 8c87c717c7cd..e6517edcd16b 100644
--- a/drivers/gpu/drm/i915/intel_sprite.c
+++ b/drivers/gpu/drm/i915/intel_sprite.c
@@ -83,10 +83,13 @@ int intel_usecs_to_scanlines(const struct drm_display_mode *adjusted_mode,
*/
void intel_pipe_update_start(struct intel_crtc *crtc)
{
+ struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
const struct drm_display_mode *adjusted_mode = &crtc->config->base.adjusted_mode;
long timeout = msecs_to_jiffies_timeout(1);
int scanline, min, max, vblank_start;
wait_queue_head_t *wq = drm_crtc_vblank_waitqueue(&crtc->base);
+ bool need_vlv_dsi_wa = (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) &&
+ intel_crtc_has_type(crtc->config, INTEL_OUTPUT_DSI);
DEFINE_WAIT(wait);
vblank_start = adjusted_mode->crtc_vblank_start;
@@ -139,6 +142,24 @@ void intel_pipe_update_start(struct intel_crtc *crtc)
drm_crtc_vblank_put(&crtc->base);
+ /*
+ * On VLV/CHV DSI the scanline counter would appear to
+ * increment approx. 1/3 of a scanline before start of vblank.
+ * The registers still get latched at start of vblank however.
+ * This means we must not write any registers on the first
+ * line of vblank (since not the whole line is actually in
+ * vblank). And unfortunately we can't use the interrupt to
+ * wait here since it will fire too soon. We could use the
+ * frame start interrupt instead since it will fire after the
+ * critical scanline, but that would require more changes
+ * in the interrupt code. So for now we'll just do the nasty
+ * thing and poll for the bad scanline to pass us by.
+ *
+ * FIXME figure out if BXT+ DSI suffers from this as well
+ */
+ while (need_vlv_dsi_wa && scanline == vblank_start)
+ scanline = intel_get_crtc_scanline(crtc);
+
crtc->debug.scanline_start = scanline;
crtc->debug.start_vbl_time = ktime_get();
crtc->debug.start_vbl_count = intel_crtc_get_vblank_counter(crtc);
diff --git a/drivers/gpu/drm/i915/intel_uc.h b/drivers/gpu/drm/i915/intel_uc.h
index 4b7f73aeddac..f84115261ae7 100644
--- a/drivers/gpu/drm/i915/intel_uc.h
+++ b/drivers/gpu/drm/i915/intel_uc.h
@@ -59,8 +59,6 @@ struct drm_i915_gem_request;
* available in the work queue (note, the queue is shared,
* not per-engine). It is OK for this to be nonzero, but
* it should not be huge!
- * q_fail: failed to enqueue a work item. This should never happen,
- * because we check for space beforehand.
* b_fail: failed to ring the doorbell. This should never happen, unless
* somehow the hardware misbehaves, or maybe if the GuC firmware
* crashes? We probably need to reset the GPU to recover.
diff --git a/drivers/gpu/drm/i915/selftests/i915_gem_context.c b/drivers/gpu/drm/i915/selftests/i915_gem_context.c
index 1afb8b06e3e1..12b85b3278cd 100644
--- a/drivers/gpu/drm/i915/selftests/i915_gem_context.c
+++ b/drivers/gpu/drm/i915/selftests/i915_gem_context.c
@@ -320,7 +320,7 @@ static unsigned long max_dwords(struct drm_i915_gem_object *obj)
static int igt_ctx_exec(void *arg)
{
struct drm_i915_private *i915 = arg;
- struct drm_i915_gem_object *obj;
+ struct drm_i915_gem_object *obj = NULL;
struct drm_file *file;
IGT_TIMEOUT(end_time);
LIST_HEAD(objects);
@@ -359,7 +359,7 @@ static int igt_ctx_exec(void *arg)
}
for_each_engine(engine, i915, id) {
- if (dw == 0) {
+ if (!obj) {
obj = create_test_object(ctx, file, &objects);
if (IS_ERR(obj)) {
err = PTR_ERR(obj);
@@ -376,8 +376,10 @@ static int igt_ctx_exec(void *arg)
goto out_unlock;
}
- if (++dw == max_dwords(obj))
+ if (++dw == max_dwords(obj)) {
+ obj = NULL;
dw = 0;
+ }
ndwords++;
}
ncontexts++;
diff --git a/drivers/gpu/drm/imx/imx-ldb.c b/drivers/gpu/drm/imx/imx-ldb.c
index 8fb801fab039..8b05ecb8fdef 100644
--- a/drivers/gpu/drm/imx/imx-ldb.c
+++ b/drivers/gpu/drm/imx/imx-ldb.c
@@ -673,7 +673,7 @@ static int imx_ldb_bind(struct device *dev, struct device *master, void *data)
ret = drm_of_find_panel_or_bridge(child,
imx_ldb->lvds_mux ? 4 : 2, 0,
&channel->panel, &channel->bridge);
- if (ret)
+ if (ret && ret != -ENODEV)
return ret;
/* panel ddc only if there is no bridge */
diff --git a/drivers/gpu/drm/mediatek/mtk_dsi.c b/drivers/gpu/drm/mediatek/mtk_dsi.c
index 808b995a990f..b5cc6e12334c 100644
--- a/drivers/gpu/drm/mediatek/mtk_dsi.c
+++ b/drivers/gpu/drm/mediatek/mtk_dsi.c
@@ -19,6 +19,7 @@
#include <drm/drm_of.h>
#include <linux/clk.h>
#include <linux/component.h>
+#include <linux/iopoll.h>
#include <linux/irq.h>
#include <linux/of.h>
#include <linux/of_platform.h>
@@ -900,16 +901,12 @@ static int mtk_dsi_host_detach(struct mipi_dsi_host *host,
static void mtk_dsi_wait_for_idle(struct mtk_dsi *dsi)
{
- u32 timeout_ms = 500000; /* total 1s ~ 2s timeout */
-
- while (timeout_ms--) {
- if (!(readl(dsi->regs + DSI_INTSTA) & DSI_BUSY))
- break;
-
- usleep_range(2, 4);
- }
+ int ret;
+ u32 val;
- if (timeout_ms == 0) {
+ ret = readl_poll_timeout(dsi->regs + DSI_INTSTA, val, !(val & DSI_BUSY),
+ 4, 2000000);
+ if (ret) {
DRM_WARN("polling dsi wait not busy timeout!\n");
mtk_dsi_enable(dsi);
diff --git a/drivers/gpu/drm/mediatek/mtk_hdmi.c b/drivers/gpu/drm/mediatek/mtk_hdmi.c
index 41a1c03b0347..0a4ffd724146 100644
--- a/drivers/gpu/drm/mediatek/mtk_hdmi.c
+++ b/drivers/gpu/drm/mediatek/mtk_hdmi.c
@@ -1062,7 +1062,7 @@ static int mtk_hdmi_setup_vendor_specific_infoframe(struct mtk_hdmi *hdmi,
}
err = hdmi_vendor_infoframe_pack(&frame, buffer, sizeof(buffer));
- if (err) {
+ if (err < 0) {
dev_err(hdmi->dev, "Failed to pack vendor infoframe: %zd\n",
err);
return err;
diff --git a/drivers/gpu/drm/meson/meson_drv.c b/drivers/gpu/drm/meson/meson_drv.c
index 75382f5f0fce..10b227d83e9a 100644
--- a/drivers/gpu/drm/meson/meson_drv.c
+++ b/drivers/gpu/drm/meson/meson_drv.c
@@ -152,7 +152,7 @@ static struct regmap_config meson_regmap_config = {
.max_register = 0x1000,
};
-static int meson_drv_bind(struct device *dev)
+static int meson_drv_bind_master(struct device *dev, bool has_components)
{
struct platform_device *pdev = to_platform_device(dev);
struct meson_drm *priv;
@@ -233,10 +233,12 @@ static int meson_drv_bind(struct device *dev)
if (ret)
goto free_drm;
- ret = component_bind_all(drm->dev, drm);
- if (ret) {
- dev_err(drm->dev, "Couldn't bind all components\n");
- goto free_drm;
+ if (has_components) {
+ ret = component_bind_all(drm->dev, drm);
+ if (ret) {
+ dev_err(drm->dev, "Couldn't bind all components\n");
+ goto free_drm;
+ }
}
ret = meson_plane_create(priv);
@@ -276,6 +278,11 @@ free_drm:
return ret;
}
+static int meson_drv_bind(struct device *dev)
+{
+ return meson_drv_bind_master(dev, true);
+}
+
static void meson_drv_unbind(struct device *dev)
{
struct drm_device *drm = dev_get_drvdata(dev);
@@ -357,6 +364,9 @@ static int meson_drv_probe(struct platform_device *pdev)
count += meson_probe_remote(pdev, &match, np, remote);
}
+ if (count && !match)
+ return meson_drv_bind_master(&pdev->dev, false);
+
/* If some endpoints were found, initialize the nodes */
if (count) {
dev_info(&pdev->dev, "Queued %d outputs on vpu\n", count);
diff --git a/drivers/gpu/drm/mgag200/mgag200_mode.c b/drivers/gpu/drm/mgag200/mgag200_mode.c
index adb411a078e8..f4b53588e071 100644
--- a/drivers/gpu/drm/mgag200/mgag200_mode.c
+++ b/drivers/gpu/drm/mgag200/mgag200_mode.c
@@ -1173,7 +1173,10 @@ static int mga_crtc_mode_set(struct drm_crtc *crtc,
if (IS_G200_SE(mdev)) {
- if (mdev->unique_rev_id >= 0x02) {
+ if (mdev->unique_rev_id >= 0x04) {
+ WREG8(MGAREG_CRTCEXT_INDEX, 0x06);
+ WREG8(MGAREG_CRTCEXT_DATA, 0);
+ } else if (mdev->unique_rev_id >= 0x02) {
u8 hi_pri_lvl;
u32 bpp;
u32 mb;
@@ -1639,6 +1642,10 @@ static int mga_vga_mode_valid(struct drm_connector *connector,
if (mga_vga_calculate_mode_bandwidth(mode, bpp)
> (30100 * 1024))
return MODE_BANDWIDTH;
+ } else {
+ if (mga_vga_calculate_mode_bandwidth(mode, bpp)
+ > (55000 * 1024))
+ return MODE_BANDWIDTH;
}
} else if (mdev->type == G200_WB) {
if (mode->hdisplay > 1280)
diff --git a/drivers/gpu/drm/msm/Kconfig b/drivers/gpu/drm/msm/Kconfig
index 5b8e23d051f2..0a31cd6d01ce 100644
--- a/drivers/gpu/drm/msm/Kconfig
+++ b/drivers/gpu/drm/msm/Kconfig
@@ -13,6 +13,7 @@ config DRM_MSM
select QCOM_SCM
select SND_SOC_HDMI_CODEC if SND_SOC
select SYNC_FILE
+ select PM_OPP
default y
help
DRM/KMS driver for MSM/snapdragon.
diff --git a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_mdss.c b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_mdss.c
index f8f48d014978..9c34d7824988 100644
--- a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_mdss.c
+++ b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_mdss.c
@@ -116,7 +116,7 @@ static int mdss_hw_irqdomain_map(struct irq_domain *d, unsigned int irq,
return 0;
}
-static struct irq_domain_ops mdss_hw_irqdomain_ops = {
+static const struct irq_domain_ops mdss_hw_irqdomain_ops = {
.map = mdss_hw_irqdomain_map,
.xlate = irq_domain_xlate_onecell,
};
diff --git a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_plane.c b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_plane.c
index a38c5fe6cc19..7d3741215387 100644
--- a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_plane.c
+++ b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_plane.c
@@ -225,9 +225,10 @@ mdp5_plane_duplicate_state(struct drm_plane *plane)
mdp5_state = kmemdup(to_mdp5_plane_state(plane->state),
sizeof(*mdp5_state), GFP_KERNEL);
+ if (!mdp5_state)
+ return NULL;
- if (mdp5_state && mdp5_state->base.fb)
- drm_framebuffer_reference(mdp5_state->base.fb);
+ __drm_atomic_helper_plane_duplicate_state(plane, &mdp5_state->base);
return &mdp5_state->base;
}
@@ -444,6 +445,10 @@ static int mdp5_plane_atomic_check_with_state(struct drm_crtc_state *crtc_state,
mdp5_pipe_release(state->state, old_hwpipe);
mdp5_pipe_release(state->state, old_right_hwpipe);
}
+ } else {
+ mdp5_pipe_release(state->state, mdp5_state->hwpipe);
+ mdp5_pipe_release(state->state, mdp5_state->r_hwpipe);
+ mdp5_state->hwpipe = mdp5_state->r_hwpipe = NULL;
}
return 0;
diff --git a/drivers/gpu/drm/msm/msm_drv.c b/drivers/gpu/drm/msm/msm_drv.c
index 87b5695d4034..9d498eb81906 100644
--- a/drivers/gpu/drm/msm/msm_drv.c
+++ b/drivers/gpu/drm/msm/msm_drv.c
@@ -830,6 +830,7 @@ static struct drm_driver msm_driver = {
.prime_fd_to_handle = drm_gem_prime_fd_to_handle,
.gem_prime_export = drm_gem_prime_export,
.gem_prime_import = drm_gem_prime_import,
+ .gem_prime_res_obj = msm_gem_prime_res_obj,
.gem_prime_pin = msm_gem_prime_pin,
.gem_prime_unpin = msm_gem_prime_unpin,
.gem_prime_get_sg_table = msm_gem_prime_get_sg_table,
diff --git a/drivers/gpu/drm/msm/msm_drv.h b/drivers/gpu/drm/msm/msm_drv.h
index 28b6f9ba5066..1b26ca626528 100644
--- a/drivers/gpu/drm/msm/msm_drv.h
+++ b/drivers/gpu/drm/msm/msm_drv.h
@@ -224,6 +224,7 @@ struct sg_table *msm_gem_prime_get_sg_table(struct drm_gem_object *obj);
void *msm_gem_prime_vmap(struct drm_gem_object *obj);
void msm_gem_prime_vunmap(struct drm_gem_object *obj, void *vaddr);
int msm_gem_prime_mmap(struct drm_gem_object *obj, struct vm_area_struct *vma);
+struct reservation_object *msm_gem_prime_res_obj(struct drm_gem_object *obj);
struct drm_gem_object *msm_gem_prime_import_sg_table(struct drm_device *dev,
struct dma_buf_attachment *attach, struct sg_table *sg);
int msm_gem_prime_pin(struct drm_gem_object *obj);
diff --git a/drivers/gpu/drm/msm/msm_fence.c b/drivers/gpu/drm/msm/msm_fence.c
index 3f299c537b77..a2f89bac9c16 100644
--- a/drivers/gpu/drm/msm/msm_fence.c
+++ b/drivers/gpu/drm/msm/msm_fence.c
@@ -99,8 +99,8 @@ void msm_update_fence(struct msm_fence_context *fctx, uint32_t fence)
}
struct msm_fence {
- struct msm_fence_context *fctx;
struct dma_fence base;
+ struct msm_fence_context *fctx;
};
static inline struct msm_fence *to_msm_fence(struct dma_fence *fence)
@@ -130,19 +130,13 @@ static bool msm_fence_signaled(struct dma_fence *fence)
return fence_completed(f->fctx, f->base.seqno);
}
-static void msm_fence_release(struct dma_fence *fence)
-{
- struct msm_fence *f = to_msm_fence(fence);
- kfree_rcu(f, base.rcu);
-}
-
static const struct dma_fence_ops msm_fence_ops = {
.get_driver_name = msm_fence_get_driver_name,
.get_timeline_name = msm_fence_get_timeline_name,
.enable_signaling = msm_fence_enable_signaling,
.signaled = msm_fence_signaled,
.wait = dma_fence_default_wait,
- .release = msm_fence_release,
+ .release = dma_fence_free,
};
struct dma_fence *
diff --git a/drivers/gpu/drm/msm/msm_gem.c b/drivers/gpu/drm/msm/msm_gem.c
index 68e509b3b9e4..50289a23baf8 100644
--- a/drivers/gpu/drm/msm/msm_gem.c
+++ b/drivers/gpu/drm/msm/msm_gem.c
@@ -758,6 +758,8 @@ static int msm_gem_new_impl(struct drm_device *dev,
struct msm_gem_object *msm_obj;
bool use_vram = false;
+ WARN_ON(!mutex_is_locked(&dev->struct_mutex));
+
switch (flags & MSM_BO_CACHE_MASK) {
case MSM_BO_UNCACHED:
case MSM_BO_CACHED:
@@ -853,7 +855,11 @@ struct drm_gem_object *msm_gem_import(struct drm_device *dev,
size = PAGE_ALIGN(dmabuf->size);
+ /* Take mutex so we can modify the inactive list in msm_gem_new_impl */
+ mutex_lock(&dev->struct_mutex);
ret = msm_gem_new_impl(dev, size, MSM_BO_WC, dmabuf->resv, &obj);
+ mutex_unlock(&dev->struct_mutex);
+
if (ret)
goto fail;
diff --git a/drivers/gpu/drm/msm/msm_gem_prime.c b/drivers/gpu/drm/msm/msm_gem_prime.c
index 60bb290700ce..13403c6da6c7 100644
--- a/drivers/gpu/drm/msm/msm_gem_prime.c
+++ b/drivers/gpu/drm/msm/msm_gem_prime.c
@@ -70,3 +70,10 @@ void msm_gem_prime_unpin(struct drm_gem_object *obj)
if (!obj->import_attach)
msm_gem_put_pages(obj);
}
+
+struct reservation_object *msm_gem_prime_res_obj(struct drm_gem_object *obj)
+{
+ struct msm_gem_object *msm_obj = to_msm_bo(obj);
+
+ return msm_obj->resv;
+}
diff --git a/drivers/gpu/drm/msm/msm_gem_submit.c b/drivers/gpu/drm/msm/msm_gem_submit.c
index 1c545ebe6a5a..7832e6421d25 100644
--- a/drivers/gpu/drm/msm/msm_gem_submit.c
+++ b/drivers/gpu/drm/msm/msm_gem_submit.c
@@ -410,12 +410,11 @@ int msm_ioctl_gem_submit(struct drm_device *dev, void *data,
if (!in_fence)
return -EINVAL;
- /* TODO if we get an array-fence due to userspace merging multiple
- * fences, we need a way to determine if all the backing fences
- * are from our own context..
+ /*
+ * Wait if the fence is from a foreign context, or if the fence
+ * array contains any fence from a foreign context.
*/
-
- if (in_fence->context != gpu->fctx->context) {
+ if (!dma_fence_match_context(in_fence, gpu->fctx->context)) {
ret = dma_fence_wait(in_fence, true);
if (ret)
return ret;
@@ -496,8 +495,9 @@ int msm_ioctl_gem_submit(struct drm_device *dev, void *data,
goto out;
}
- if ((submit_cmd.size + submit_cmd.submit_offset) >=
- msm_obj->base.size) {
+ if (!submit_cmd.size ||
+ ((submit_cmd.size + submit_cmd.submit_offset) >
+ msm_obj->base.size)) {
DRM_ERROR("invalid cmdstream size: %u\n", submit_cmd.size);
ret = -EINVAL;
goto out;
diff --git a/drivers/gpu/drm/msm/msm_gpu.c b/drivers/gpu/drm/msm/msm_gpu.c
index 97b9c38c6b3f..0fdc88d79ca8 100644
--- a/drivers/gpu/drm/msm/msm_gpu.c
+++ b/drivers/gpu/drm/msm/msm_gpu.c
@@ -549,9 +549,9 @@ static int get_clocks(struct platform_device *pdev, struct msm_gpu *gpu)
gpu->grp_clks[i] = get_clock(dev, name);
/* Remember the key clocks that we need to control later */
- if (!strcmp(name, "core"))
+ if (!strcmp(name, "core") || !strcmp(name, "core_clk"))
gpu->core_clk = gpu->grp_clks[i];
- else if (!strcmp(name, "rbbmtimer"))
+ else if (!strcmp(name, "rbbmtimer") || !strcmp(name, "rbbmtimer_clk"))
gpu->rbbmtimer_clk = gpu->grp_clks[i];
++i;
diff --git a/drivers/gpu/drm/mxsfb/mxsfb_crtc.c b/drivers/gpu/drm/mxsfb/mxsfb_crtc.c
index 1144e0c9e894..0abe77675b76 100644
--- a/drivers/gpu/drm/mxsfb/mxsfb_crtc.c
+++ b/drivers/gpu/drm/mxsfb/mxsfb_crtc.c
@@ -35,6 +35,13 @@
#include "mxsfb_drv.h"
#include "mxsfb_regs.h"
+#define MXS_SET_ADDR 0x4
+#define MXS_CLR_ADDR 0x8
+#define MODULE_CLKGATE BIT(30)
+#define MODULE_SFTRST BIT(31)
+/* 1 second delay should be plenty of time for block reset */
+#define RESET_TIMEOUT 1000000
+
static u32 set_hsync_pulse_width(struct mxsfb_drm_private *mxsfb, u32 val)
{
return (val & mxsfb->devdata->hs_wdth_mask) <<
@@ -159,6 +166,36 @@ static void mxsfb_disable_controller(struct mxsfb_drm_private *mxsfb)
clk_disable_unprepare(mxsfb->clk_disp_axi);
}
+/*
+ * Clear the bit and poll it cleared. This is usually called with
+ * a reset address and mask being either SFTRST(bit 31) or CLKGATE
+ * (bit 30).
+ */
+static int clear_poll_bit(void __iomem *addr, u32 mask)
+{
+ u32 reg;
+
+ writel(mask, addr + MXS_CLR_ADDR);
+ return readl_poll_timeout(addr, reg, !(reg & mask), 0, RESET_TIMEOUT);
+}
+
+static int mxsfb_reset_block(void __iomem *reset_addr)
+{
+ int ret;
+
+ ret = clear_poll_bit(reset_addr, MODULE_SFTRST);
+ if (ret)
+ return ret;
+
+ writel(MODULE_CLKGATE, reset_addr + MXS_CLR_ADDR);
+
+ ret = clear_poll_bit(reset_addr, MODULE_SFTRST);
+ if (ret)
+ return ret;
+
+ return clear_poll_bit(reset_addr, MODULE_CLKGATE);
+}
+
static void mxsfb_crtc_mode_set_nofb(struct mxsfb_drm_private *mxsfb)
{
struct drm_display_mode *m = &mxsfb->pipe.crtc.state->adjusted_mode;
@@ -173,6 +210,11 @@ static void mxsfb_crtc_mode_set_nofb(struct mxsfb_drm_private *mxsfb)
*/
mxsfb_enable_axi_clk(mxsfb);
+ /* Mandatory eLCDIF reset as per the Reference Manual */
+ err = mxsfb_reset_block(mxsfb->base);
+ if (err)
+ return;
+
/* Clear the FIFOs */
writel(CTRL1_FIFO_CLEAR, mxsfb->base + LCDC_CTRL1 + REG_SET);
diff --git a/drivers/gpu/drm/nouveau/include/nvkm/subdev/timer.h b/drivers/gpu/drm/nouveau/include/nvkm/subdev/timer.h
index 6a567fe347b3..820a4805916f 100644
--- a/drivers/gpu/drm/nouveau/include/nvkm/subdev/timer.h
+++ b/drivers/gpu/drm/nouveau/include/nvkm/subdev/timer.h
@@ -4,6 +4,7 @@
struct nvkm_alarm {
struct list_head head;
+ struct list_head exec;
u64 timestamp;
void (*func)(struct nvkm_alarm *);
};
diff --git a/drivers/gpu/drm/nouveau/nouveau_acpi.c b/drivers/gpu/drm/nouveau/nouveau_acpi.c
index 39468c218027..7459ef9943ec 100644
--- a/drivers/gpu/drm/nouveau/nouveau_acpi.c
+++ b/drivers/gpu/drm/nouveau/nouveau_acpi.c
@@ -60,15 +60,13 @@ bool nouveau_is_v1_dsm(void) {
}
#ifdef CONFIG_VGA_SWITCHEROO
-static const char nouveau_dsm_muid[] = {
- 0xA0, 0xA0, 0x95, 0x9D, 0x60, 0x00, 0x48, 0x4D,
- 0xB3, 0x4D, 0x7E, 0x5F, 0xEA, 0x12, 0x9F, 0xD4,
-};
+static const guid_t nouveau_dsm_muid =
+ GUID_INIT(0x9D95A0A0, 0x0060, 0x4D48,
+ 0xB3, 0x4D, 0x7E, 0x5F, 0xEA, 0x12, 0x9F, 0xD4);
-static const char nouveau_op_dsm_muid[] = {
- 0xF8, 0xD8, 0x86, 0xA4, 0xDA, 0x0B, 0x1B, 0x47,
- 0xA7, 0x2B, 0x60, 0x42, 0xA6, 0xB5, 0xBE, 0xE0,
-};
+static const guid_t nouveau_op_dsm_muid =
+ GUID_INIT(0xA486D8F8, 0x0BDA, 0x471B,
+ 0xA7, 0x2B, 0x60, 0x42, 0xA6, 0xB5, 0xBE, 0xE0);
static int nouveau_optimus_dsm(acpi_handle handle, int func, int arg, uint32_t *result)
{
@@ -86,7 +84,7 @@ static int nouveau_optimus_dsm(acpi_handle handle, int func, int arg, uint32_t *
args_buff[i] = (arg >> i * 8) & 0xFF;
*result = 0;
- obj = acpi_evaluate_dsm_typed(handle, nouveau_op_dsm_muid, 0x00000100,
+ obj = acpi_evaluate_dsm_typed(handle, &nouveau_op_dsm_muid, 0x00000100,
func, &argv4, ACPI_TYPE_BUFFER);
if (!obj) {
acpi_handle_info(handle, "failed to evaluate _DSM\n");
@@ -138,7 +136,7 @@ static int nouveau_dsm(acpi_handle handle, int func, int arg)
.integer.value = arg,
};
- obj = acpi_evaluate_dsm_typed(handle, nouveau_dsm_muid, 0x00000102,
+ obj = acpi_evaluate_dsm_typed(handle, &nouveau_dsm_muid, 0x00000102,
func, &argv4, ACPI_TYPE_INTEGER);
if (!obj) {
acpi_handle_info(handle, "failed to evaluate _DSM\n");
@@ -259,7 +257,7 @@ static void nouveau_dsm_pci_probe(struct pci_dev *pdev, acpi_handle *dhandle_out
if (!acpi_has_method(dhandle, "_DSM"))
return;
- supports_mux = acpi_check_dsm(dhandle, nouveau_dsm_muid, 0x00000102,
+ supports_mux = acpi_check_dsm(dhandle, &nouveau_dsm_muid, 0x00000102,
1 << NOUVEAU_DSM_POWER);
optimus_funcs = nouveau_dsm_get_optimus_functions(dhandle);
diff --git a/drivers/gpu/drm/nouveau/nouveau_drm.c b/drivers/gpu/drm/nouveau/nouveau_drm.c
index 36268e1802b5..15a13d09d431 100644
--- a/drivers/gpu/drm/nouveau/nouveau_drm.c
+++ b/drivers/gpu/drm/nouveau/nouveau_drm.c
@@ -80,7 +80,7 @@ int nouveau_modeset = -1;
module_param_named(modeset, nouveau_modeset, int, 0400);
MODULE_PARM_DESC(runpm, "disable (0), force enable (1), optimus only default (-1)");
-int nouveau_runtime_pm = -1;
+static int nouveau_runtime_pm = -1;
module_param_named(runpm, nouveau_runtime_pm, int, 0400);
static struct drm_driver driver_stub;
@@ -495,7 +495,7 @@ nouveau_drm_load(struct drm_device *dev, unsigned long flags)
nouveau_fbcon_init(dev);
nouveau_led_init(dev);
- if (nouveau_runtime_pm != 0) {
+ if (nouveau_pmops_runtime()) {
pm_runtime_use_autosuspend(dev->dev);
pm_runtime_set_autosuspend_delay(dev->dev, 5000);
pm_runtime_set_active(dev->dev);
@@ -527,7 +527,7 @@ nouveau_drm_unload(struct drm_device *dev)
{
struct nouveau_drm *drm = nouveau_drm(dev);
- if (nouveau_runtime_pm != 0) {
+ if (nouveau_pmops_runtime()) {
pm_runtime_get_sync(dev->dev);
pm_runtime_forbid(dev->dev);
}
@@ -726,6 +726,14 @@ nouveau_pmops_thaw(struct device *dev)
return nouveau_do_resume(drm_dev, false);
}
+bool
+nouveau_pmops_runtime()
+{
+ if (nouveau_runtime_pm == -1)
+ return nouveau_is_optimus() || nouveau_is_v1_dsm();
+ return nouveau_runtime_pm == 1;
+}
+
static int
nouveau_pmops_runtime_suspend(struct device *dev)
{
@@ -733,14 +741,7 @@ nouveau_pmops_runtime_suspend(struct device *dev)
struct drm_device *drm_dev = pci_get_drvdata(pdev);
int ret;
- if (nouveau_runtime_pm == 0) {
- pm_runtime_forbid(dev);
- return -EBUSY;
- }
-
- /* are we optimus enabled? */
- if (nouveau_runtime_pm == -1 && !nouveau_is_optimus() && !nouveau_is_v1_dsm()) {
- DRM_DEBUG_DRIVER("failing to power off - not optimus\n");
+ if (!nouveau_pmops_runtime()) {
pm_runtime_forbid(dev);
return -EBUSY;
}
@@ -765,8 +766,10 @@ nouveau_pmops_runtime_resume(struct device *dev)
struct nvif_device *device = &nouveau_drm(drm_dev)->client.device;
int ret;
- if (nouveau_runtime_pm == 0)
- return -EINVAL;
+ if (!nouveau_pmops_runtime()) {
+ pm_runtime_forbid(dev);
+ return -EBUSY;
+ }
pci_set_power_state(pdev, PCI_D0);
pci_restore_state(pdev);
@@ -796,14 +799,7 @@ nouveau_pmops_runtime_idle(struct device *dev)
struct nouveau_drm *drm = nouveau_drm(drm_dev);
struct drm_crtc *crtc;
- if (nouveau_runtime_pm == 0) {
- pm_runtime_forbid(dev);
- return -EBUSY;
- }
-
- /* are we optimus enabled? */
- if (nouveau_runtime_pm == -1 && !nouveau_is_optimus() && !nouveau_is_v1_dsm()) {
- DRM_DEBUG_DRIVER("failing to power off - not optimus\n");
+ if (!nouveau_pmops_runtime()) {
pm_runtime_forbid(dev);
return -EBUSY;
}
diff --git a/drivers/gpu/drm/nouveau/nouveau_drv.h b/drivers/gpu/drm/nouveau/nouveau_drv.h
index eadec2f49ad3..a11b6aaed325 100644
--- a/drivers/gpu/drm/nouveau/nouveau_drv.h
+++ b/drivers/gpu/drm/nouveau/nouveau_drv.h
@@ -108,8 +108,6 @@ nouveau_cli(struct drm_file *fpriv)
#include <nvif/object.h>
#include <nvif/device.h>
-extern int nouveau_runtime_pm;
-
struct nouveau_drm {
struct nouveau_cli client;
struct drm_device *dev;
@@ -195,6 +193,7 @@ nouveau_drm(struct drm_device *dev)
int nouveau_pmops_suspend(struct device *);
int nouveau_pmops_resume(struct device *);
+bool nouveau_pmops_runtime(void);
#include <nvkm/core/tegra.h>
diff --git a/drivers/gpu/drm/nouveau/nouveau_vga.c b/drivers/gpu/drm/nouveau/nouveau_vga.c
index a4aacbc0cec8..02fe0efb9e16 100644
--- a/drivers/gpu/drm/nouveau/nouveau_vga.c
+++ b/drivers/gpu/drm/nouveau/nouveau_vga.c
@@ -87,7 +87,7 @@ void
nouveau_vga_init(struct nouveau_drm *drm)
{
struct drm_device *dev = drm->dev;
- bool runtime = false;
+ bool runtime = nouveau_pmops_runtime();
/* only relevant for PCI devices */
if (!dev->pdev)
@@ -99,10 +99,6 @@ nouveau_vga_init(struct nouveau_drm *drm)
if (pci_is_thunderbolt_attached(dev->pdev))
return;
- if (nouveau_runtime_pm == 1)
- runtime = true;
- if ((nouveau_runtime_pm == -1) && (nouveau_is_optimus() || nouveau_is_v1_dsm()))
- runtime = true;
vga_switcheroo_register_client(dev->pdev, &nouveau_switcheroo_ops, runtime);
if (runtime && nouveau_is_v1_dsm() && !nouveau_is_optimus())
@@ -113,18 +109,13 @@ void
nouveau_vga_fini(struct nouveau_drm *drm)
{
struct drm_device *dev = drm->dev;
- bool runtime = false;
+ bool runtime = nouveau_pmops_runtime();
vga_client_register(dev->pdev, NULL, NULL, NULL);
if (pci_is_thunderbolt_attached(dev->pdev))
return;
- if (nouveau_runtime_pm == 1)
- runtime = true;
- if ((nouveau_runtime_pm == -1) && (nouveau_is_optimus() || nouveau_is_v1_dsm()))
- runtime = true;
-
vga_switcheroo_unregister_client(dev->pdev);
if (runtime && nouveau_is_v1_dsm() && !nouveau_is_optimus())
vga_switcheroo_fini_domain_pm_ops(drm->dev->dev);
diff --git a/drivers/gpu/drm/nouveau/nv50_display.c b/drivers/gpu/drm/nouveau/nv50_display.c
index a7663249b3ba..06e564a9ccb2 100644
--- a/drivers/gpu/drm/nouveau/nv50_display.c
+++ b/drivers/gpu/drm/nouveau/nv50_display.c
@@ -2107,7 +2107,8 @@ nv50_head_atomic_check(struct drm_crtc *crtc, struct drm_crtc_state *state)
asyc->set.dither = true;
}
} else {
- asyc->set.mask = ~0;
+ if (asyc)
+ asyc->set.mask = ~0;
asyh->set.mask = ~0;
}
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/mxm/base.c b/drivers/gpu/drm/nouveau/nvkm/subdev/mxm/base.c
index e3e2f5e83815..f44682d62f75 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/mxm/base.c
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/mxm/base.c
@@ -81,10 +81,9 @@ mxm_shadow_dsm(struct nvkm_mxm *mxm, u8 version)
{
struct nvkm_subdev *subdev = &mxm->subdev;
struct nvkm_device *device = subdev->device;
- static char muid[] = {
- 0x00, 0xA4, 0x04, 0x40, 0x7D, 0x91, 0xF2, 0x4C,
- 0xB8, 0x9C, 0x79, 0xB6, 0x2F, 0xD5, 0x56, 0x65
- };
+ static guid_t muid =
+ GUID_INIT(0x4004A400, 0x917D, 0x4CF2,
+ 0xB8, 0x9C, 0x79, 0xB6, 0x2F, 0xD5, 0x56, 0x65);
u32 mxms_args[] = { 0x00000000 };
union acpi_object argv4 = {
.buffer.type = ACPI_TYPE_BUFFER,
@@ -105,7 +104,7 @@ mxm_shadow_dsm(struct nvkm_mxm *mxm, u8 version)
* unless you pass in exactly the version it supports..
*/
rev = (version & 0xf0) << 4 | (version & 0x0f);
- obj = acpi_evaluate_dsm(handle, muid, rev, 0x00000010, &argv4);
+ obj = acpi_evaluate_dsm(handle, &muid, rev, 0x00000010, &argv4);
if (!obj) {
nvkm_debug(subdev, "DSM MXMS failed\n");
return false;
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/timer/base.c b/drivers/gpu/drm/nouveau/nvkm/subdev/timer/base.c
index f2a86eae0a0d..2437f7d41ca2 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/timer/base.c
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/timer/base.c
@@ -50,7 +50,8 @@ nvkm_timer_alarm_trigger(struct nvkm_timer *tmr)
/* Move to completed list. We'll drop the lock before
* executing the callback so it can reschedule itself.
*/
- list_move_tail(&alarm->head, &exec);
+ list_del_init(&alarm->head);
+ list_add(&alarm->exec, &exec);
}
/* Shut down interrupt if no more pending alarms. */
@@ -59,8 +60,8 @@ nvkm_timer_alarm_trigger(struct nvkm_timer *tmr)
spin_unlock_irqrestore(&tmr->lock, flags);
/* Execute completed callbacks. */
- list_for_each_entry_safe(alarm, atemp, &exec, head) {
- list_del_init(&alarm->head);
+ list_for_each_entry_safe(alarm, atemp, &exec, exec) {
+ list_del(&alarm->exec);
alarm->func(alarm);
}
}
diff --git a/drivers/gpu/drm/qxl/qxl_display.c b/drivers/gpu/drm/qxl/qxl_display.c
index 058340a002c2..4a340efd8ba6 100644
--- a/drivers/gpu/drm/qxl/qxl_display.c
+++ b/drivers/gpu/drm/qxl/qxl_display.c
@@ -575,8 +575,6 @@ static void qxl_cursor_atomic_update(struct drm_plane *plane,
if (ret)
return;
- cmd = (struct qxl_cursor_cmd *) qxl_release_map(qdev, release);
-
if (fb != old_state->fb) {
obj = to_qxl_framebuffer(fb)->obj;
user_bo = gem_to_qxl_bo(obj);
@@ -614,6 +612,7 @@ static void qxl_cursor_atomic_update(struct drm_plane *plane,
qxl_bo_kunmap(cursor_bo);
qxl_bo_kunmap(user_bo);
+ cmd = (struct qxl_cursor_cmd *) qxl_release_map(qdev, release);
cmd->u.set.visible = 1;
cmd->u.set.shape = qxl_bo_physical_address(qdev,
cursor_bo, 0);
@@ -624,6 +623,7 @@ static void qxl_cursor_atomic_update(struct drm_plane *plane,
if (ret)
goto out_free_release;
+ cmd = (struct qxl_cursor_cmd *) qxl_release_map(qdev, release);
cmd->type = QXL_CURSOR_MOVE;
}
diff --git a/drivers/gpu/drm/radeon/ci_dpm.c b/drivers/gpu/drm/radeon/ci_dpm.c
index 7ba450832e6b..ea36dc4dd5d2 100644
--- a/drivers/gpu/drm/radeon/ci_dpm.c
+++ b/drivers/gpu/drm/radeon/ci_dpm.c
@@ -776,6 +776,12 @@ bool ci_dpm_vblank_too_short(struct radeon_device *rdev)
u32 vblank_time = r600_dpm_get_vblank_time(rdev);
u32 switch_limit = pi->mem_gddr5 ? 450 : 300;
+ /* disable mclk switching if the refresh is >120Hz, even if the
+ * blanking period would allow it
+ */
+ if (r600_dpm_get_vrefresh(rdev) > 120)
+ return true;
+
if (vblank_time < switch_limit)
return true;
else
diff --git a/drivers/gpu/drm/radeon/cik.c b/drivers/gpu/drm/radeon/cik.c
index ccebe0f8d2e1..ca44233ceacc 100644
--- a/drivers/gpu/drm/radeon/cik.c
+++ b/drivers/gpu/drm/radeon/cik.c
@@ -7401,7 +7401,7 @@ static inline void cik_irq_ack(struct radeon_device *rdev)
WREG32(DC_HPD5_INT_CONTROL, tmp);
}
if (rdev->irq.stat_regs.cik.disp_int_cont5 & DC_HPD6_INTERRUPT) {
- tmp = RREG32(DC_HPD5_INT_CONTROL);
+ tmp = RREG32(DC_HPD6_INT_CONTROL);
tmp |= DC_HPDx_INT_ACK;
WREG32(DC_HPD6_INT_CONTROL, tmp);
}
@@ -7431,7 +7431,7 @@ static inline void cik_irq_ack(struct radeon_device *rdev)
WREG32(DC_HPD5_INT_CONTROL, tmp);
}
if (rdev->irq.stat_regs.cik.disp_int_cont5 & DC_HPD6_RX_INTERRUPT) {
- tmp = RREG32(DC_HPD5_INT_CONTROL);
+ tmp = RREG32(DC_HPD6_INT_CONTROL);
tmp |= DC_HPDx_RX_INT_ACK;
WREG32(DC_HPD6_INT_CONTROL, tmp);
}
@@ -9267,8 +9267,11 @@ static void dce8_program_watermarks(struct radeon_device *rdev,
u32 tmp, wm_mask;
if (radeon_crtc->base.enabled && num_heads && mode) {
- active_time = 1000000UL * (u32)mode->crtc_hdisplay / (u32)mode->clock;
- line_time = min((u32) (1000000UL * (u32)mode->crtc_htotal / (u32)mode->clock), (u32)65535);
+ active_time = (u32) div_u64((u64)mode->crtc_hdisplay * 1000000,
+ (u32)mode->clock);
+ line_time = (u32) div_u64((u64)mode->crtc_htotal * 1000000,
+ (u32)mode->clock);
+ line_time = min(line_time, (u32)65535);
/* watermark for high clocks */
if ((rdev->pm.pm_method == PM_METHOD_DPM) &&
diff --git a/drivers/gpu/drm/radeon/evergreen.c b/drivers/gpu/drm/radeon/evergreen.c
index f130ec41ee4b..534637203e70 100644
--- a/drivers/gpu/drm/radeon/evergreen.c
+++ b/drivers/gpu/drm/radeon/evergreen.c
@@ -2266,8 +2266,11 @@ static void evergreen_program_watermarks(struct radeon_device *rdev,
fixed20_12 a, b, c;
if (radeon_crtc->base.enabled && num_heads && mode) {
- active_time = 1000000UL * (u32)mode->crtc_hdisplay / (u32)mode->clock;
- line_time = min((u32) (1000000UL * (u32)mode->crtc_htotal / (u32)mode->clock), (u32)65535);
+ active_time = (u32) div_u64((u64)mode->crtc_hdisplay * 1000000,
+ (u32)mode->clock);
+ line_time = (u32) div_u64((u64)mode->crtc_htotal * 1000000,
+ (u32)mode->clock);
+ line_time = min(line_time, (u32)65535);
priority_a_cnt = 0;
priority_b_cnt = 0;
dram_channels = evergreen_get_number_of_dram_channels(rdev);
@@ -4927,7 +4930,7 @@ static void evergreen_irq_ack(struct radeon_device *rdev)
WREG32(DC_HPD5_INT_CONTROL, tmp);
}
if (rdev->irq.stat_regs.evergreen.disp_int_cont5 & DC_HPD6_INTERRUPT) {
- tmp = RREG32(DC_HPD5_INT_CONTROL);
+ tmp = RREG32(DC_HPD6_INT_CONTROL);
tmp |= DC_HPDx_INT_ACK;
WREG32(DC_HPD6_INT_CONTROL, tmp);
}
@@ -4958,7 +4961,7 @@ static void evergreen_irq_ack(struct radeon_device *rdev)
WREG32(DC_HPD5_INT_CONTROL, tmp);
}
if (rdev->irq.stat_regs.evergreen.disp_int_cont5 & DC_HPD6_RX_INTERRUPT) {
- tmp = RREG32(DC_HPD5_INT_CONTROL);
+ tmp = RREG32(DC_HPD6_INT_CONTROL);
tmp |= DC_HPDx_RX_INT_ACK;
WREG32(DC_HPD6_INT_CONTROL, tmp);
}
diff --git a/drivers/gpu/drm/radeon/r600.c b/drivers/gpu/drm/radeon/r600.c
index 0a085176e79b..e06e2d8feab3 100644
--- a/drivers/gpu/drm/radeon/r600.c
+++ b/drivers/gpu/drm/radeon/r600.c
@@ -3988,7 +3988,7 @@ static void r600_irq_ack(struct radeon_device *rdev)
WREG32(DC_HPD5_INT_CONTROL, tmp);
}
if (rdev->irq.stat_regs.r600.disp_int_cont2 & DC_HPD6_INTERRUPT) {
- tmp = RREG32(DC_HPD5_INT_CONTROL);
+ tmp = RREG32(DC_HPD6_INT_CONTROL);
tmp |= DC_HPDx_INT_ACK;
WREG32(DC_HPD6_INT_CONTROL, tmp);
}
diff --git a/drivers/gpu/drm/radeon/radeon.h b/drivers/gpu/drm/radeon/radeon.h
index c1c8e2208a21..e562a78510ff 100644
--- a/drivers/gpu/drm/radeon/radeon.h
+++ b/drivers/gpu/drm/radeon/radeon.h
@@ -375,7 +375,7 @@ struct radeon_fence {
unsigned ring;
bool is_vm_update;
- wait_queue_t fence_wake;
+ wait_queue_entry_t fence_wake;
};
int radeon_fence_driver_start_ring(struct radeon_device *rdev, int ring);
diff --git a/drivers/gpu/drm/radeon/radeon_combios.c b/drivers/gpu/drm/radeon/radeon_combios.c
index 432480ff9d22..3178ba0c537c 100644
--- a/drivers/gpu/drm/radeon/radeon_combios.c
+++ b/drivers/gpu/drm/radeon/radeon_combios.c
@@ -3393,6 +3393,13 @@ void radeon_combios_asic_init(struct drm_device *dev)
rdev->pdev->subsystem_vendor == 0x103c &&
rdev->pdev->subsystem_device == 0x280a)
return;
+ /* quirk for rs4xx Toshiba Sattellite L20-183 latop to make it resume
+ * - it hangs on resume inside the dynclk 1 table.
+ */
+ if (rdev->family == CHIP_RS400 &&
+ rdev->pdev->subsystem_vendor == 0x1179 &&
+ rdev->pdev->subsystem_device == 0xff31)
+ return;
/* DYN CLK 1 */
table = combios_get_table_offset(dev, COMBIOS_DYN_CLK_1_TABLE);
diff --git a/drivers/gpu/drm/radeon/radeon_device.c b/drivers/gpu/drm/radeon/radeon_device.c
index 6ecf42783d4b..0a6444d72000 100644
--- a/drivers/gpu/drm/radeon/radeon_device.c
+++ b/drivers/gpu/drm/radeon/radeon_device.c
@@ -136,6 +136,10 @@ static struct radeon_px_quirk radeon_px_quirk_list[] = {
* https://bugzilla.kernel.org/show_bug.cgi?id=51381
*/
{ PCI_VENDOR_ID_ATI, 0x6840, 0x1043, 0x2122, RADEON_PX_QUIRK_DISABLE_PX },
+ /* Asus K53TK laptop with AMD A6-3420M APU and Radeon 7670m GPU
+ * https://bugs.freedesktop.org/show_bug.cgi?id=101491
+ */
+ { PCI_VENDOR_ID_ATI, 0x6741, 0x1043, 0x2122, RADEON_PX_QUIRK_DISABLE_PX },
/* macbook pro 8.2 */
{ PCI_VENDOR_ID_ATI, 0x6741, PCI_VENDOR_ID_APPLE, 0x00e2, RADEON_PX_QUIRK_LONG_WAKEUP },
{ 0, 0, 0, 0, 0 },
diff --git a/drivers/gpu/drm/radeon/radeon_fence.c b/drivers/gpu/drm/radeon/radeon_fence.c
index ef09f0a63754..e86f2bd38410 100644
--- a/drivers/gpu/drm/radeon/radeon_fence.c
+++ b/drivers/gpu/drm/radeon/radeon_fence.c
@@ -158,7 +158,7 @@ int radeon_fence_emit(struct radeon_device *rdev,
* for the fence locking itself, so unlocked variants are used for
* fence_signal, and remove_wait_queue.
*/
-static int radeon_fence_check_signaled(wait_queue_t *wait, unsigned mode, int flags, void *key)
+static int radeon_fence_check_signaled(wait_queue_entry_t *wait, unsigned mode, int flags, void *key)
{
struct radeon_fence *fence;
u64 seq;
diff --git a/drivers/gpu/drm/radeon/radeon_kms.c b/drivers/gpu/drm/radeon/radeon_kms.c
index e3e7cb1d10a2..4761f27f2ca2 100644
--- a/drivers/gpu/drm/radeon/radeon_kms.c
+++ b/drivers/gpu/drm/radeon/radeon_kms.c
@@ -116,7 +116,7 @@ int radeon_driver_load_kms(struct drm_device *dev, unsigned long flags)
if ((radeon_runtime_pm != 0) &&
radeon_has_atpx() &&
((flags & RADEON_IS_IGP) == 0) &&
- !pci_is_thunderbolt_attached(rdev->pdev))
+ !pci_is_thunderbolt_attached(dev->pdev))
flags |= RADEON_IS_PX;
/* radeon_device_init should report only fatal error
diff --git a/drivers/gpu/drm/radeon/radeon_uvd.c b/drivers/gpu/drm/radeon/radeon_uvd.c
index 7431eb4a11b7..d34d1cf33895 100644
--- a/drivers/gpu/drm/radeon/radeon_uvd.c
+++ b/drivers/gpu/drm/radeon/radeon_uvd.c
@@ -621,7 +621,7 @@ static int radeon_uvd_cs_reloc(struct radeon_cs_parser *p,
}
/* TODO: is this still necessary on NI+ ? */
- if ((cmd == 0 || cmd == 1 || cmd == 0x3) &&
+ if ((cmd == 0 || cmd == 0x3) &&
(start >> 28) != (p->rdev->uvd.gpu_addr >> 28)) {
DRM_ERROR("msg/fb buffer %LX-%LX out of 256MB segment!\n",
start, end);
diff --git a/drivers/gpu/drm/radeon/si.c b/drivers/gpu/drm/radeon/si.c
index ceee87f029d9..5303f25d5280 100644
--- a/drivers/gpu/drm/radeon/si.c
+++ b/drivers/gpu/drm/radeon/si.c
@@ -2284,8 +2284,11 @@ static void dce6_program_watermarks(struct radeon_device *rdev,
fixed20_12 a, b, c;
if (radeon_crtc->base.enabled && num_heads && mode) {
- active_time = 1000000UL * (u32)mode->crtc_hdisplay / (u32)mode->clock;
- line_time = min((u32) (1000000UL * (u32)mode->crtc_htotal / (u32)mode->clock), (u32)65535);
+ active_time = (u32) div_u64((u64)mode->crtc_hdisplay * 1000000,
+ (u32)mode->clock);
+ line_time = (u32) div_u64((u64)mode->crtc_htotal * 1000000,
+ (u32)mode->clock);
+ line_time = min(line_time, (u32)65535);
priority_a_cnt = 0;
priority_b_cnt = 0;
@@ -6317,7 +6320,7 @@ static inline void si_irq_ack(struct radeon_device *rdev)
WREG32(DC_HPD5_INT_CONTROL, tmp);
}
if (rdev->irq.stat_regs.evergreen.disp_int_cont5 & DC_HPD6_INTERRUPT) {
- tmp = RREG32(DC_HPD5_INT_CONTROL);
+ tmp = RREG32(DC_HPD6_INT_CONTROL);
tmp |= DC_HPDx_INT_ACK;
WREG32(DC_HPD6_INT_CONTROL, tmp);
}
@@ -6348,7 +6351,7 @@ static inline void si_irq_ack(struct radeon_device *rdev)
WREG32(DC_HPD5_INT_CONTROL, tmp);
}
if (rdev->irq.stat_regs.evergreen.disp_int_cont5 & DC_HPD6_RX_INTERRUPT) {
- tmp = RREG32(DC_HPD5_INT_CONTROL);
+ tmp = RREG32(DC_HPD6_INT_CONTROL);
tmp |= DC_HPDx_RX_INT_ACK;
WREG32(DC_HPD6_INT_CONTROL, tmp);
}
diff --git a/drivers/gpu/drm/rockchip/analogix_dp-rockchip.c b/drivers/gpu/drm/rockchip/analogix_dp-rockchip.c
index d8fa7a9c9240..ce5f2d1f9994 100644
--- a/drivers/gpu/drm/rockchip/analogix_dp-rockchip.c
+++ b/drivers/gpu/drm/rockchip/analogix_dp-rockchip.c
@@ -245,8 +245,6 @@ rockchip_dp_drm_encoder_atomic_check(struct drm_encoder *encoder,
struct drm_connector_state *conn_state)
{
struct rockchip_crtc_state *s = to_rockchip_crtc_state(crtc_state);
- struct rockchip_dp_device *dp = to_dp(encoder);
- int ret;
/*
* The hardware IC designed that VOP must output the RGB10 video
@@ -258,16 +256,6 @@ rockchip_dp_drm_encoder_atomic_check(struct drm_encoder *encoder,
s->output_mode = ROCKCHIP_OUT_MODE_AAAA;
s->output_type = DRM_MODE_CONNECTOR_eDP;
- if (dp->data->chip_type == RK3399_EDP) {
- /*
- * For RK3399, VOP Lit must code the out mode to RGB888,
- * VOP Big must code the out mode to RGB10.
- */
- ret = drm_of_encoder_active_endpoint_id(dp->dev->of_node,
- encoder);
- if (ret > 0)
- s->output_mode = ROCKCHIP_OUT_MODE_P888;
- }
return 0;
}
diff --git a/drivers/gpu/drm/rockchip/cdn-dp-core.c b/drivers/gpu/drm/rockchip/cdn-dp-core.c
index a2169dd3d26b..14fa1f8351e8 100644
--- a/drivers/gpu/drm/rockchip/cdn-dp-core.c
+++ b/drivers/gpu/drm/rockchip/cdn-dp-core.c
@@ -615,7 +615,6 @@ static void cdn_dp_encoder_enable(struct drm_encoder *encoder)
{
struct cdn_dp_device *dp = encoder_to_dp(encoder);
int ret, val;
- struct rockchip_crtc_state *state;
ret = drm_of_encoder_active_endpoint_id(dp->dev->of_node, encoder);
if (ret < 0) {
@@ -625,14 +624,10 @@ static void cdn_dp_encoder_enable(struct drm_encoder *encoder)
DRM_DEV_DEBUG_KMS(dp->dev, "vop %s output to cdn-dp\n",
(ret) ? "LIT" : "BIG");
- state = to_rockchip_crtc_state(encoder->crtc->state);
- if (ret) {
+ if (ret)
val = DP_SEL_VOP_LIT | (DP_SEL_VOP_LIT << 16);
- state->output_mode = ROCKCHIP_OUT_MODE_P888;
- } else {
+ else
val = DP_SEL_VOP_LIT << 16;
- state->output_mode = ROCKCHIP_OUT_MODE_AAAA;
- }
ret = cdn_dp_grf_write(dp, GRF_SOC_CON9, val);
if (ret)
diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
index 3f7a82d1e095..45589d6ce65e 100644
--- a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
+++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
@@ -875,6 +875,7 @@ static bool vop_crtc_mode_fixup(struct drm_crtc *crtc,
static void vop_crtc_enable(struct drm_crtc *crtc)
{
struct vop *vop = to_vop(crtc);
+ const struct vop_data *vop_data = vop->data;
struct rockchip_crtc_state *s = to_rockchip_crtc_state(crtc->state);
struct drm_display_mode *adjusted_mode = &crtc->state->adjusted_mode;
u16 hsync_len = adjusted_mode->hsync_end - adjusted_mode->hsync_start;
@@ -967,6 +968,13 @@ static void vop_crtc_enable(struct drm_crtc *crtc)
DRM_DEV_ERROR(vop->dev, "unsupported connector_type [%d]\n",
s->output_type);
}
+
+ /*
+ * if vop is not support RGB10 output, need force RGB10 to RGB888.
+ */
+ if (s->output_mode == ROCKCHIP_OUT_MODE_AAAA &&
+ !(vop_data->feature & VOP_FEATURE_OUTPUT_RGB10))
+ s->output_mode = ROCKCHIP_OUT_MODE_P888;
VOP_CTRL_SET(vop, out_mode, s->output_mode);
VOP_CTRL_SET(vop, htotal_pw, (htotal << 16) | hsync_len);
diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop.h b/drivers/gpu/drm/rockchip/rockchip_drm_vop.h
index 5a4faa85dbd2..9979fd0c2282 100644
--- a/drivers/gpu/drm/rockchip/rockchip_drm_vop.h
+++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop.h
@@ -142,6 +142,9 @@ struct vop_data {
const struct vop_intr *intr;
const struct vop_win_data *win;
unsigned int win_size;
+
+#define VOP_FEATURE_OUTPUT_RGB10 BIT(0)
+ u64 feature;
};
/* interrupt define */
diff --git a/drivers/gpu/drm/rockchip/rockchip_vop_reg.c b/drivers/gpu/drm/rockchip/rockchip_vop_reg.c
index 0da44442aab0..bafd698a28b1 100644
--- a/drivers/gpu/drm/rockchip/rockchip_vop_reg.c
+++ b/drivers/gpu/drm/rockchip/rockchip_vop_reg.c
@@ -275,6 +275,7 @@ static const struct vop_intr rk3288_vop_intr = {
static const struct vop_data rk3288_vop = {
.init_table = rk3288_init_reg_table,
.table_size = ARRAY_SIZE(rk3288_init_reg_table),
+ .feature = VOP_FEATURE_OUTPUT_RGB10,
.intr = &rk3288_vop_intr,
.ctrl = &rk3288_ctrl_data,
.win = rk3288_vop_win_data,
@@ -343,6 +344,7 @@ static const struct vop_reg_data rk3399_init_reg_table[] = {
static const struct vop_data rk3399_vop_big = {
.init_table = rk3399_init_reg_table,
.table_size = ARRAY_SIZE(rk3399_init_reg_table),
+ .feature = VOP_FEATURE_OUTPUT_RGB10,
.intr = &rk3399_vop_intr,
.ctrl = &rk3399_ctrl_data,
/*
diff --git a/drivers/gpu/drm/tegra/drm.c b/drivers/gpu/drm/tegra/drm.c
index 9a1e34e48f64..81f86a67c10d 100644
--- a/drivers/gpu/drm/tegra/drm.c
+++ b/drivers/gpu/drm/tegra/drm.c
@@ -451,18 +451,6 @@ fail:
#ifdef CONFIG_DRM_TEGRA_STAGING
-static struct tegra_drm_context *
-tegra_drm_file_get_context(struct tegra_drm_file *file, u32 id)
-{
- struct tegra_drm_context *context;
-
- mutex_lock(&file->lock);
- context = idr_find(&file->contexts, id);
- mutex_unlock(&file->lock);
-
- return context;
-}
-
static int tegra_gem_create(struct drm_device *drm, void *data,
struct drm_file *file)
{
@@ -551,7 +539,7 @@ static int tegra_client_open(struct tegra_drm_file *fpriv,
if (err < 0)
return err;
- err = idr_alloc(&fpriv->contexts, context, 0, 0, GFP_KERNEL);
+ err = idr_alloc(&fpriv->contexts, context, 1, 0, GFP_KERNEL);
if (err < 0) {
client->ops->close_channel(context);
return err;
@@ -606,7 +594,7 @@ static int tegra_close_channel(struct drm_device *drm, void *data,
mutex_lock(&fpriv->lock);
- context = tegra_drm_file_get_context(fpriv, args->context);
+ context = idr_find(&fpriv->contexts, args->context);
if (!context) {
err = -EINVAL;
goto unlock;
@@ -631,7 +619,7 @@ static int tegra_get_syncpt(struct drm_device *drm, void *data,
mutex_lock(&fpriv->lock);
- context = tegra_drm_file_get_context(fpriv, args->context);
+ context = idr_find(&fpriv->contexts, args->context);
if (!context) {
err = -ENODEV;
goto unlock;
@@ -660,7 +648,7 @@ static int tegra_submit(struct drm_device *drm, void *data,
mutex_lock(&fpriv->lock);
- context = tegra_drm_file_get_context(fpriv, args->context);
+ context = idr_find(&fpriv->contexts, args->context);
if (!context) {
err = -ENODEV;
goto unlock;
@@ -685,7 +673,7 @@ static int tegra_get_syncpt_base(struct drm_device *drm, void *data,
mutex_lock(&fpriv->lock);
- context = tegra_drm_file_get_context(fpriv, args->context);
+ context = idr_find(&fpriv->contexts, args->context);
if (!context) {
err = -ENODEV;
goto unlock;
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_cmdbuf_res.c b/drivers/gpu/drm/vmwgfx/vmwgfx_cmdbuf_res.c
index 13db8a2851ed..1f013d45c9e9 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_cmdbuf_res.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_cmdbuf_res.c
@@ -321,6 +321,7 @@ void vmw_cmdbuf_res_man_destroy(struct vmw_cmdbuf_res_manager *man)
list_for_each_entry_safe(entry, next, &man->list, head)
vmw_cmdbuf_res_free(man, entry);
+ drm_ht_remove(&man->resources);
kfree(man);
}
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h
index 130d51c5ec6a..4b948fba9eec 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h
@@ -41,9 +41,9 @@
#include <drm/ttm/ttm_module.h>
#include "vmwgfx_fence.h"
-#define VMWGFX_DRIVER_DATE "20170221"
+#define VMWGFX_DRIVER_DATE "20170607"
#define VMWGFX_DRIVER_MAJOR 2
-#define VMWGFX_DRIVER_MINOR 12
+#define VMWGFX_DRIVER_MINOR 13
#define VMWGFX_DRIVER_PATCHLEVEL 0
#define VMWGFX_FILE_PAGE_OFFSET 0x00100000
#define VMWGFX_FIFO_STATIC_SIZE (1024*1024)
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_fifo.c b/drivers/gpu/drm/vmwgfx/vmwgfx_fifo.c
index b6a0806b06bf..a1c68e6a689e 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_fifo.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_fifo.c
@@ -368,6 +368,8 @@ static void *vmw_local_fifo_reserve(struct vmw_private *dev_priv,
return fifo_state->static_buffer;
else {
fifo_state->dynamic_buffer = vmalloc(bytes);
+ if (!fifo_state->dynamic_buffer)
+ goto out_err;
return fifo_state->dynamic_buffer;
}
}
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c
index ef9f3a2a4030..1d2db5d912b0 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c
@@ -274,108 +274,6 @@ void vmw_kms_cursor_post_execbuf(struct vmw_private *dev_priv)
}
-
-/**
- * vmw_du_cursor_plane_update() - Update cursor image and location
- *
- * @plane: plane object to update
- * @crtc: owning CRTC of @plane
- * @fb: framebuffer to flip onto plane
- * @crtc_x: x offset of plane on crtc
- * @crtc_y: y offset of plane on crtc
- * @crtc_w: width of plane rectangle on crtc
- * @crtc_h: height of plane rectangle on crtc
- * @src_x: Not used
- * @src_y: Not used
- * @src_w: Not used
- * @src_h: Not used
- *
- *
- * RETURNS:
- * Zero on success, error code on failure
- */
-int vmw_du_cursor_plane_update(struct drm_plane *plane,
- struct drm_crtc *crtc,
- struct drm_framebuffer *fb,
- int crtc_x, int crtc_y,
- unsigned int crtc_w,
- unsigned int crtc_h,
- uint32_t src_x, uint32_t src_y,
- uint32_t src_w, uint32_t src_h)
-{
- struct vmw_private *dev_priv = vmw_priv(crtc->dev);
- struct vmw_display_unit *du = vmw_crtc_to_du(crtc);
- struct vmw_surface *surface = NULL;
- struct vmw_dma_buffer *dmabuf = NULL;
- s32 hotspot_x, hotspot_y;
- int ret;
-
- hotspot_x = du->hotspot_x + fb->hot_x;
- hotspot_y = du->hotspot_y + fb->hot_y;
-
- /* A lot of the code assumes this */
- if (crtc_w != 64 || crtc_h != 64) {
- ret = -EINVAL;
- goto out;
- }
-
- if (vmw_framebuffer_to_vfb(fb)->dmabuf)
- dmabuf = vmw_framebuffer_to_vfbd(fb)->buffer;
- else
- surface = vmw_framebuffer_to_vfbs(fb)->surface;
-
- if (surface && !surface->snooper.image) {
- DRM_ERROR("surface not suitable for cursor\n");
- ret = -EINVAL;
- goto out;
- }
-
- /* setup new image */
- ret = 0;
- if (surface) {
- /* vmw_user_surface_lookup takes one reference */
- du->cursor_surface = surface;
-
- du->cursor_age = du->cursor_surface->snooper.age;
-
- ret = vmw_cursor_update_image(dev_priv, surface->snooper.image,
- 64, 64, hotspot_x, hotspot_y);
- } else if (dmabuf) {
- /* vmw_user_surface_lookup takes one reference */
- du->cursor_dmabuf = dmabuf;
-
- ret = vmw_cursor_update_dmabuf(dev_priv, dmabuf, crtc_w, crtc_h,
- hotspot_x, hotspot_y);
- } else {
- vmw_cursor_update_position(dev_priv, false, 0, 0);
- goto out;
- }
-
- if (!ret) {
- du->cursor_x = crtc_x + du->set_gui_x;
- du->cursor_y = crtc_y + du->set_gui_y;
-
- vmw_cursor_update_position(dev_priv, true,
- du->cursor_x + hotspot_x,
- du->cursor_y + hotspot_y);
- }
-
-out:
- return ret;
-}
-
-
-int vmw_du_cursor_plane_disable(struct drm_plane *plane)
-{
- if (plane->fb) {
- drm_framebuffer_unreference(plane->fb);
- plane->fb = NULL;
- }
-
- return -EINVAL;
-}
-
-
void vmw_du_cursor_plane_destroy(struct drm_plane *plane)
{
vmw_cursor_update_position(plane->dev->dev_private, false, 0, 0);
@@ -473,18 +371,6 @@ vmw_du_cursor_plane_prepare_fb(struct drm_plane *plane,
void
-vmw_du_cursor_plane_atomic_disable(struct drm_plane *plane,
- struct drm_plane_state *old_state)
-{
- struct drm_crtc *crtc = plane->state->crtc ?: old_state->crtc;
- struct vmw_private *dev_priv = vmw_priv(crtc->dev);
-
- drm_atomic_set_fb_for_plane(plane->state, NULL);
- vmw_cursor_update_position(dev_priv, false, 0, 0);
-}
-
-
-void
vmw_du_cursor_plane_atomic_update(struct drm_plane *plane,
struct drm_plane_state *old_state)
{
@@ -1498,6 +1384,7 @@ vmw_kms_new_framebuffer(struct vmw_private *dev_priv,
*/
if (vmw_kms_srf_ok(dev_priv, mode_cmd->width, mode_cmd->height) &&
dmabuf && only_2d &&
+ mode_cmd->width > 64 && /* Don't create a proxy for cursor */
dev_priv->active_display_unit == vmw_du_screen_target) {
ret = vmw_create_dmabuf_proxy(dev_priv->dev, mode_cmd,
dmabuf, &surface);
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.h b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.h
index 13f2f1d2818a..5f8d678ae675 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.h
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.h
@@ -256,10 +256,6 @@ int vmw_du_crtc_gamma_set(struct drm_crtc *crtc,
u16 *r, u16 *g, u16 *b,
uint32_t size,
struct drm_modeset_acquire_ctx *ctx);
-int vmw_du_crtc_cursor_set2(struct drm_crtc *crtc, struct drm_file *file_priv,
- uint32_t handle, uint32_t width, uint32_t height,
- int32_t hot_x, int32_t hot_y);
-int vmw_du_crtc_cursor_move(struct drm_crtc *crtc, int x, int y);
int vmw_du_connector_set_property(struct drm_connector *connector,
struct drm_property *property,
uint64_t val);
@@ -339,15 +335,6 @@ void vmw_kms_create_implicit_placement_property(struct vmw_private *dev_priv,
/* Universal Plane Helpers */
void vmw_du_primary_plane_destroy(struct drm_plane *plane);
void vmw_du_cursor_plane_destroy(struct drm_plane *plane);
-int vmw_du_cursor_plane_disable(struct drm_plane *plane);
-int vmw_du_cursor_plane_update(struct drm_plane *plane,
- struct drm_crtc *crtc,
- struct drm_framebuffer *fb,
- int crtc_x, int crtc_y,
- unsigned int crtc_w,
- unsigned int crtc_h,
- uint32_t src_x, uint32_t src_y,
- uint32_t src_w, uint32_t src_h);
/* Atomic Helpers */
int vmw_du_primary_plane_atomic_check(struct drm_plane *plane,
@@ -356,8 +343,6 @@ int vmw_du_cursor_plane_atomic_check(struct drm_plane *plane,
struct drm_plane_state *state);
void vmw_du_cursor_plane_atomic_update(struct drm_plane *plane,
struct drm_plane_state *old_state);
-void vmw_du_cursor_plane_atomic_disable(struct drm_plane *plane,
- struct drm_plane_state *old_state);
int vmw_du_cursor_plane_prepare_fb(struct drm_plane *plane,
struct drm_plane_state *new_state);
void vmw_du_plane_cleanup_fb(struct drm_plane *plane,
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_stdu.c b/drivers/gpu/drm/vmwgfx/vmwgfx_stdu.c
index bad31bdf09b6..50be1f034f9e 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_stdu.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_stdu.c
@@ -56,6 +56,8 @@ enum stdu_content_type {
* @right: Right side of bounding box.
* @top: Top side of bounding box.
* @bottom: Bottom side of bounding box.
+ * @fb_left: Left side of the framebuffer/content bounding box
+ * @fb_top: Top of the framebuffer/content bounding box
* @buf: DMA buffer when DMA-ing between buffer and screen targets.
* @sid: Surface ID when copying between surface and screen targets.
*/
@@ -63,6 +65,7 @@ struct vmw_stdu_dirty {
struct vmw_kms_dirty base;
SVGA3dTransferType transfer;
s32 left, right, top, bottom;
+ s32 fb_left, fb_top;
u32 pitch;
union {
struct vmw_dma_buffer *buf;
@@ -647,7 +650,7 @@ static void vmw_stdu_dmabuf_fifo_commit(struct vmw_kms_dirty *dirty)
*
* @dirty: The closure structure.
*
- * This function calculates the bounding box for all the incoming clips
+ * This function calculates the bounding box for all the incoming clips.
*/
static void vmw_stdu_dmabuf_cpu_clip(struct vmw_kms_dirty *dirty)
{
@@ -656,11 +659,19 @@ static void vmw_stdu_dmabuf_cpu_clip(struct vmw_kms_dirty *dirty)
dirty->num_hits = 1;
- /* Calculate bounding box */
+ /* Calculate destination bounding box */
ddirty->left = min_t(s32, ddirty->left, dirty->unit_x1);
ddirty->top = min_t(s32, ddirty->top, dirty->unit_y1);
ddirty->right = max_t(s32, ddirty->right, dirty->unit_x2);
ddirty->bottom = max_t(s32, ddirty->bottom, dirty->unit_y2);
+
+ /*
+ * Calculate content bounding box. We only need the top-left
+ * coordinate because width and height will be the same as the
+ * destination bounding box above
+ */
+ ddirty->fb_left = min_t(s32, ddirty->fb_left, dirty->fb_x);
+ ddirty->fb_top = min_t(s32, ddirty->fb_top, dirty->fb_y);
}
@@ -697,11 +708,11 @@ static void vmw_stdu_dmabuf_cpu_commit(struct vmw_kms_dirty *dirty)
/* Assume we are blitting from Host (display_srf) to Guest (dmabuf) */
src_pitch = stdu->display_srf->base_size.width * stdu->cpp;
src = ttm_kmap_obj_virtual(&stdu->host_map, &not_used);
- src += dirty->unit_y1 * src_pitch + dirty->unit_x1 * stdu->cpp;
+ src += ddirty->top * src_pitch + ddirty->left * stdu->cpp;
dst_pitch = ddirty->pitch;
dst = ttm_kmap_obj_virtual(&stdu->guest_map, &not_used);
- dst += dirty->fb_y * dst_pitch + dirty->fb_x * stdu->cpp;
+ dst += ddirty->fb_top * dst_pitch + ddirty->fb_left * stdu->cpp;
/* Figure out the real direction */
@@ -760,7 +771,7 @@ static void vmw_stdu_dmabuf_cpu_commit(struct vmw_kms_dirty *dirty)
}
out_cleanup:
- ddirty->left = ddirty->top = S32_MAX;
+ ddirty->left = ddirty->top = ddirty->fb_left = ddirty->fb_top = S32_MAX;
ddirty->right = ddirty->bottom = S32_MIN;
}
@@ -812,6 +823,7 @@ int vmw_kms_stdu_dma(struct vmw_private *dev_priv,
SVGA3D_READ_HOST_VRAM;
ddirty.left = ddirty.top = S32_MAX;
ddirty.right = ddirty.bottom = S32_MIN;
+ ddirty.fb_left = ddirty.fb_top = S32_MAX;
ddirty.pitch = vfb->base.pitches[0];
ddirty.buf = buf;
ddirty.base.fifo_commit = vmw_stdu_dmabuf_fifo_commit;
@@ -1355,6 +1367,11 @@ vmw_stdu_primary_plane_atomic_update(struct drm_plane *plane,
DRM_ERROR("Failed to bind surface to STDU.\n");
else
crtc->primary->fb = plane->state->fb;
+
+ ret = vmw_stdu_update_st(dev_priv, stdu);
+
+ if (ret)
+ DRM_ERROR("Failed to update STDU.\n");
}
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_surface.c b/drivers/gpu/drm/vmwgfx/vmwgfx_surface.c
index 7681341fe32b..6b70bd259953 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_surface.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_surface.c
@@ -1274,11 +1274,14 @@ int vmw_gb_surface_define_ioctl(struct drm_device *dev, void *data,
struct ttm_object_file *tfile = vmw_fpriv(file_priv)->tfile;
int ret;
uint32_t size;
- uint32_t backup_handle;
+ uint32_t backup_handle = 0;
if (req->multisample_count != 0)
return -EINVAL;
+ if (req->mip_levels > DRM_VMW_MAX_MIP_LEVELS)
+ return -EINVAL;
+
if (unlikely(vmw_user_surface_size == 0))
vmw_user_surface_size = ttm_round_pot(sizeof(*user_srf)) +
128;
@@ -1314,12 +1317,16 @@ int vmw_gb_surface_define_ioctl(struct drm_device *dev, void *data,
ret = vmw_user_dmabuf_lookup(tfile, req->buffer_handle,
&res->backup,
&user_srf->backup_base);
- if (ret == 0 && res->backup->base.num_pages * PAGE_SIZE <
- res->backup_size) {
- DRM_ERROR("Surface backup buffer is too small.\n");
- vmw_dmabuf_unreference(&res->backup);
- ret = -EINVAL;
- goto out_unlock;
+ if (ret == 0) {
+ if (res->backup->base.num_pages * PAGE_SIZE <
+ res->backup_size) {
+ DRM_ERROR("Surface backup buffer is too small.\n");
+ vmw_dmabuf_unreference(&res->backup);
+ ret = -EINVAL;
+ goto out_unlock;
+ } else {
+ backup_handle = req->buffer_handle;
+ }
}
} else if (req->drm_surface_flags & drm_vmw_surface_flag_create_buffer)
ret = vmw_user_dmabuf_alloc(dev_priv, tfile,
@@ -1491,7 +1498,7 @@ int vmw_surface_gb_priv_define(struct drm_device *dev,
dev_priv->stdu_max_height);
if (size.width > max_width || size.height > max_height) {
- DRM_ERROR("%ux%u\n, exeeds max surface size %ux%u",
+ DRM_ERROR("%ux%u\n, exceeds max surface size %ux%u",
size.width, size.height,
max_width, max_height);
return -EINVAL;
diff --git a/drivers/gpu/host1x/dev.c b/drivers/gpu/host1x/dev.c
index f05ebb14fa63..ac65f52850a6 100644
--- a/drivers/gpu/host1x/dev.c
+++ b/drivers/gpu/host1x/dev.c
@@ -172,7 +172,7 @@ static int host1x_probe(struct platform_device *pdev)
host->rst = devm_reset_control_get(&pdev->dev, "host1x");
if (IS_ERR(host->rst)) {
- err = PTR_ERR(host->clk);
+ err = PTR_ERR(host->rst);
dev_err(&pdev->dev, "failed to get reset: %d\n", err);
return err;
}
diff --git a/drivers/gpu/ipu-v3/ipu-common.c b/drivers/gpu/ipu-v3/ipu-common.c
index 16d556816b5f..2fb5f432a54c 100644
--- a/drivers/gpu/ipu-v3/ipu-common.c
+++ b/drivers/gpu/ipu-v3/ipu-common.c
@@ -725,15 +725,16 @@ void ipu_set_ic_src_mux(struct ipu_soc *ipu, int csi_id, bool vdi)
spin_lock_irqsave(&ipu->lock, flags);
val = ipu_cm_read(ipu, IPU_CONF);
- if (vdi) {
+ if (vdi)
val |= IPU_CONF_IC_INPUT;
- } else {
+ else
val &= ~IPU_CONF_IC_INPUT;
- if (csi_id == 1)
- val |= IPU_CONF_CSI_SEL;
- else
- val &= ~IPU_CONF_CSI_SEL;
- }
+
+ if (csi_id == 1)
+ val |= IPU_CONF_CSI_SEL;
+ else
+ val &= ~IPU_CONF_CSI_SEL;
+
ipu_cm_write(ipu, val, IPU_CONF);
spin_unlock_irqrestore(&ipu->lock, flags);
diff --git a/drivers/gpu/ipu-v3/ipu-pre.c b/drivers/gpu/ipu-v3/ipu-pre.c
index c55563379e2e..c35f74c83065 100644
--- a/drivers/gpu/ipu-v3/ipu-pre.c
+++ b/drivers/gpu/ipu-v3/ipu-pre.c
@@ -131,8 +131,6 @@ int ipu_pre_get(struct ipu_pre *pre)
if (pre->in_use)
return -EBUSY;
- clk_prepare_enable(pre->clk_axi);
-
/* first get the engine out of reset and remove clock gating */
writel(0, pre->regs + IPU_PRE_CTRL);
@@ -149,12 +147,7 @@ int ipu_pre_get(struct ipu_pre *pre)
void ipu_pre_put(struct ipu_pre *pre)
{
- u32 val;
-
- val = IPU_PRE_CTRL_SFTRST | IPU_PRE_CTRL_CLKGATE;
- writel(val, pre->regs + IPU_PRE_CTRL);
-
- clk_disable_unprepare(pre->clk_axi);
+ writel(IPU_PRE_CTRL_SFTRST, pre->regs + IPU_PRE_CTRL);
pre->in_use = false;
}
@@ -249,6 +242,8 @@ static int ipu_pre_probe(struct platform_device *pdev)
if (!pre->buffer_virt)
return -ENOMEM;
+ clk_prepare_enable(pre->clk_axi);
+
pre->dev = dev;
platform_set_drvdata(pdev, pre);
mutex_lock(&ipu_pre_list_mutex);
@@ -268,6 +263,8 @@ static int ipu_pre_remove(struct platform_device *pdev)
available_pres--;
mutex_unlock(&ipu_pre_list_mutex);
+ clk_disable_unprepare(pre->clk_axi);
+
if (pre->buffer_virt)
gen_pool_free(pre->iram, (unsigned long)pre->buffer_virt,
IPU_PRE_MAX_WIDTH * IPU_PRE_NUM_SCANLINES * 4);
diff --git a/drivers/gpu/vga/vgaarb.c b/drivers/gpu/vga/vgaarb.c
index 92f1452dad57..76875f6299b8 100644
--- a/drivers/gpu/vga/vgaarb.c
+++ b/drivers/gpu/vga/vgaarb.c
@@ -417,7 +417,7 @@ int vga_get(struct pci_dev *pdev, unsigned int rsrc, int interruptible)
{
struct vga_device *vgadev, *conflict;
unsigned long flags;
- wait_queue_t wait;
+ wait_queue_entry_t wait;
int rc = 0;
vga_check_first_use();
diff --git a/drivers/hid/Kconfig b/drivers/hid/Kconfig
index fe40e5e499dd..687705c50794 100644
--- a/drivers/hid/Kconfig
+++ b/drivers/hid/Kconfig
@@ -275,10 +275,12 @@ config HID_EMS_FF
- Trio Linker Plus II
config HID_ELECOM
- tristate "ELECOM BM084 bluetooth mouse"
+ tristate "ELECOM HID devices"
depends on HID
---help---
- Support for the ELECOM BM084 (bluetooth mouse).
+ Support for ELECOM devices:
+ - BM084 Bluetooth Mouse
+ - DEFT Trackball (Wired and wireless)
config HID_ELO
tristate "ELO USB 4000/4500 touchscreen"
diff --git a/drivers/hid/hid-asus.c b/drivers/hid/hid-asus.c
index 16df6cc90235..a6268f2f7408 100644
--- a/drivers/hid/hid-asus.c
+++ b/drivers/hid/hid-asus.c
@@ -69,6 +69,7 @@ MODULE_DESCRIPTION("Asus HID Keyboard and TouchPad");
#define QUIRK_IS_MULTITOUCH BIT(3)
#define QUIRK_NO_CONSUMER_USAGES BIT(4)
#define QUIRK_USE_KBD_BACKLIGHT BIT(5)
+#define QUIRK_T100_KEYBOARD BIT(6)
#define I2C_KEYBOARD_QUIRKS (QUIRK_FIX_NOTEBOOK_REPORT | \
QUIRK_NO_INIT_REPORTS | \
@@ -536,6 +537,8 @@ static void asus_remove(struct hid_device *hdev)
drvdata->kbd_backlight->removed = true;
cancel_work_sync(&drvdata->kbd_backlight->work);
}
+
+ hid_hw_stop(hdev);
}
static __u8 *asus_report_fixup(struct hid_device *hdev, __u8 *rdesc,
@@ -548,6 +551,12 @@ static __u8 *asus_report_fixup(struct hid_device *hdev, __u8 *rdesc,
hid_info(hdev, "Fixing up Asus notebook report descriptor\n");
rdesc[55] = 0xdd;
}
+ if (drvdata->quirks & QUIRK_T100_KEYBOARD &&
+ *rsize == 76 && rdesc[73] == 0x81 && rdesc[74] == 0x01) {
+ hid_info(hdev, "Fixing up Asus T100 keyb report descriptor\n");
+ rdesc[74] &= ~HID_MAIN_ITEM_CONSTANT;
+ }
+
return rdesc;
}
@@ -560,6 +569,9 @@ static const struct hid_device_id asus_devices[] = {
USB_DEVICE_ID_ASUSTEK_ROG_KEYBOARD1) },
{ HID_USB_DEVICE(USB_VENDOR_ID_ASUSTEK,
USB_DEVICE_ID_ASUSTEK_ROG_KEYBOARD2), QUIRK_USE_KBD_BACKLIGHT },
+ { HID_USB_DEVICE(USB_VENDOR_ID_ASUSTEK,
+ USB_DEVICE_ID_ASUSTEK_T100_KEYBOARD),
+ QUIRK_T100_KEYBOARD | QUIRK_NO_CONSUMER_USAGES },
{ }
};
MODULE_DEVICE_TABLE(hid, asus_devices);
diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c
index 9184033a0de6..2241e7913c0d 100644
--- a/drivers/hid/hid-core.c
+++ b/drivers/hid/hid-core.c
@@ -826,11 +826,35 @@ static int hid_scan_report(struct hid_device *hid)
* hid-rmi should take care of them,
* not hid-generic
*/
- if (IS_ENABLED(CONFIG_HID_RMI))
- hid->group = HID_GROUP_RMI;
+ hid->group = HID_GROUP_RMI;
break;
}
+ /* fall back to generic driver in case specific driver doesn't exist */
+ switch (hid->group) {
+ case HID_GROUP_MULTITOUCH_WIN_8:
+ /* fall-through */
+ case HID_GROUP_MULTITOUCH:
+ if (!IS_ENABLED(CONFIG_HID_MULTITOUCH))
+ hid->group = HID_GROUP_GENERIC;
+ break;
+ case HID_GROUP_SENSOR_HUB:
+ if (!IS_ENABLED(CONFIG_HID_SENSOR_HUB))
+ hid->group = HID_GROUP_GENERIC;
+ break;
+ case HID_GROUP_RMI:
+ if (!IS_ENABLED(CONFIG_HID_RMI))
+ hid->group = HID_GROUP_GENERIC;
+ break;
+ case HID_GROUP_WACOM:
+ if (!IS_ENABLED(CONFIG_HID_WACOM))
+ hid->group = HID_GROUP_GENERIC;
+ break;
+ case HID_GROUP_LOGITECH_DJ_DEVICE:
+ if (!IS_ENABLED(CONFIG_HID_LOGITECH_DJ))
+ hid->group = HID_GROUP_GENERIC;
+ break;
+ }
vfree(parser);
return 0;
}
@@ -1763,15 +1787,23 @@ EXPORT_SYMBOL_GPL(hid_disconnect);
* used as a driver. See hid_scan_report().
*/
static const struct hid_device_id hid_have_special_driver[] = {
+#if IS_ENABLED(CONFIG_HID_A4TECH)
{ HID_USB_DEVICE(USB_VENDOR_ID_A4TECH, USB_DEVICE_ID_A4TECH_WCP32PU) },
{ HID_USB_DEVICE(USB_VENDOR_ID_A4TECH, USB_DEVICE_ID_A4TECH_X5_005D) },
{ HID_USB_DEVICE(USB_VENDOR_ID_A4TECH, USB_DEVICE_ID_A4TECH_RP_649) },
+#endif
+#if IS_ENABLED(CONFIG_HID_ACCUTOUCH)
+ { HID_USB_DEVICE(USB_VENDOR_ID_ELO, USB_DEVICE_ID_ELO_ACCUTOUCH_2216) },
+#endif
+#if IS_ENABLED(CONFIG_HID_ACRUX)
{ HID_USB_DEVICE(USB_VENDOR_ID_ACRUX, 0x0802) },
{ HID_USB_DEVICE(USB_VENDOR_ID_ACRUX, 0xf705) },
+#endif
+#if IS_ENABLED(CONFIG_HID_ALPS)
{ HID_DEVICE(HID_BUS_ANY, HID_GROUP_ANY, USB_VENDOR_ID_ALPS_JP, HID_DEVICE_ID_ALPS_U1_DUAL) },
+#endif
+#if IS_ENABLED(CONFIG_HID_APPLE)
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_MIGHTYMOUSE) },
- { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_MAGICMOUSE) },
- { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_MAGICTRACKPAD) },
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_FOUNTAIN_ANSI) },
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_FOUNTAIN_ISO) },
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER_ANSI) },
@@ -1792,11 +1824,6 @@ static const struct hid_device_id hid_have_special_driver[] = {
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER4_HF_ANSI) },
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER4_HF_ISO) },
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER4_HF_JIS) },
- { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_IRCONTROL) },
- { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_IRCONTROL2) },
- { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_IRCONTROL3) },
- { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_IRCONTROL4) },
- { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_IRCONTROL5) },
{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_ANSI) },
{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_ISO) },
{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_JIS) },
@@ -1851,59 +1878,100 @@ static const struct hid_device_id hid_have_special_driver[] = {
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_MAGIC_KEYBOARD_ANSI) },
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_FOUNTAIN_TP_ONLY) },
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER1_TP_ONLY) },
+#endif
+#if IS_ENABLED(CONFIG_HID_APPLEIR)
+ { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_IRCONTROL) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_IRCONTROL2) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_IRCONTROL3) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_IRCONTROL4) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_IRCONTROL5) },
+#endif
+#if IS_ENABLED(CONFIG_HID_ASUS)
{ HID_I2C_DEVICE(USB_VENDOR_ID_ASUSTEK, USB_DEVICE_ID_ASUSTEK_I2C_KEYBOARD) },
{ HID_I2C_DEVICE(USB_VENDOR_ID_ASUSTEK, USB_DEVICE_ID_ASUSTEK_I2C_TOUCHPAD) },
{ HID_USB_DEVICE(USB_VENDOR_ID_ASUSTEK, USB_DEVICE_ID_ASUSTEK_ROG_KEYBOARD1) },
{ HID_USB_DEVICE(USB_VENDOR_ID_ASUSTEK, USB_DEVICE_ID_ASUSTEK_ROG_KEYBOARD2) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_ASUSTEK, USB_DEVICE_ID_ASUSTEK_T100_KEYBOARD) },
+#endif
+#if IS_ENABLED(CONFIG_HID_AUREAL)
{ HID_USB_DEVICE(USB_VENDOR_ID_AUREAL, USB_DEVICE_ID_AUREAL_W01RN) },
+#endif
+#if IS_ENABLED(CONFIG_HID_BELKIN)
{ HID_USB_DEVICE(USB_VENDOR_ID_BELKIN, USB_DEVICE_ID_FLIP_KVM) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_LABTEC, USB_DEVICE_ID_LABTEC_WIRELESS_KEYBOARD) },
+#endif
+#if IS_ENABLED(CONFIG_HID_BETOP_FF)
{ HID_USB_DEVICE(USB_VENDOR_ID_BETOP_2185BFM, 0x2208) },
{ HID_USB_DEVICE(USB_VENDOR_ID_BETOP_2185PC, 0x5506) },
{ HID_USB_DEVICE(USB_VENDOR_ID_BETOP_2185V2PC, 0x1850) },
{ HID_USB_DEVICE(USB_VENDOR_ID_BETOP_2185V2BFM, 0x5500) },
- { HID_USB_DEVICE(USB_VENDOR_ID_BTC, USB_DEVICE_ID_BTC_EMPREX_REMOTE) },
- { HID_USB_DEVICE(USB_VENDOR_ID_BTC, USB_DEVICE_ID_BTC_EMPREX_REMOTE_2) },
+#endif
+#if IS_ENABLED(CONFIG_HID_CHERRY)
{ HID_USB_DEVICE(USB_VENDOR_ID_CHERRY, USB_DEVICE_ID_CHERRY_CYMOTION) },
{ HID_USB_DEVICE(USB_VENDOR_ID_CHERRY, USB_DEVICE_ID_CHERRY_CYMOTION_SOLAR) },
+#endif
+#if IS_ENABLED(CONFIG_HID_CHICONY)
{ HID_USB_DEVICE(USB_VENDOR_ID_CHICONY, USB_DEVICE_ID_CHICONY_TACTICAL_PAD) },
- { HID_USB_DEVICE(USB_VENDOR_ID_CHICONY, USB_DEVICE_ID_CHICONY_WIRELESS) },
{ HID_USB_DEVICE(USB_VENDOR_ID_CHICONY, USB_DEVICE_ID_CHICONY_WIRELESS2) },
{ HID_USB_DEVICE(USB_VENDOR_ID_CHICONY, USB_DEVICE_ID_CHICONY_AK1D) },
{ HID_USB_DEVICE(USB_VENDOR_ID_CHICONY, USB_DEVICE_ID_CHICONY_ACER_SWITCH12) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_JESS, USB_DEVICE_ID_JESS_ZEN_AIO_KBD) },
+#endif
+#if IS_ENABLED(CONFIG_HID_CMEDIA)
+ { HID_USB_DEVICE(USB_VENDOR_ID_CMEDIA, USB_DEVICE_ID_CM6533) },
+#endif
+#if IS_ENABLED(CONFIG_HID_CORSAIR)
{ HID_USB_DEVICE(USB_VENDOR_ID_CORSAIR, USB_DEVICE_ID_CORSAIR_K90) },
{ HID_USB_DEVICE(USB_VENDOR_ID_CORSAIR, USB_DEVICE_ID_CORSAIR_SCIMITAR_PRO_RGB) },
- { HID_USB_DEVICE(USB_VENDOR_ID_CREATIVELABS, USB_DEVICE_ID_PRODIKEYS_PCMIDI) },
+#endif
+#if IS_ENABLED(CONFIG_HID_CP2112)
{ HID_USB_DEVICE(USB_VENDOR_ID_CYGNAL, USB_DEVICE_ID_CYGNAL_CP2112) },
+#endif
+#if IS_ENABLED(CONFIG_HID_CYPRESS)
{ HID_USB_DEVICE(USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_BARCODE_1) },
{ HID_USB_DEVICE(USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_BARCODE_2) },
{ HID_USB_DEVICE(USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_BARCODE_3) },
{ HID_USB_DEVICE(USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_BARCODE_4) },
{ HID_USB_DEVICE(USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_MOUSE) },
- { HID_USB_DEVICE(USB_VENDOR_ID_DELCOM, USB_DEVICE_ID_DELCOM_VISUAL_IND) },
+#endif
+#if IS_ENABLED(CONFIG_HID_DRAGONRISE)
{ HID_USB_DEVICE(USB_VENDOR_ID_DRAGONRISE, 0x0006) },
{ HID_USB_DEVICE(USB_VENDOR_ID_DRAGONRISE, 0x0011) },
-#if IS_ENABLED(CONFIG_HID_MAYFLASH)
- { HID_USB_DEVICE(USB_VENDOR_ID_DRAGONRISE, USB_DEVICE_ID_DRAGONRISE_PS3) },
- { HID_USB_DEVICE(USB_VENDOR_ID_DRAGONRISE, USB_DEVICE_ID_DRAGONRISE_DOLPHINBAR) },
- { HID_USB_DEVICE(USB_VENDOR_ID_DRAGONRISE, USB_DEVICE_ID_DRAGONRISE_GAMECUBE1) },
- { HID_USB_DEVICE(USB_VENDOR_ID_DRAGONRISE, USB_DEVICE_ID_DRAGONRISE_GAMECUBE2) },
#endif
- { HID_USB_DEVICE(USB_VENDOR_ID_DREAM_CHEEKY, USB_DEVICE_ID_DREAM_CHEEKY_WN) },
- { HID_USB_DEVICE(USB_VENDOR_ID_DREAM_CHEEKY, USB_DEVICE_ID_DREAM_CHEEKY_FA) },
+#if IS_ENABLED(CONFIG_HID_ELECOM)
{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_ELECOM, USB_DEVICE_ID_ELECOM_BM084) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_ELECOM, USB_DEVICE_ID_ELECOM_DEFT_WIRED) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_ELECOM, USB_DEVICE_ID_ELECOM_DEFT_WIRELESS) },
+#endif
+#if IS_ENABLED(CONFIG_HID_ELO)
{ HID_USB_DEVICE(USB_VENDOR_ID_ELO, 0x0009) },
{ HID_USB_DEVICE(USB_VENDOR_ID_ELO, 0x0030) },
- { HID_USB_DEVICE(USB_VENDOR_ID_ELO, USB_DEVICE_ID_ELO_ACCUTOUCH_2216) },
+#endif
+#if IS_ENABLED(CONFIG_HID_EMS_FF)
{ HID_USB_DEVICE(USB_VENDOR_ID_EMS, USB_DEVICE_ID_EMS_TRIO_LINKER_PLUS_II) },
+#endif
+#if IS_ENABLED(CONFIG_HID_EZKEY)
{ HID_USB_DEVICE(USB_VENDOR_ID_EZKEY, USB_DEVICE_ID_BTC_8193) },
- { HID_USB_DEVICE(USB_VENDOR_ID_GAMERON, USB_DEVICE_ID_GAMERON_DUAL_PSX_ADAPTOR) },
- { HID_USB_DEVICE(USB_VENDOR_ID_GAMERON, USB_DEVICE_ID_GAMERON_DUAL_PCS_ADAPTOR) },
+#endif
+#if IS_ENABLED(CONFIG_HID_GEMBIRD)
{ HID_USB_DEVICE(USB_VENDOR_ID_GEMBIRD, USB_DEVICE_ID_GEMBIRD_JPD_DUALFORCE2) },
- { HID_USB_DEVICE(USB_VENDOR_ID_GREENASIA, 0x0003) },
+#endif
+#if IS_ENABLED(CONFIG_HID_GFRM)
+ { HID_BLUETOOTH_DEVICE(0x58, 0x2000) },
+ { HID_BLUETOOTH_DEVICE(0x471, 0x2210) },
+#endif
+#if IS_ENABLED(CONFIG_HID_GREENASIA)
{ HID_USB_DEVICE(USB_VENDOR_ID_GREENASIA, 0x0012) },
+#endif
+#if IS_ENABLED(CONFIG_HID_GT683R)
+ { HID_USB_DEVICE(USB_VENDOR_ID_MSI, USB_DEVICE_ID_MSI_GT683R_LED_PANEL) },
+#endif
+#if IS_ENABLED(CONFIG_HID_GYRATION)
{ HID_USB_DEVICE(USB_VENDOR_ID_GYRATION, USB_DEVICE_ID_GYRATION_REMOTE) },
{ HID_USB_DEVICE(USB_VENDOR_ID_GYRATION, USB_DEVICE_ID_GYRATION_REMOTE_2) },
{ HID_USB_DEVICE(USB_VENDOR_ID_GYRATION, USB_DEVICE_ID_GYRATION_REMOTE_3) },
+#endif
+#if IS_ENABLED(CONFIG_HID_HOLTEK)
{ HID_USB_DEVICE(USB_VENDOR_ID_HOLTEK, USB_DEVICE_ID_HOLTEK_ON_LINE_GRIP) },
{ HID_USB_DEVICE(USB_VENDOR_ID_HOLTEK_ALT, USB_DEVICE_ID_HOLTEK_ALT_KEYBOARD) },
{ HID_USB_DEVICE(USB_VENDOR_ID_HOLTEK_ALT, USB_DEVICE_ID_HOLTEK_ALT_MOUSE_A04A) },
@@ -1912,12 +1980,17 @@ static const struct hid_device_id hid_have_special_driver[] = {
{ HID_USB_DEVICE(USB_VENDOR_ID_HOLTEK_ALT, USB_DEVICE_ID_HOLTEK_ALT_MOUSE_A072) },
{ HID_USB_DEVICE(USB_VENDOR_ID_HOLTEK_ALT, USB_DEVICE_ID_HOLTEK_ALT_MOUSE_A081) },
{ HID_USB_DEVICE(USB_VENDOR_ID_HOLTEK_ALT, USB_DEVICE_ID_HOLTEK_ALT_MOUSE_A0C2) },
- { HID_USB_DEVICE(USB_VENDOR_ID_HUION, USB_DEVICE_ID_HUION_TABLET) },
- { HID_USB_DEVICE(USB_VENDOR_ID_JESS, USB_DEVICE_ID_JESS_ZEN_AIO_KBD) },
- { HID_USB_DEVICE(USB_VENDOR_ID_JESS2, USB_DEVICE_ID_JESS2_COLOR_RUMBLE_PAD) },
+#endif
+#if IS_ENABLED(CONFIG_HID_ICADE)
{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_ION, USB_DEVICE_ID_ICADE) },
+#endif
+#if IS_ENABLED(CONFIG_HID_KENSINGTON)
{ HID_USB_DEVICE(USB_VENDOR_ID_KENSINGTON, USB_DEVICE_ID_KS_SLIMBLADE) },
+#endif
+#if IS_ENABLED(CONFIG_HID_KEYTOUCH)
{ HID_USB_DEVICE(USB_VENDOR_ID_KEYTOUCH, USB_DEVICE_ID_KEYTOUCH_IEC) },
+#endif
+#if IS_ENABLED(CONFIG_HID_KYE)
{ HID_USB_DEVICE(USB_VENDOR_ID_KYE, USB_DEVICE_ID_GENIUS_GILA_GAMING_MOUSE) },
{ HID_USB_DEVICE(USB_VENDOR_ID_KYE, USB_DEVICE_ID_GENIUS_MANTICORE) },
{ HID_USB_DEVICE(USB_VENDOR_ID_KYE, USB_DEVICE_ID_GENIUS_GX_IMPERATOR) },
@@ -1927,21 +2000,29 @@ static const struct hid_device_id hid_have_special_driver[] = {
{ HID_USB_DEVICE(USB_VENDOR_ID_KYE, USB_DEVICE_ID_KYE_MOUSEPEN_I608X_V2) },
{ HID_USB_DEVICE(USB_VENDOR_ID_KYE, USB_DEVICE_ID_KYE_EASYPEN_M610X) },
{ HID_USB_DEVICE(USB_VENDOR_ID_KYE, USB_DEVICE_ID_KYE_PENSKETCH_M912) },
- { HID_USB_DEVICE(USB_VENDOR_ID_LABTEC, USB_DEVICE_ID_LABTEC_WIRELESS_KEYBOARD) },
+#endif
+#if IS_ENABLED(CONFIG_HID_LCPOWER)
{ HID_USB_DEVICE(USB_VENDOR_ID_LCPOWER, USB_DEVICE_ID_LCPOWER_LC1000 ) },
+#endif
+#if IS_ENABLED(CONFIG_HID_LED)
+ { HID_USB_DEVICE(USB_VENDOR_ID_DELCOM, USB_DEVICE_ID_DELCOM_VISUAL_IND) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_DREAM_CHEEKY, USB_DEVICE_ID_DREAM_CHEEKY_WN) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_DREAM_CHEEKY, USB_DEVICE_ID_DREAM_CHEEKY_FA) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_MICROCHIP, USB_DEVICE_ID_LUXAFOR) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_RISO_KAGAKU, USB_DEVICE_ID_RI_KA_WEBMAIL) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_THINGM, USB_DEVICE_ID_BLINK1) },
+#endif
#if IS_ENABLED(CONFIG_HID_LENOVO)
{ HID_USB_DEVICE(USB_VENDOR_ID_LENOVO, USB_DEVICE_ID_LENOVO_TPKBD) },
{ HID_USB_DEVICE(USB_VENDOR_ID_LENOVO, USB_DEVICE_ID_LENOVO_CUSBKBD) },
{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_LENOVO, USB_DEVICE_ID_LENOVO_CBTKBD) },
{ HID_USB_DEVICE(USB_VENDOR_ID_LENOVO, USB_DEVICE_ID_LENOVO_TPPRODOCK) },
#endif
- { HID_USB_DEVICE(USB_VENDOR_ID_LG, USB_DEVICE_ID_LG_MELFAS_MT) },
+#if IS_ENABLED(CONFIG_HID_LOGITECH)
{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_MX3000_RECEIVER) },
{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_S510_RECEIVER) },
{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_S510_RECEIVER_2) },
{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_RECEIVER) },
- { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_HARMONY_PS3) },
- { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_T651) },
{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_DINOVO_DESKTOP) },
{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_DINOVO_EDGE) },
{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_DINOVO_MINI) },
@@ -1954,7 +2035,6 @@ static const struct hid_device_id hid_have_special_driver[] = {
{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_RUMBLEPAD) },
{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_RUMBLEPAD2_2) },
{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_G29_WHEEL) },
- { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_G920_WHEEL) },
{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_WINGMAN_F3D) },
{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_WINGMAN_FFG ) },
{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_FORCE3D_PRO) },
@@ -1966,17 +2046,30 @@ static const struct hid_device_id hid_have_special_driver[] = {
{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_DFGT_WHEEL) },
{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_G25_WHEEL) },
{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_G27_WHEEL) },
-#if IS_ENABLED(CONFIG_HID_LOGITECH_DJ)
- { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_UNIFYING_RECEIVER) },
- { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_UNIFYING_RECEIVER_2) },
-#endif
{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_WII_WHEEL) },
{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_RUMBLEPAD2) },
{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_SPACETRAVELLER) },
{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_SPACENAVIGATOR) },
- { HID_USB_DEVICE(USB_VENDOR_ID_MICROCHIP, USB_DEVICE_ID_PICOLCD) },
- { HID_USB_DEVICE(USB_VENDOR_ID_MICROCHIP, USB_DEVICE_ID_PICOLCD_BOOTLOADER) },
- { HID_USB_DEVICE(USB_VENDOR_ID_MICROCHIP, USB_DEVICE_ID_LUXAFOR) },
+#endif
+#if IS_ENABLED(CONFIG_HID_LOGITECH_HIDPP)
+ { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_T651) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_G920_WHEEL) },
+#endif
+#if IS_ENABLED(CONFIG_HID_LOGITECH_DJ)
+ { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_UNIFYING_RECEIVER) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_UNIFYING_RECEIVER_2) },
+#endif
+#if IS_ENABLED(CONFIG_HID_MAGICMOUSE)
+ { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_MAGICMOUSE) },
+ { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_MAGICTRACKPAD) },
+#endif
+#if IS_ENABLED(CONFIG_HID_MAYFLASH)
+ { HID_USB_DEVICE(USB_VENDOR_ID_DRAGONRISE, USB_DEVICE_ID_DRAGONRISE_PS3) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_DRAGONRISE, USB_DEVICE_ID_DRAGONRISE_DOLPHINBAR) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_DRAGONRISE, USB_DEVICE_ID_DRAGONRISE_GAMECUBE1) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_DRAGONRISE, USB_DEVICE_ID_DRAGONRISE_GAMECUBE2) },
+#endif
+#if IS_ENABLED(CONFIG_HID_MICROSOFT)
{ HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_COMFORT_MOUSE_4500) },
{ HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_COMFORT_KEYBOARD) },
{ HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_SIDEWINDER_GV) },
@@ -1992,9 +2085,22 @@ static const struct hid_device_id hid_have_special_driver[] = {
{ HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_DIGITAL_MEDIA_600) },
{ HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_DIGITAL_MEDIA_3KV1) },
{ HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_POWER_COVER) },
+ { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_PRESENTER_8K_BT) },
+#endif
+#if IS_ENABLED(CONFIG_HID_MONTEREY)
{ HID_USB_DEVICE(USB_VENDOR_ID_MONTEREY, USB_DEVICE_ID_GENIUS_KB29E) },
- { HID_USB_DEVICE(USB_VENDOR_ID_MSI, USB_DEVICE_ID_MSI_GT683R_LED_PANEL) },
+#endif
+#if IS_ENABLED(CONFIG_HID_MULTITOUCH)
+ { HID_USB_DEVICE(USB_VENDOR_ID_LG, USB_DEVICE_ID_LG_MELFAS_MT) },
+#endif
+#if IS_ENABLED(CONFIG_HID_WIIMOTE)
+ { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_NINTENDO, USB_DEVICE_ID_NINTENDO_WIIMOTE) },
+ { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_NINTENDO, USB_DEVICE_ID_NINTENDO_WIIMOTE2) },
+#endif
+#if IS_ENABLED(CONFIG_HID_NTI)
{ HID_USB_DEVICE(USB_VENDOR_ID_NTI, USB_DEVICE_ID_USB_SUN) },
+#endif
+#if IS_ENABLED(CONFIG_HID_NTRIG)
{ HID_USB_DEVICE(USB_VENDOR_ID_NTRIG, USB_DEVICE_ID_NTRIG_TOUCH_SCREEN) },
{ HID_USB_DEVICE(USB_VENDOR_ID_NTRIG, USB_DEVICE_ID_NTRIG_TOUCH_SCREEN_1) },
{ HID_USB_DEVICE(USB_VENDOR_ID_NTRIG, USB_DEVICE_ID_NTRIG_TOUCH_SCREEN_2) },
@@ -2014,13 +2120,41 @@ static const struct hid_device_id hid_have_special_driver[] = {
{ HID_USB_DEVICE(USB_VENDOR_ID_NTRIG, USB_DEVICE_ID_NTRIG_TOUCH_SCREEN_16) },
{ HID_USB_DEVICE(USB_VENDOR_ID_NTRIG, USB_DEVICE_ID_NTRIG_TOUCH_SCREEN_17) },
{ HID_USB_DEVICE(USB_VENDOR_ID_NTRIG, USB_DEVICE_ID_NTRIG_TOUCH_SCREEN_18) },
+#endif
+#if IS_ENABLED(CONFIG_HID_ORTEK)
{ HID_USB_DEVICE(USB_VENDOR_ID_ORTEK, USB_DEVICE_ID_ORTEK_PKB1700) },
{ HID_USB_DEVICE(USB_VENDOR_ID_ORTEK, USB_DEVICE_ID_ORTEK_WKB2000) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_SKYCABLE, USB_DEVICE_ID_SKYCABLE_WIRELESS_PRESENTER) },
+#endif
+#if IS_ENABLED(CONFIG_HID_PANTHERLORD)
+ { HID_USB_DEVICE(USB_VENDOR_ID_GAMERON, USB_DEVICE_ID_GAMERON_DUAL_PSX_ADAPTOR) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_GAMERON, USB_DEVICE_ID_GAMERON_DUAL_PCS_ADAPTOR) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_GREENASIA, 0x0003) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_JESS2, USB_DEVICE_ID_JESS2_COLOR_RUMBLE_PAD) },
+#endif
+#if IS_ENABLED(CONFIG_HID_PENMOUNT)
{ HID_USB_DEVICE(USB_VENDOR_ID_PENMOUNT, USB_DEVICE_ID_PENMOUNT_6000) },
+#endif
+#if IS_ENABLED(CONFIG_HID_PETALYNX)
{ HID_USB_DEVICE(USB_VENDOR_ID_PETALYNX, USB_DEVICE_ID_PETALYNX_MAXTER_REMOTE) },
+#endif
+#if IS_ENABLED(CONFIG_HID_PICOLCD)
+ { HID_USB_DEVICE(USB_VENDOR_ID_MICROCHIP, USB_DEVICE_ID_PICOLCD) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_MICROCHIP, USB_DEVICE_ID_PICOLCD_BOOTLOADER) },
+#endif
+#if IS_ENABLED(CONFIG_HID_PLANTRONICS)
{ HID_USB_DEVICE(USB_VENDOR_ID_PLANTRONICS, HID_ANY_ID) },
+#endif
+#if IS_ENABLED(CONFIG_HID_PRIMAX)
{ HID_USB_DEVICE(USB_VENDOR_ID_PRIMAX, USB_DEVICE_ID_PRIMAX_KEYBOARD) },
- { HID_USB_DEVICE(USB_VENDOR_ID_RISO_KAGAKU, USB_DEVICE_ID_RI_KA_WEBMAIL) },
+#endif
+#if IS_ENABLED(CONFIG_HID_PRODIKEYS)
+ { HID_USB_DEVICE(USB_VENDOR_ID_CREATIVELABS, USB_DEVICE_ID_PRODIKEYS_PCMIDI) },
+#endif
+#if IS_ENABLED(CONFIG_HID_RMI)
+ { HID_USB_DEVICE(USB_VENDOR_ID_LENOVO, USB_DEVICE_ID_LENOVO_X1_COVER) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_RAZER, USB_DEVICE_ID_RAZER_BLADE_14) },
+#endif
#if IS_ENABLED(CONFIG_HID_ROCCAT)
{ HID_USB_DEVICE(USB_VENDOR_ID_ROCCAT, USB_DEVICE_ID_ROCCAT_ARVO) },
{ HID_USB_DEVICE(USB_VENDOR_ID_ROCCAT, USB_DEVICE_ID_ROCCAT_ISKU) },
@@ -2048,9 +2182,21 @@ static const struct hid_device_id hid_have_special_driver[] = {
{ HID_USB_DEVICE(USB_VENDOR_ID_MADCATZ, USB_DEVICE_ID_MADCATZ_RAT5) },
{ HID_USB_DEVICE(USB_VENDOR_ID_MADCATZ, USB_DEVICE_ID_MADCATZ_RAT9) },
#endif
+#if IS_ENABLED(CONFIG_HID_SAMSUNG)
{ HID_USB_DEVICE(USB_VENDOR_ID_SAMSUNG, USB_DEVICE_ID_SAMSUNG_IR_REMOTE) },
{ HID_USB_DEVICE(USB_VENDOR_ID_SAMSUNG, USB_DEVICE_ID_SAMSUNG_WIRELESS_KBD_MOUSE) },
- { HID_USB_DEVICE(USB_VENDOR_ID_SKYCABLE, USB_DEVICE_ID_SKYCABLE_WIRELESS_PRESENTER) },
+#endif
+#if IS_ENABLED(CONFIG_HID_SMARTJOYPLUS)
+ { HID_USB_DEVICE(USB_VENDOR_ID_PLAYDOTCOM, USB_DEVICE_ID_PLAYDOTCOM_EMS_USBII) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_WISEGROUP, USB_DEVICE_ID_SMARTJOY_PLUS) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_WISEGROUP, USB_DEVICE_ID_SUPER_JOY_BOX_3) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_WISEGROUP, USB_DEVICE_ID_DUAL_USB_JOYPAD) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_WISEGROUP_LTD, USB_DEVICE_ID_SUPER_JOY_BOX_3_PRO) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_WISEGROUP_LTD, USB_DEVICE_ID_SUPER_DUAL_BOX_PRO) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_WISEGROUP_LTD, USB_DEVICE_ID_SUPER_JOY_BOX_5_PRO) },
+#endif
+#if IS_ENABLED(CONFIG_HID_SONY)
+ { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_HARMONY_PS3) },
{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_SMK, USB_DEVICE_ID_SMK_PS3_BDREMOTE) },
{ HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_BUZZ_CONTROLLER) },
{ HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_WIRELESS_BUZZ_CONTROLLER) },
@@ -2069,9 +2215,17 @@ static const struct hid_device_id hid_have_special_driver[] = {
{ HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_VAIO_VGX_MOUSE) },
{ HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_VAIO_VGP_MOUSE) },
{ HID_USB_DEVICE(USB_VENDOR_ID_SINO_LITE, USB_DEVICE_ID_SINO_LITE_CONTROLLER) },
+#endif
+#if IS_ENABLED(CONFIG_HID_SPEEDLINK)
+ { HID_USB_DEVICE(USB_VENDOR_ID_X_TENSIONS, USB_DEVICE_ID_SPEEDLINK_VAD_CEZANNE) },
+#endif
+#if IS_ENABLED(CONFIG_HID_STEELSERIES)
{ HID_USB_DEVICE(USB_VENDOR_ID_STEELSERIES, USB_DEVICE_ID_STEELSERIES_SRWS1) },
+#endif
+#if IS_ENABLED(CONFIG_HID_SUNPLUS)
{ HID_USB_DEVICE(USB_VENDOR_ID_SUNPLUS, USB_DEVICE_ID_SUNPLUS_WDESKTOP) },
- { HID_USB_DEVICE(USB_VENDOR_ID_THINGM, USB_DEVICE_ID_BLINK1) },
+#endif
+#if IS_ENABLED(CONFIG_HID_THRUSTMASTER)
{ HID_USB_DEVICE(USB_VENDOR_ID_THRUSTMASTER, 0xb300) },
{ HID_USB_DEVICE(USB_VENDOR_ID_THRUSTMASTER, 0xb304) },
{ HID_USB_DEVICE(USB_VENDOR_ID_THRUSTMASTER, 0xb323) },
@@ -2080,12 +2234,25 @@ static const struct hid_device_id hid_have_special_driver[] = {
{ HID_USB_DEVICE(USB_VENDOR_ID_THRUSTMASTER, 0xb653) },
{ HID_USB_DEVICE(USB_VENDOR_ID_THRUSTMASTER, 0xb654) },
{ HID_USB_DEVICE(USB_VENDOR_ID_THRUSTMASTER, 0xb65a) },
+#endif
+#if IS_ENABLED(CONFIG_HID_TIVO)
{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_TIVO, USB_DEVICE_ID_TIVO_SLIDE_BT) },
{ HID_USB_DEVICE(USB_VENDOR_ID_TIVO, USB_DEVICE_ID_TIVO_SLIDE) },
{ HID_USB_DEVICE(USB_VENDOR_ID_TIVO, USB_DEVICE_ID_TIVO_SLIDE_PRO) },
+#endif
+#if IS_ENABLED(CONFIG_HID_TOPSEED)
+ { HID_USB_DEVICE(USB_VENDOR_ID_BTC, USB_DEVICE_ID_BTC_EMPREX_REMOTE) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_BTC, USB_DEVICE_ID_BTC_EMPREX_REMOTE_2) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_CHICONY, USB_DEVICE_ID_CHICONY_WIRELESS) },
{ HID_USB_DEVICE(USB_VENDOR_ID_TOPSEED, USB_DEVICE_ID_TOPSEED_CYBERLINK) },
{ HID_USB_DEVICE(USB_VENDOR_ID_TOPSEED2, USB_DEVICE_ID_TOPSEED2_RF_COMBO) },
+#endif
+#if IS_ENABLED(CONFIG_HID_TWINHAN)
{ HID_USB_DEVICE(USB_VENDOR_ID_TWINHAN, USB_DEVICE_ID_TWINHAN_IR_REMOTE) },
+#endif
+#if IS_ENABLED(CONFIG_HID_UCLOGIC)
+ { HID_USB_DEVICE(USB_VENDOR_ID_HUION, USB_DEVICE_ID_HUION_TABLET) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_UCLOGIC, USB_DEVICE_ID_HUION_TABLET) },
{ HID_USB_DEVICE(USB_VENDOR_ID_UCLOGIC, USB_DEVICE_ID_UCLOGIC_TABLET_PF1209) },
{ HID_USB_DEVICE(USB_VENDOR_ID_UCLOGIC, USB_DEVICE_ID_UCLOGIC_TABLET_WP4030U) },
{ HID_USB_DEVICE(USB_VENDOR_ID_UCLOGIC, USB_DEVICE_ID_UCLOGIC_TABLET_WP5540U) },
@@ -2093,20 +2260,17 @@ static const struct hid_device_id hid_have_special_driver[] = {
{ HID_USB_DEVICE(USB_VENDOR_ID_UCLOGIC, USB_DEVICE_ID_UCLOGIC_TABLET_WP1062) },
{ HID_USB_DEVICE(USB_VENDOR_ID_UCLOGIC, USB_DEVICE_ID_UCLOGIC_WIRELESS_TABLET_TWHL850) },
{ HID_USB_DEVICE(USB_VENDOR_ID_UCLOGIC, USB_DEVICE_ID_UCLOGIC_TABLET_TWHA60) },
- { HID_USB_DEVICE(USB_VENDOR_ID_THQ, USB_DEVICE_ID_THQ_PS3_UDRAW) },
{ HID_USB_DEVICE(USB_VENDOR_ID_UCLOGIC, USB_DEVICE_ID_YIYNOVA_TABLET) },
{ HID_USB_DEVICE(USB_VENDOR_ID_UCLOGIC, USB_DEVICE_ID_UGEE_TABLET_81) },
{ HID_USB_DEVICE(USB_VENDOR_ID_UCLOGIC, USB_DEVICE_ID_UGEE_TABLET_45) },
{ HID_USB_DEVICE(USB_VENDOR_ID_UCLOGIC, USB_DEVICE_ID_UCLOGIC_DRAWIMAGE_G3) },
- { HID_USB_DEVICE(USB_VENDOR_ID_UGTIZER, USB_DEVICE_ID_UGTIZER_TABLET_GP0610) },
{ HID_USB_DEVICE(USB_VENDOR_ID_UGEE, USB_DEVICE_ID_UGEE_TABLET_EX07S) },
- { HID_USB_DEVICE(USB_VENDOR_ID_WISEGROUP, USB_DEVICE_ID_SMARTJOY_PLUS) },
- { HID_USB_DEVICE(USB_VENDOR_ID_WISEGROUP, USB_DEVICE_ID_SUPER_JOY_BOX_3) },
- { HID_USB_DEVICE(USB_VENDOR_ID_WISEGROUP, USB_DEVICE_ID_DUAL_USB_JOYPAD) },
- { HID_USB_DEVICE(USB_VENDOR_ID_WISEGROUP_LTD, USB_DEVICE_ID_SUPER_JOY_BOX_3_PRO) },
- { HID_USB_DEVICE(USB_VENDOR_ID_WISEGROUP_LTD, USB_DEVICE_ID_SUPER_DUAL_BOX_PRO) },
- { HID_USB_DEVICE(USB_VENDOR_ID_WISEGROUP_LTD, USB_DEVICE_ID_SUPER_JOY_BOX_5_PRO) },
- { HID_USB_DEVICE(USB_VENDOR_ID_PLAYDOTCOM, USB_DEVICE_ID_PLAYDOTCOM_EMS_USBII) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_UGTIZER, USB_DEVICE_ID_UGTIZER_TABLET_GP0610) },
+#endif
+#if IS_ENABLED(CONFIG_HID_UDRAW_PS3)
+ { HID_USB_DEVICE(USB_VENDOR_ID_THQ, USB_DEVICE_ID_THQ_PS3_UDRAW) },
+#endif
+#if IS_ENABLED(CONFIG_HID_WALTOP)
{ HID_USB_DEVICE(USB_VENDOR_ID_WALTOP, USB_DEVICE_ID_WALTOP_SLIM_TABLET_5_8_INCH) },
{ HID_USB_DEVICE(USB_VENDOR_ID_WALTOP, USB_DEVICE_ID_WALTOP_SLIM_TABLET_12_1_INCH) },
{ HID_USB_DEVICE(USB_VENDOR_ID_WALTOP, USB_DEVICE_ID_WALTOP_Q_PAD) },
@@ -2114,19 +2278,18 @@ static const struct hid_device_id hid_have_special_driver[] = {
{ HID_USB_DEVICE(USB_VENDOR_ID_WALTOP, USB_DEVICE_ID_WALTOP_MEDIA_TABLET_10_6_INCH) },
{ HID_USB_DEVICE(USB_VENDOR_ID_WALTOP, USB_DEVICE_ID_WALTOP_MEDIA_TABLET_14_1_INCH) },
{ HID_USB_DEVICE(USB_VENDOR_ID_WALTOP, USB_DEVICE_ID_WALTOP_SIRIUS_BATTERY_FREE_TABLET) },
- { HID_USB_DEVICE(USB_VENDOR_ID_X_TENSIONS, USB_DEVICE_ID_SPEEDLINK_VAD_CEZANNE) },
+#endif
+#if IS_ENABLED(CONFIG_HID_XINMO)
{ HID_USB_DEVICE(USB_VENDOR_ID_XIN_MO, USB_DEVICE_ID_XIN_MO_DUAL_ARCADE) },
{ HID_USB_DEVICE(USB_VENDOR_ID_XIN_MO, USB_DEVICE_ID_THT_2P_ARCADE) },
+#endif
+#if IS_ENABLED(CONFIG_HID_ZEROPLUS)
{ HID_USB_DEVICE(USB_VENDOR_ID_ZEROPLUS, 0x0005) },
{ HID_USB_DEVICE(USB_VENDOR_ID_ZEROPLUS, 0x0030) },
+#endif
+#if IS_ENABLED(CONFIG_HID_ZYDACRON)
{ HID_USB_DEVICE(USB_VENDOR_ID_ZYDACRON, USB_DEVICE_ID_ZYDACRON_REMOTE_CONTROL) },
-
- { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_PRESENTER_8K_BT) },
- { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_NINTENDO, USB_DEVICE_ID_NINTENDO_WIIMOTE) },
- { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_NINTENDO, USB_DEVICE_ID_NINTENDO_WIIMOTE2) },
- { HID_USB_DEVICE(USB_VENDOR_ID_RAZER, USB_DEVICE_ID_RAZER_BLADE_14) },
- { HID_USB_DEVICE(USB_VENDOR_ID_CMEDIA, USB_DEVICE_ID_CM6533) },
- { HID_USB_DEVICE(USB_VENDOR_ID_LENOVO, USB_DEVICE_ID_LENOVO_X1_COVER) },
+#endif
{ }
};
diff --git a/drivers/hid/hid-elecom.c b/drivers/hid/hid-elecom.c
index 6e3848a8d8dd..e2c7465df69f 100644
--- a/drivers/hid/hid-elecom.c
+++ b/drivers/hid/hid-elecom.c
@@ -1,10 +1,8 @@
/*
- * HID driver for Elecom BM084 (bluetooth mouse).
- * Removes a non-existing horizontal wheel from
- * the HID descriptor.
- * (This module is based on "hid-ortek".)
- *
+ * HID driver for ELECOM devices.
* Copyright (c) 2010 Richard Nauber <Richard.Nauber@gmail.com>
+ * Copyright (c) 2016 Yuxuan Shui <yshuiv7@gmail.com>
+ * Copyright (c) 2017 Diego Elio Pettenò <flameeyes@flameeyes.eu>
*/
/*
@@ -23,15 +21,61 @@
static __u8 *elecom_report_fixup(struct hid_device *hdev, __u8 *rdesc,
unsigned int *rsize)
{
- if (*rsize >= 48 && rdesc[46] == 0x05 && rdesc[47] == 0x0c) {
- hid_info(hdev, "Fixing up Elecom BM084 report descriptor\n");
- rdesc[47] = 0x00;
+ switch (hdev->product) {
+ case USB_DEVICE_ID_ELECOM_BM084:
+ /* The BM084 Bluetooth mouse includes a non-existing horizontal
+ * wheel in the HID descriptor. */
+ if (*rsize >= 48 && rdesc[46] == 0x05 && rdesc[47] == 0x0c) {
+ hid_info(hdev, "Fixing up Elecom BM084 report descriptor\n");
+ rdesc[47] = 0x00;
+ }
+ break;
+ case USB_DEVICE_ID_ELECOM_DEFT_WIRED:
+ case USB_DEVICE_ID_ELECOM_DEFT_WIRELESS:
+ /* The DEFT trackball has eight buttons, but its descriptor only
+ * reports five, disabling the three Fn buttons on the top of
+ * the mouse.
+ *
+ * Apply the following diff to the descriptor:
+ *
+ * Collection (Physical), Collection (Physical),
+ * Report ID (1), Report ID (1),
+ * Report Count (5), -> Report Count (8),
+ * Report Size (1), Report Size (1),
+ * Usage Page (Button), Usage Page (Button),
+ * Usage Minimum (01h), Usage Minimum (01h),
+ * Usage Maximum (05h), -> Usage Maximum (08h),
+ * Logical Minimum (0), Logical Minimum (0),
+ * Logical Maximum (1), Logical Maximum (1),
+ * Input (Variable), Input (Variable),
+ * Report Count (1), -> Report Count (0),
+ * Report Size (3), Report Size (3),
+ * Input (Constant), Input (Constant),
+ * Report Size (16), Report Size (16),
+ * Report Count (2), Report Count (2),
+ * Usage Page (Desktop), Usage Page (Desktop),
+ * Usage (X), Usage (X),
+ * Usage (Y), Usage (Y),
+ * Logical Minimum (-32768), Logical Minimum (-32768),
+ * Logical Maximum (32767), Logical Maximum (32767),
+ * Input (Variable, Relative), Input (Variable, Relative),
+ * End Collection, End Collection,
+ */
+ if (*rsize == 213 && rdesc[13] == 5 && rdesc[21] == 5) {
+ hid_info(hdev, "Fixing up Elecom DEFT Fn buttons\n");
+ rdesc[13] = 8; /* Button/Variable Report Count */
+ rdesc[21] = 8; /* Button/Variable Usage Maximum */
+ rdesc[29] = 0; /* Button/Constant Report Count */
+ }
+ break;
}
return rdesc;
}
static const struct hid_device_id elecom_devices[] = {
- { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_ELECOM, USB_DEVICE_ID_ELECOM_BM084)},
+ { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_ELECOM, USB_DEVICE_ID_ELECOM_BM084) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_ELECOM, USB_DEVICE_ID_ELECOM_DEFT_WIRED) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_ELECOM, USB_DEVICE_ID_ELECOM_DEFT_WIRELESS) },
{ }
};
MODULE_DEVICE_TABLE(hid, elecom_devices);
diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h
index 643390ba749d..4f9a3938189a 100644
--- a/drivers/hid/hid-ids.h
+++ b/drivers/hid/hid-ids.h
@@ -173,6 +173,7 @@
#define USB_VENDOR_ID_ASUSTEK 0x0b05
#define USB_DEVICE_ID_ASUSTEK_LCM 0x1726
#define USB_DEVICE_ID_ASUSTEK_LCM2 0x175b
+#define USB_DEVICE_ID_ASUSTEK_T100_KEYBOARD 0x17e0
#define USB_DEVICE_ID_ASUSTEK_I2C_KEYBOARD 0x8585
#define USB_DEVICE_ID_ASUSTEK_I2C_TOUCHPAD 0x0101
#define USB_DEVICE_ID_ASUSTEK_ROG_KEYBOARD1 0x1854
@@ -318,6 +319,9 @@
#define USB_VENDOR_ID_DELCOM 0x0fc5
#define USB_DEVICE_ID_DELCOM_VISUAL_IND 0xb080
+#define USB_VENDOR_ID_DELL 0x413c
+#define USB_DEVICE_ID_DELL_PIXART_USB_OPTICAL_MOUSE 0x301a
+
#define USB_VENDOR_ID_DELORME 0x1163
#define USB_DEVICE_ID_DELORME_EARTHMATE 0x0100
#define USB_DEVICE_ID_DELORME_EM_LT20 0x0200
@@ -358,6 +362,8 @@
#define USB_VENDOR_ID_ELECOM 0x056e
#define USB_DEVICE_ID_ELECOM_BM084 0x0061
+#define USB_DEVICE_ID_ELECOM_DEFT_WIRED 0x00fe
+#define USB_DEVICE_ID_ELECOM_DEFT_WIRELESS 0x00ff
#define USB_VENDOR_ID_DREAM_CHEEKY 0x1d34
#define USB_DEVICE_ID_DREAM_CHEEKY_WN 0x0004
diff --git a/drivers/hid/i2c-hid/i2c-hid.c b/drivers/hid/i2c-hid/i2c-hid.c
index 8daa8ce64ebb..04015032a35a 100644
--- a/drivers/hid/i2c-hid/i2c-hid.c
+++ b/drivers/hid/i2c-hid/i2c-hid.c
@@ -872,10 +872,9 @@ static int i2c_hid_fetch_hid_descriptor(struct i2c_hid *ihid)
static int i2c_hid_acpi_pdata(struct i2c_client *client,
struct i2c_hid_platform_data *pdata)
{
- static u8 i2c_hid_guid[] = {
- 0xF7, 0xF6, 0xDF, 0x3C, 0x67, 0x42, 0x55, 0x45,
- 0xAD, 0x05, 0xB3, 0x0A, 0x3D, 0x89, 0x38, 0xDE,
- };
+ static guid_t i2c_hid_guid =
+ GUID_INIT(0x3CDFF6F7, 0x4267, 0x4555,
+ 0xAD, 0x05, 0xB3, 0x0A, 0x3D, 0x89, 0x38, 0xDE);
union acpi_object *obj;
struct acpi_device *adev;
acpi_handle handle;
@@ -884,7 +883,7 @@ static int i2c_hid_acpi_pdata(struct i2c_client *client,
if (!handle || acpi_bus_get_device(handle, &adev))
return -ENODEV;
- obj = acpi_evaluate_dsm_typed(handle, i2c_hid_guid, 1, 1, NULL,
+ obj = acpi_evaluate_dsm_typed(handle, &i2c_hid_guid, 1, 1, NULL,
ACPI_TYPE_INTEGER);
if (!obj) {
dev_err(&client->dev, "device _DSM execution failed\n");
@@ -897,6 +896,15 @@ static int i2c_hid_acpi_pdata(struct i2c_client *client,
return 0;
}
+static void i2c_hid_acpi_fix_up_power(struct device *dev)
+{
+ acpi_handle handle = ACPI_HANDLE(dev);
+ struct acpi_device *adev;
+
+ if (handle && acpi_bus_get_device(handle, &adev) == 0)
+ acpi_device_fix_up_power(adev);
+}
+
static const struct acpi_device_id i2c_hid_acpi_match[] = {
{"ACPI0C50", 0 },
{"PNP0C50", 0 },
@@ -909,6 +917,8 @@ static inline int i2c_hid_acpi_pdata(struct i2c_client *client,
{
return -ENODEV;
}
+
+static inline void i2c_hid_acpi_fix_up_power(struct device *dev) {}
#endif
#ifdef CONFIG_OF
@@ -1030,6 +1040,8 @@ static int i2c_hid_probe(struct i2c_client *client,
if (ret < 0)
goto err_regulator;
+ i2c_hid_acpi_fix_up_power(&client->dev);
+
pm_runtime_get_noresume(&client->dev);
pm_runtime_set_active(&client->dev);
pm_runtime_enable(&client->dev);
diff --git a/drivers/hid/usbhid/hid-quirks.c b/drivers/hid/usbhid/hid-quirks.c
index 6316498b7812..a88e7c7bea0a 100644
--- a/drivers/hid/usbhid/hid-quirks.c
+++ b/drivers/hid/usbhid/hid-quirks.c
@@ -85,6 +85,7 @@ static const struct hid_blacklist {
{ USB_VENDOR_ID_CORSAIR, USB_DEVICE_ID_CORSAIR_K65RGB_RAPIDFIRE, HID_QUIRK_NO_INIT_REPORTS | HID_QUIRK_ALWAYS_POLL },
{ USB_VENDOR_ID_CORSAIR, USB_DEVICE_ID_CORSAIR_SCIMITAR_PRO_RGB, HID_QUIRK_NO_INIT_REPORTS | HID_QUIRK_ALWAYS_POLL },
{ USB_VENDOR_ID_CREATIVELABS, USB_DEVICE_ID_CREATIVE_SB_OMNI_SURROUND_51, HID_QUIRK_NOGET },
+ { USB_VENDOR_ID_DELL, USB_DEVICE_ID_DELL_PIXART_USB_OPTICAL_MOUSE, HID_QUIRK_ALWAYS_POLL },
{ USB_VENDOR_ID_DMI, USB_DEVICE_ID_DMI_ENC, HID_QUIRK_NOGET },
{ USB_VENDOR_ID_DRAGONRISE, USB_DEVICE_ID_DRAGONRISE_WIIU, HID_QUIRK_MULTI_INPUT },
{ USB_VENDOR_ID_DRAGONRISE, USB_DEVICE_ID_DRAGONRISE_PS3, HID_QUIRK_MULTI_INPUT },
diff --git a/drivers/hid/wacom_wac.c b/drivers/hid/wacom_wac.c
index 4b225fb19a16..e274c9dc32f3 100644
--- a/drivers/hid/wacom_wac.c
+++ b/drivers/hid/wacom_wac.c
@@ -1571,37 +1571,38 @@ static int wacom_tpc_irq(struct wacom_wac *wacom, size_t len)
{
unsigned char *data = wacom->data;
- if (wacom->pen_input)
+ if (wacom->pen_input) {
dev_dbg(wacom->pen_input->dev.parent,
"%s: received report #%d\n", __func__, data[0]);
- else if (wacom->touch_input)
+
+ if (len == WACOM_PKGLEN_PENABLED ||
+ data[0] == WACOM_REPORT_PENABLED)
+ return wacom_tpc_pen(wacom);
+ }
+ else if (wacom->touch_input) {
dev_dbg(wacom->touch_input->dev.parent,
"%s: received report #%d\n", __func__, data[0]);
- switch (len) {
- case WACOM_PKGLEN_TPC1FG:
- return wacom_tpc_single_touch(wacom, len);
+ switch (len) {
+ case WACOM_PKGLEN_TPC1FG:
+ return wacom_tpc_single_touch(wacom, len);
- case WACOM_PKGLEN_TPC2FG:
- return wacom_tpc_mt_touch(wacom);
+ case WACOM_PKGLEN_TPC2FG:
+ return wacom_tpc_mt_touch(wacom);
- case WACOM_PKGLEN_PENABLED:
- return wacom_tpc_pen(wacom);
+ default:
+ switch (data[0]) {
+ case WACOM_REPORT_TPC1FG:
+ case WACOM_REPORT_TPCHID:
+ case WACOM_REPORT_TPCST:
+ case WACOM_REPORT_TPC1FGE:
+ return wacom_tpc_single_touch(wacom, len);
- default:
- switch (data[0]) {
- case WACOM_REPORT_TPC1FG:
- case WACOM_REPORT_TPCHID:
- case WACOM_REPORT_TPCST:
- case WACOM_REPORT_TPC1FGE:
- return wacom_tpc_single_touch(wacom, len);
-
- case WACOM_REPORT_TPCMT:
- case WACOM_REPORT_TPCMT2:
- return wacom_mt_touch(wacom);
+ case WACOM_REPORT_TPCMT:
+ case WACOM_REPORT_TPCMT2:
+ return wacom_mt_touch(wacom);
- case WACOM_REPORT_PENABLED:
- return wacom_tpc_pen(wacom);
+ }
}
}
diff --git a/drivers/hsi/clients/ssi_protocol.c b/drivers/hsi/clients/ssi_protocol.c
index 26b05106f0d3..93d28c0ec8bf 100644
--- a/drivers/hsi/clients/ssi_protocol.c
+++ b/drivers/hsi/clients/ssi_protocol.c
@@ -1066,7 +1066,7 @@ static void ssip_pn_setup(struct net_device *dev)
dev->addr_len = 1;
dev->tx_queue_len = SSIP_TXQUEUE_LEN;
- dev->destructor = free_netdev;
+ dev->needs_free_netdev = true;
dev->header_ops = &phonet_header_ops;
}
diff --git a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig
index 22d5eafd6815..5ef2814345ef 100644
--- a/drivers/hwmon/Kconfig
+++ b/drivers/hwmon/Kconfig
@@ -343,6 +343,7 @@ config SENSORS_ASB100
config SENSORS_ASPEED
tristate "ASPEED AST2400/AST2500 PWM and Fan tach driver"
+ select REGMAP
help
This driver provides support for ASPEED AST2400/AST2500 PWM
and Fan Tacho controllers.
diff --git a/drivers/hwmon/aspeed-pwm-tacho.c b/drivers/hwmon/aspeed-pwm-tacho.c
index 48403a2115be..9de13d626c68 100644
--- a/drivers/hwmon/aspeed-pwm-tacho.c
+++ b/drivers/hwmon/aspeed-pwm-tacho.c
@@ -7,6 +7,7 @@
*/
#include <linux/clk.h>
+#include <linux/errno.h>
#include <linux/gpio/consumer.h>
#include <linux/delay.h>
#include <linux/hwmon.h>
@@ -494,7 +495,7 @@ static u32 aspeed_get_fan_tach_ch_measure_period(struct aspeed_pwm_tacho_data
return clk / (clk_unit * div_h * div_l * tacho_div * tacho_unit);
}
-static u32 aspeed_get_fan_tach_ch_rpm(struct aspeed_pwm_tacho_data *priv,
+static int aspeed_get_fan_tach_ch_rpm(struct aspeed_pwm_tacho_data *priv,
u8 fan_tach_ch)
{
u32 raw_data, tach_div, clk_source, sec, val;
@@ -510,6 +511,9 @@ static u32 aspeed_get_fan_tach_ch_rpm(struct aspeed_pwm_tacho_data *priv,
msleep(sec);
regmap_read(priv->regmap, ASPEED_PTCR_RESULT, &val);
+ if (!(val & RESULT_STATUS_MASK))
+ return -ETIMEDOUT;
+
raw_data = val & RESULT_VALUE_MASK;
tach_div = priv->type_fan_tach_clock_division[type];
tach_div = 0x4 << (tach_div * 2);
@@ -561,12 +565,14 @@ static ssize_t show_rpm(struct device *dev, struct device_attribute *attr,
{
struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
int index = sensor_attr->index;
- u32 rpm;
+ int rpm;
struct aspeed_pwm_tacho_data *priv = dev_get_drvdata(dev);
rpm = aspeed_get_fan_tach_ch_rpm(priv, index);
+ if (rpm < 0)
+ return rpm;
- return sprintf(buf, "%u\n", rpm);
+ return sprintf(buf, "%d\n", rpm);
}
static umode_t pwm_is_visible(struct kobject *kobj,
@@ -591,24 +597,23 @@ static umode_t fan_dev_is_visible(struct kobject *kobj,
return a->mode;
}
-static SENSOR_DEVICE_ATTR(pwm0, 0644,
- show_pwm, set_pwm, 0);
static SENSOR_DEVICE_ATTR(pwm1, 0644,
- show_pwm, set_pwm, 1);
+ show_pwm, set_pwm, 0);
static SENSOR_DEVICE_ATTR(pwm2, 0644,
- show_pwm, set_pwm, 2);
+ show_pwm, set_pwm, 1);
static SENSOR_DEVICE_ATTR(pwm3, 0644,
- show_pwm, set_pwm, 3);
+ show_pwm, set_pwm, 2);
static SENSOR_DEVICE_ATTR(pwm4, 0644,
- show_pwm, set_pwm, 4);
+ show_pwm, set_pwm, 3);
static SENSOR_DEVICE_ATTR(pwm5, 0644,
- show_pwm, set_pwm, 5);
+ show_pwm, set_pwm, 4);
static SENSOR_DEVICE_ATTR(pwm6, 0644,
- show_pwm, set_pwm, 6);
+ show_pwm, set_pwm, 5);
static SENSOR_DEVICE_ATTR(pwm7, 0644,
+ show_pwm, set_pwm, 6);
+static SENSOR_DEVICE_ATTR(pwm8, 0644,
show_pwm, set_pwm, 7);
static struct attribute *pwm_dev_attrs[] = {
- &sensor_dev_attr_pwm0.dev_attr.attr,
&sensor_dev_attr_pwm1.dev_attr.attr,
&sensor_dev_attr_pwm2.dev_attr.attr,
&sensor_dev_attr_pwm3.dev_attr.attr,
@@ -616,6 +621,7 @@ static struct attribute *pwm_dev_attrs[] = {
&sensor_dev_attr_pwm5.dev_attr.attr,
&sensor_dev_attr_pwm6.dev_attr.attr,
&sensor_dev_attr_pwm7.dev_attr.attr,
+ &sensor_dev_attr_pwm8.dev_attr.attr,
NULL,
};
@@ -624,40 +630,39 @@ static const struct attribute_group pwm_dev_group = {
.is_visible = pwm_is_visible,
};
-static SENSOR_DEVICE_ATTR(fan0_input, 0444,
- show_rpm, NULL, 0);
static SENSOR_DEVICE_ATTR(fan1_input, 0444,
- show_rpm, NULL, 1);
+ show_rpm, NULL, 0);
static SENSOR_DEVICE_ATTR(fan2_input, 0444,
- show_rpm, NULL, 2);
+ show_rpm, NULL, 1);
static SENSOR_DEVICE_ATTR(fan3_input, 0444,
- show_rpm, NULL, 3);
+ show_rpm, NULL, 2);
static SENSOR_DEVICE_ATTR(fan4_input, 0444,
- show_rpm, NULL, 4);
+ show_rpm, NULL, 3);
static SENSOR_DEVICE_ATTR(fan5_input, 0444,
- show_rpm, NULL, 5);
+ show_rpm, NULL, 4);
static SENSOR_DEVICE_ATTR(fan6_input, 0444,
- show_rpm, NULL, 6);
+ show_rpm, NULL, 5);
static SENSOR_DEVICE_ATTR(fan7_input, 0444,
- show_rpm, NULL, 7);
+ show_rpm, NULL, 6);
static SENSOR_DEVICE_ATTR(fan8_input, 0444,
- show_rpm, NULL, 8);
+ show_rpm, NULL, 7);
static SENSOR_DEVICE_ATTR(fan9_input, 0444,
- show_rpm, NULL, 9);
+ show_rpm, NULL, 8);
static SENSOR_DEVICE_ATTR(fan10_input, 0444,
- show_rpm, NULL, 10);
+ show_rpm, NULL, 9);
static SENSOR_DEVICE_ATTR(fan11_input, 0444,
- show_rpm, NULL, 11);
+ show_rpm, NULL, 10);
static SENSOR_DEVICE_ATTR(fan12_input, 0444,
- show_rpm, NULL, 12);
+ show_rpm, NULL, 11);
static SENSOR_DEVICE_ATTR(fan13_input, 0444,
- show_rpm, NULL, 13);
+ show_rpm, NULL, 12);
static SENSOR_DEVICE_ATTR(fan14_input, 0444,
- show_rpm, NULL, 14);
+ show_rpm, NULL, 13);
static SENSOR_DEVICE_ATTR(fan15_input, 0444,
+ show_rpm, NULL, 14);
+static SENSOR_DEVICE_ATTR(fan16_input, 0444,
show_rpm, NULL, 15);
static struct attribute *fan_dev_attrs[] = {
- &sensor_dev_attr_fan0_input.dev_attr.attr,
&sensor_dev_attr_fan1_input.dev_attr.attr,
&sensor_dev_attr_fan2_input.dev_attr.attr,
&sensor_dev_attr_fan3_input.dev_attr.attr,
@@ -673,6 +678,7 @@ static struct attribute *fan_dev_attrs[] = {
&sensor_dev_attr_fan13_input.dev_attr.attr,
&sensor_dev_attr_fan14_input.dev_attr.attr,
&sensor_dev_attr_fan15_input.dev_attr.attr,
+ &sensor_dev_attr_fan16_input.dev_attr.attr,
NULL
};
@@ -802,7 +808,6 @@ static int aspeed_pwm_tacho_probe(struct platform_device *pdev)
if (ret)
return ret;
}
- of_node_put(np);
priv->groups[0] = &pwm_dev_group;
priv->groups[1] = &fan_dev_group;
diff --git a/drivers/hwtracing/coresight/coresight-etm3x.c b/drivers/hwtracing/coresight/coresight-etm3x.c
index a51b6b64ecdf..93ee8fc539be 100644
--- a/drivers/hwtracing/coresight/coresight-etm3x.c
+++ b/drivers/hwtracing/coresight/coresight-etm3x.c
@@ -587,7 +587,7 @@ static void etm_disable_sysfs(struct coresight_device *csdev)
* after cpu online mask indicates the cpu is offline but before the
* DYING hotplug callback is serviced by the ETM driver.
*/
- get_online_cpus();
+ cpus_read_lock();
spin_lock(&drvdata->spinlock);
/*
@@ -597,7 +597,7 @@ static void etm_disable_sysfs(struct coresight_device *csdev)
smp_call_function_single(drvdata->cpu, etm_disable_hw, drvdata, 1);
spin_unlock(&drvdata->spinlock);
- put_online_cpus();
+ cpus_read_unlock();
dev_info(drvdata->dev, "ETM tracing disabled\n");
}
@@ -795,7 +795,7 @@ static int etm_probe(struct amba_device *adev, const struct amba_id *id)
drvdata->cpu = pdata ? pdata->cpu : 0;
- get_online_cpus();
+ cpus_read_lock();
etmdrvdata[drvdata->cpu] = drvdata;
if (smp_call_function_single(drvdata->cpu,
@@ -803,17 +803,17 @@ static int etm_probe(struct amba_device *adev, const struct amba_id *id)
dev_err(dev, "ETM arch init failed\n");
if (!etm_count++) {
- cpuhp_setup_state_nocalls(CPUHP_AP_ARM_CORESIGHT_STARTING,
- "arm/coresight:starting",
- etm_starting_cpu, etm_dying_cpu);
- ret = cpuhp_setup_state_nocalls(CPUHP_AP_ONLINE_DYN,
- "arm/coresight:online",
- etm_online_cpu, NULL);
+ cpuhp_setup_state_nocalls_cpuslocked(CPUHP_AP_ARM_CORESIGHT_STARTING,
+ "arm/coresight:starting",
+ etm_starting_cpu, etm_dying_cpu);
+ ret = cpuhp_setup_state_nocalls_cpuslocked(CPUHP_AP_ONLINE_DYN,
+ "arm/coresight:online",
+ etm_online_cpu, NULL);
if (ret < 0)
goto err_arch_supported;
hp_online = ret;
}
- put_online_cpus();
+ cpus_read_unlock();
if (etm_arch_supported(drvdata->arch) == false) {
ret = -EINVAL;
diff --git a/drivers/hwtracing/coresight/coresight-etm4x.c b/drivers/hwtracing/coresight/coresight-etm4x.c
index d1340fb4e457..532adc9dd32a 100644
--- a/drivers/hwtracing/coresight/coresight-etm4x.c
+++ b/drivers/hwtracing/coresight/coresight-etm4x.c
@@ -371,7 +371,7 @@ static void etm4_disable_sysfs(struct coresight_device *csdev)
* after cpu online mask indicates the cpu is offline but before the
* DYING hotplug callback is serviced by the ETM driver.
*/
- get_online_cpus();
+ cpus_read_lock();
spin_lock(&drvdata->spinlock);
/*
@@ -381,7 +381,7 @@ static void etm4_disable_sysfs(struct coresight_device *csdev)
smp_call_function_single(drvdata->cpu, etm4_disable_hw, drvdata, 1);
spin_unlock(&drvdata->spinlock);
- put_online_cpus();
+ cpus_read_unlock();
dev_info(drvdata->dev, "ETM tracing disabled\n");
}
@@ -982,7 +982,7 @@ static int etm4_probe(struct amba_device *adev, const struct amba_id *id)
drvdata->cpu = pdata ? pdata->cpu : 0;
- get_online_cpus();
+ cpus_read_lock();
etmdrvdata[drvdata->cpu] = drvdata;
if (smp_call_function_single(drvdata->cpu,
@@ -990,18 +990,18 @@ static int etm4_probe(struct amba_device *adev, const struct amba_id *id)
dev_err(dev, "ETM arch init failed\n");
if (!etm4_count++) {
- cpuhp_setup_state_nocalls(CPUHP_AP_ARM_CORESIGHT_STARTING,
- "arm/coresight4:starting",
- etm4_starting_cpu, etm4_dying_cpu);
- ret = cpuhp_setup_state_nocalls(CPUHP_AP_ONLINE_DYN,
- "arm/coresight4:online",
- etm4_online_cpu, NULL);
+ cpuhp_setup_state_nocalls_cpuslocked(CPUHP_AP_ARM_CORESIGHT_STARTING,
+ "arm/coresight4:starting",
+ etm4_starting_cpu, etm4_dying_cpu);
+ ret = cpuhp_setup_state_nocalls_cpuslocked(CPUHP_AP_ONLINE_DYN,
+ "arm/coresight4:online",
+ etm4_online_cpu, NULL);
if (ret < 0)
goto err_arch_supported;
hp_online = ret;
}
- put_online_cpus();
+ cpus_read_unlock();
if (etm4_arch_supported(drvdata->arch) == false) {
ret = -EINVAL;
diff --git a/drivers/i2c/busses/i2c-designware-platdrv.c b/drivers/i2c/busses/i2c-designware-platdrv.c
index 6283b99d2b17..d1263b82d646 100644
--- a/drivers/i2c/busses/i2c-designware-platdrv.c
+++ b/drivers/i2c/busses/i2c-designware-platdrv.c
@@ -94,9 +94,9 @@ static void dw_i2c_acpi_params(struct platform_device *pdev, char method[],
static int dw_i2c_acpi_configure(struct platform_device *pdev)
{
struct dw_i2c_dev *dev = platform_get_drvdata(pdev);
+ u32 ss_ht = 0, fp_ht = 0, hs_ht = 0, fs_ht = 0;
acpi_handle handle = ACPI_HANDLE(&pdev->dev);
const struct acpi_device_id *id;
- u32 ss_ht, fp_ht, hs_ht, fs_ht;
struct acpi_device *adev;
const char *uid;
diff --git a/drivers/i2c/busses/i2c-imx.c b/drivers/i2c/busses/i2c-imx.c
index 95ed17183e73..54a47b40546f 100644
--- a/drivers/i2c/busses/i2c-imx.c
+++ b/drivers/i2c/busses/i2c-imx.c
@@ -734,9 +734,9 @@ static int i2c_imx_dma_read(struct imx_i2c_struct *i2c_imx,
* the first read operation, otherwise the first read cost
* one extra clock cycle.
*/
- temp = readb(i2c_imx->base + IMX_I2C_I2CR);
+ temp = imx_i2c_read_reg(i2c_imx, IMX_I2C_I2CR);
temp |= I2CR_MTX;
- writeb(temp, i2c_imx->base + IMX_I2C_I2CR);
+ imx_i2c_write_reg(temp, i2c_imx, IMX_I2C_I2CR);
}
msgs->buf[msgs->len-1] = imx_i2c_read_reg(i2c_imx, IMX_I2C_I2DR);
@@ -857,9 +857,9 @@ static int i2c_imx_read(struct imx_i2c_struct *i2c_imx, struct i2c_msg *msgs, bo
* the first read operation, otherwise the first read cost
* one extra clock cycle.
*/
- temp = readb(i2c_imx->base + IMX_I2C_I2CR);
+ temp = imx_i2c_read_reg(i2c_imx, IMX_I2C_I2CR);
temp |= I2CR_MTX;
- writeb(temp, i2c_imx->base + IMX_I2C_I2CR);
+ imx_i2c_write_reg(temp, i2c_imx, IMX_I2C_I2CR);
}
} else if (i == (msgs->len - 2)) {
dev_dbg(&i2c_imx->adapter.dev,
diff --git a/drivers/i2c/busses/i2c-ismt.c b/drivers/i2c/busses/i2c-ismt.c
index f573448d2132..e98e44e584a4 100644
--- a/drivers/i2c/busses/i2c-ismt.c
+++ b/drivers/i2c/busses/i2c-ismt.c
@@ -584,7 +584,7 @@ static int ismt_access(struct i2c_adapter *adap, u16 addr,
/* unmap the data buffer */
if (dma_size != 0)
- dma_unmap_single(&adap->dev, dma_addr, dma_size, dma_direction);
+ dma_unmap_single(dev, dma_addr, dma_size, dma_direction);
if (unlikely(!time_left)) {
dev_err(dev, "completion wait timed out\n");
diff --git a/drivers/i2c/busses/i2c-rcar.c b/drivers/i2c/busses/i2c-rcar.c
index 214bf2835d1f..8be3e6cb8fe6 100644
--- a/drivers/i2c/busses/i2c-rcar.c
+++ b/drivers/i2c/busses/i2c-rcar.c
@@ -319,7 +319,7 @@ static void rcar_i2c_dma_unmap(struct rcar_i2c_priv *priv)
rcar_i2c_write(priv, ICFBSCR, TCYC06);
dma_unmap_single(chan->device->dev, sg_dma_address(&priv->sg),
- priv->msg->len, priv->dma_direction);
+ sg_dma_len(&priv->sg), priv->dma_direction);
priv->dma_direction = DMA_NONE;
}
diff --git a/drivers/i2c/busses/i2c-tiny-usb.c b/drivers/i2c/busses/i2c-tiny-usb.c
index 0ed77eeff31e..a2e3dd715380 100644
--- a/drivers/i2c/busses/i2c-tiny-usb.c
+++ b/drivers/i2c/busses/i2c-tiny-usb.c
@@ -178,22 +178,39 @@ static int usb_read(struct i2c_adapter *adapter, int cmd,
int value, int index, void *data, int len)
{
struct i2c_tiny_usb *dev = (struct i2c_tiny_usb *)adapter->algo_data;
+ void *dmadata = kmalloc(len, GFP_KERNEL);
+ int ret;
+
+ if (!dmadata)
+ return -ENOMEM;
/* do control transfer */
- return usb_control_msg(dev->usb_dev, usb_rcvctrlpipe(dev->usb_dev, 0),
+ ret = usb_control_msg(dev->usb_dev, usb_rcvctrlpipe(dev->usb_dev, 0),
cmd, USB_TYPE_VENDOR | USB_RECIP_INTERFACE |
- USB_DIR_IN, value, index, data, len, 2000);
+ USB_DIR_IN, value, index, dmadata, len, 2000);
+
+ memcpy(data, dmadata, len);
+ kfree(dmadata);
+ return ret;
}
static int usb_write(struct i2c_adapter *adapter, int cmd,
int value, int index, void *data, int len)
{
struct i2c_tiny_usb *dev = (struct i2c_tiny_usb *)adapter->algo_data;
+ void *dmadata = kmemdup(data, len, GFP_KERNEL);
+ int ret;
+
+ if (!dmadata)
+ return -ENOMEM;
/* do control transfer */
- return usb_control_msg(dev->usb_dev, usb_sndctrlpipe(dev->usb_dev, 0),
+ ret = usb_control_msg(dev->usb_dev, usb_sndctrlpipe(dev->usb_dev, 0),
cmd, USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
- value, index, data, len, 2000);
+ value, index, dmadata, len, 2000);
+
+ kfree(dmadata);
+ return ret;
}
static void i2c_tiny_usb_free(struct i2c_tiny_usb *dev)
diff --git a/drivers/ide/ide-atapi.c b/drivers/ide/ide-atapi.c
index 5901937284e7..14d1e7d9a1d6 100644
--- a/drivers/ide/ide-atapi.c
+++ b/drivers/ide/ide-atapi.c
@@ -93,7 +93,6 @@ int ide_queue_pc_tail(ide_drive_t *drive, struct gendisk *disk,
int error;
rq = blk_get_request(drive->queue, REQ_OP_DRV_IN, __GFP_RECLAIM);
- scsi_req_init(rq);
ide_req(rq)->type = ATA_PRIV_MISC;
rq->special = (char *)pc;
@@ -200,7 +199,7 @@ void ide_prep_sense(ide_drive_t *drive, struct request *rq)
memset(sense, 0, sizeof(*sense));
blk_rq_init(rq->q, sense_rq);
- scsi_req_init(sense_rq);
+ scsi_req_init(req);
err = blk_rq_map_kern(drive->queue, sense_rq, sense, sense_len,
GFP_NOIO);
@@ -273,7 +272,7 @@ void ide_retry_pc(ide_drive_t *drive)
ide_requeue_and_plug(drive, failed_rq);
if (ide_queue_sense_rq(drive, pc)) {
blk_start_request(failed_rq);
- ide_complete_rq(drive, -EIO, blk_rq_bytes(failed_rq));
+ ide_complete_rq(drive, BLK_STS_IOERR, blk_rq_bytes(failed_rq));
}
}
EXPORT_SYMBOL_GPL(ide_retry_pc);
@@ -437,7 +436,8 @@ static ide_startstop_t ide_pc_intr(ide_drive_t *drive)
/* No more interrupts */
if ((stat & ATA_DRQ) == 0) {
- int uptodate, error;
+ int uptodate;
+ blk_status_t error;
debug_log("Packet command completed, %d bytes transferred\n",
blk_rq_bytes(rq));
@@ -490,7 +490,7 @@ static ide_startstop_t ide_pc_intr(ide_drive_t *drive)
if (ata_misc_request(rq)) {
scsi_req(rq)->result = 0;
- error = 0;
+ error = BLK_STS_OK;
} else {
if (blk_rq_is_passthrough(rq) && uptodate <= 0) {
@@ -498,7 +498,7 @@ static ide_startstop_t ide_pc_intr(ide_drive_t *drive)
scsi_req(rq)->result = -EIO;
}
- error = uptodate ? 0 : -EIO;
+ error = uptodate ? BLK_STS_OK : BLK_STS_IOERR;
}
ide_complete_rq(drive, error, blk_rq_bytes(rq));
diff --git a/drivers/ide/ide-cd.c b/drivers/ide/ide-cd.c
index 07e5ff3a64c3..81e18f9628d0 100644
--- a/drivers/ide/ide-cd.c
+++ b/drivers/ide/ide-cd.c
@@ -228,7 +228,7 @@ static void ide_cd_complete_failed_rq(ide_drive_t *drive, struct request *rq)
scsi_req(failed)->sense_len = scsi_req(rq)->sense_len;
cdrom_analyze_sense_data(drive, failed);
- if (ide_end_rq(drive, failed, -EIO, blk_rq_bytes(failed)))
+ if (ide_end_rq(drive, failed, BLK_STS_IOERR, blk_rq_bytes(failed)))
BUG();
} else
cdrom_analyze_sense_data(drive, NULL);
@@ -438,7 +438,6 @@ int ide_cd_queue_pc(ide_drive_t *drive, const unsigned char *cmd,
rq = blk_get_request(drive->queue,
write ? REQ_OP_DRV_OUT : REQ_OP_DRV_IN, __GFP_RECLAIM);
- scsi_req_init(rq);
memcpy(scsi_req(rq)->cmd, cmd, BLK_MAX_CDB);
ide_req(rq)->type = ATA_PRIV_PC;
rq->rq_flags |= rq_flags;
@@ -508,7 +507,7 @@ static bool ide_cd_error_cmd(ide_drive_t *drive, struct ide_cmd *cmd)
nr_bytes -= cmd->last_xfer_len;
if (nr_bytes > 0) {
- ide_complete_rq(drive, 0, nr_bytes);
+ ide_complete_rq(drive, BLK_STS_OK, nr_bytes);
return true;
}
@@ -674,7 +673,7 @@ static ide_startstop_t cdrom_newpc_intr(ide_drive_t *drive)
out_end:
if (blk_rq_is_scsi(rq) && rc == 0) {
scsi_req(rq)->resid_len = 0;
- blk_end_request_all(rq, 0);
+ blk_end_request_all(rq, BLK_STS_OK);
hwif->rq = NULL;
} else {
if (sense && uptodate)
@@ -699,7 +698,7 @@ out_end:
scsi_req(rq)->resid_len += cmd->last_xfer_len;
}
- ide_complete_rq(drive, uptodate ? 0 : -EIO, blk_rq_bytes(rq));
+ ide_complete_rq(drive, uptodate ? BLK_STS_OK : BLK_STS_IOERR, blk_rq_bytes(rq));
if (sense && rc == 2)
ide_error(drive, "request sense failure", stat);
@@ -844,7 +843,7 @@ out_end:
if (nsectors == 0)
nsectors = 1;
- ide_complete_rq(drive, uptodate ? 0 : -EIO, nsectors << 9);
+ ide_complete_rq(drive, uptodate ? BLK_STS_OK : BLK_STS_IOERR, nsectors << 9);
return ide_stopped;
}
diff --git a/drivers/ide/ide-cd_ioctl.c b/drivers/ide/ide-cd_ioctl.c
index 55cd736c39c6..9d26c9737e21 100644
--- a/drivers/ide/ide-cd_ioctl.c
+++ b/drivers/ide/ide-cd_ioctl.c
@@ -304,7 +304,6 @@ int ide_cdrom_reset(struct cdrom_device_info *cdi)
int ret;
rq = blk_get_request(drive->queue, REQ_OP_DRV_IN, __GFP_RECLAIM);
- scsi_req_init(rq);
ide_req(rq)->type = ATA_PRIV_MISC;
rq->rq_flags = RQF_QUIET;
blk_execute_rq(drive->queue, cd->disk, rq, 0);
diff --git a/drivers/ide/ide-devsets.c b/drivers/ide/ide-devsets.c
index 9b69c32ee560..ef7c8c43a380 100644
--- a/drivers/ide/ide-devsets.c
+++ b/drivers/ide/ide-devsets.c
@@ -166,7 +166,6 @@ int ide_devset_execute(ide_drive_t *drive, const struct ide_devset *setting,
return setting->set(drive, arg);
rq = blk_get_request(q, REQ_OP_DRV_IN, __GFP_RECLAIM);
- scsi_req_init(rq);
ide_req(rq)->type = ATA_PRIV_MISC;
scsi_req(rq)->cmd_len = 5;
scsi_req(rq)->cmd[0] = REQ_DEVSET_EXEC;
diff --git a/drivers/ide/ide-disk.c b/drivers/ide/ide-disk.c
index 7c06237f3479..241983da5fc4 100644
--- a/drivers/ide/ide-disk.c
+++ b/drivers/ide/ide-disk.c
@@ -478,7 +478,6 @@ static int set_multcount(ide_drive_t *drive, int arg)
return -EBUSY;
rq = blk_get_request(drive->queue, REQ_OP_DRV_IN, __GFP_RECLAIM);
- scsi_req_init(rq);
ide_req(rq)->type = ATA_PRIV_TASKFILE;
drive->mult_req = arg;
diff --git a/drivers/ide/ide-dma.c b/drivers/ide/ide-dma.c
index 51c81223e56d..54d4d78ca46a 100644
--- a/drivers/ide/ide-dma.c
+++ b/drivers/ide/ide-dma.c
@@ -104,7 +104,7 @@ ide_startstop_t ide_dma_intr(ide_drive_t *drive)
if ((cmd->tf_flags & IDE_TFLAG_FS) == 0)
ide_finish_cmd(drive, cmd, stat);
else
- ide_complete_rq(drive, 0,
+ ide_complete_rq(drive, BLK_STS_OK,
blk_rq_sectors(cmd->rq) << 9);
return ide_stopped;
}
diff --git a/drivers/ide/ide-eh.c b/drivers/ide/ide-eh.c
index 4b7ffd7d158d..47d5f3379748 100644
--- a/drivers/ide/ide-eh.c
+++ b/drivers/ide/ide-eh.c
@@ -135,7 +135,7 @@ ide_startstop_t ide_error(ide_drive_t *drive, const char *msg, u8 stat)
return ide_stopped;
}
scsi_req(rq)->result = err;
- ide_complete_rq(drive, err ? -EIO : 0, blk_rq_bytes(rq));
+ ide_complete_rq(drive, err ? BLK_STS_IOERR : BLK_STS_OK, blk_rq_bytes(rq));
return ide_stopped;
}
@@ -143,7 +143,7 @@ ide_startstop_t ide_error(ide_drive_t *drive, const char *msg, u8 stat)
}
EXPORT_SYMBOL_GPL(ide_error);
-static inline void ide_complete_drive_reset(ide_drive_t *drive, int err)
+static inline void ide_complete_drive_reset(ide_drive_t *drive, blk_status_t err)
{
struct request *rq = drive->hwif->rq;
@@ -151,7 +151,7 @@ static inline void ide_complete_drive_reset(ide_drive_t *drive, int err)
scsi_req(rq)->cmd[0] == REQ_DRIVE_RESET) {
if (err <= 0 && scsi_req(rq)->result == 0)
scsi_req(rq)->result = -EIO;
- ide_complete_rq(drive, err ? err : 0, blk_rq_bytes(rq));
+ ide_complete_rq(drive, err, blk_rq_bytes(rq));
}
}
@@ -191,7 +191,7 @@ static ide_startstop_t atapi_reset_pollfunc(ide_drive_t *drive)
}
/* done polling */
hwif->polling = 0;
- ide_complete_drive_reset(drive, 0);
+ ide_complete_drive_reset(drive, BLK_STS_OK);
return ide_stopped;
}
@@ -225,7 +225,7 @@ static ide_startstop_t reset_pollfunc(ide_drive_t *drive)
ide_hwif_t *hwif = drive->hwif;
const struct ide_port_ops *port_ops = hwif->port_ops;
u8 tmp;
- int err = 0;
+ blk_status_t err = BLK_STS_OK;
if (port_ops && port_ops->reset_poll) {
err = port_ops->reset_poll(drive);
@@ -247,7 +247,7 @@ static ide_startstop_t reset_pollfunc(ide_drive_t *drive)
printk(KERN_ERR "%s: reset timed-out, status=0x%02x\n",
hwif->name, tmp);
drive->failures++;
- err = -EIO;
+ err = BLK_STS_IOERR;
} else {
tmp = ide_read_error(drive);
@@ -257,7 +257,7 @@ static ide_startstop_t reset_pollfunc(ide_drive_t *drive)
} else {
ide_reset_report_error(hwif, tmp);
drive->failures++;
- err = -EIO;
+ err = BLK_STS_IOERR;
}
}
out:
@@ -392,7 +392,7 @@ static ide_startstop_t do_reset1(ide_drive_t *drive, int do_not_try_atapi)
if (io_ports->ctl_addr == 0) {
spin_unlock_irqrestore(&hwif->lock, flags);
- ide_complete_drive_reset(drive, -ENXIO);
+ ide_complete_drive_reset(drive, BLK_STS_IOERR);
return ide_stopped;
}
diff --git a/drivers/ide/ide-floppy.c b/drivers/ide/ide-floppy.c
index 8ac6048cd2df..627b1f62a749 100644
--- a/drivers/ide/ide-floppy.c
+++ b/drivers/ide/ide-floppy.c
@@ -143,7 +143,7 @@ static ide_startstop_t ide_floppy_issue_pc(ide_drive_t *drive,
drive->failed_pc = NULL;
drive->pc_callback(drive, 0);
- ide_complete_rq(drive, -EIO, done);
+ ide_complete_rq(drive, BLK_STS_IOERR, done);
return ide_stopped;
}
@@ -248,7 +248,7 @@ static ide_startstop_t ide_floppy_do_request(ide_drive_t *drive,
if (ata_misc_request(rq)) {
scsi_req(rq)->result = 0;
- ide_complete_rq(drive, 0, blk_rq_bytes(rq));
+ ide_complete_rq(drive, BLK_STS_OK, blk_rq_bytes(rq));
return ide_stopped;
} else
goto out_end;
@@ -303,7 +303,7 @@ out_end:
drive->failed_pc = NULL;
if (blk_rq_is_passthrough(rq) && scsi_req(rq)->result == 0)
scsi_req(rq)->result = -EIO;
- ide_complete_rq(drive, -EIO, blk_rq_bytes(rq));
+ ide_complete_rq(drive, BLK_STS_IOERR, blk_rq_bytes(rq));
return ide_stopped;
}
diff --git a/drivers/ide/ide-io.c b/drivers/ide/ide-io.c
index 323af721f8cb..3a234701d92c 100644
--- a/drivers/ide/ide-io.c
+++ b/drivers/ide/ide-io.c
@@ -54,7 +54,7 @@
#include <linux/uaccess.h>
#include <asm/io.h>
-int ide_end_rq(ide_drive_t *drive, struct request *rq, int error,
+int ide_end_rq(ide_drive_t *drive, struct request *rq, blk_status_t error,
unsigned int nr_bytes)
{
/*
@@ -112,7 +112,7 @@ void ide_complete_cmd(ide_drive_t *drive, struct ide_cmd *cmd, u8 stat, u8 err)
}
}
-int ide_complete_rq(ide_drive_t *drive, int error, unsigned int nr_bytes)
+int ide_complete_rq(ide_drive_t *drive, blk_status_t error, unsigned int nr_bytes)
{
ide_hwif_t *hwif = drive->hwif;
struct request *rq = hwif->rq;
@@ -122,7 +122,7 @@ int ide_complete_rq(ide_drive_t *drive, int error, unsigned int nr_bytes)
* if failfast is set on a request, override number of sectors
* and complete the whole request right now
*/
- if (blk_noretry_request(rq) && error <= 0)
+ if (blk_noretry_request(rq) && error)
nr_bytes = blk_rq_sectors(rq) << 9;
rc = ide_end_rq(drive, rq, error, nr_bytes);
@@ -149,7 +149,7 @@ void ide_kill_rq(ide_drive_t *drive, struct request *rq)
scsi_req(rq)->result = -EIO;
}
- ide_complete_rq(drive, -EIO, blk_rq_bytes(rq));
+ ide_complete_rq(drive, BLK_STS_IOERR, blk_rq_bytes(rq));
}
static void ide_tf_set_specify_cmd(ide_drive_t *drive, struct ide_taskfile *tf)
@@ -272,7 +272,7 @@ static ide_startstop_t execute_drive_cmd (ide_drive_t *drive,
printk("%s: DRIVE_CMD (null)\n", drive->name);
#endif
scsi_req(rq)->result = 0;
- ide_complete_rq(drive, 0, blk_rq_bytes(rq));
+ ide_complete_rq(drive, BLK_STS_OK, blk_rq_bytes(rq));
return ide_stopped;
}
diff --git a/drivers/ide/ide-ioctls.c b/drivers/ide/ide-ioctls.c
index 8c0d17297a7a..3661abb16a5f 100644
--- a/drivers/ide/ide-ioctls.c
+++ b/drivers/ide/ide-ioctls.c
@@ -126,7 +126,6 @@ static int ide_cmd_ioctl(ide_drive_t *drive, unsigned long arg)
struct request *rq;
rq = blk_get_request(drive->queue, REQ_OP_DRV_IN, __GFP_RECLAIM);
- scsi_req_init(rq);
ide_req(rq)->type = ATA_PRIV_TASKFILE;
blk_execute_rq(drive->queue, NULL, rq, 0);
err = scsi_req(rq)->result ? -EIO : 0;
@@ -224,7 +223,6 @@ static int generic_drive_reset(ide_drive_t *drive)
int ret = 0;
rq = blk_get_request(drive->queue, REQ_OP_DRV_IN, __GFP_RECLAIM);
- scsi_req_init(rq);
ide_req(rq)->type = ATA_PRIV_MISC;
scsi_req(rq)->cmd_len = 1;
scsi_req(rq)->cmd[0] = REQ_DRIVE_RESET;
diff --git a/drivers/ide/ide-park.c b/drivers/ide/ide-park.c
index 94e3107f59b9..1f264d5d3f3f 100644
--- a/drivers/ide/ide-park.c
+++ b/drivers/ide/ide-park.c
@@ -32,7 +32,6 @@ static void issue_park_cmd(ide_drive_t *drive, unsigned long timeout)
spin_unlock_irq(&hwif->lock);
rq = blk_get_request(q, REQ_OP_DRV_IN, __GFP_RECLAIM);
- scsi_req_init(rq);
scsi_req(rq)->cmd[0] = REQ_PARK_HEADS;
scsi_req(rq)->cmd_len = 1;
ide_req(rq)->type = ATA_PRIV_MISC;
@@ -48,7 +47,6 @@ static void issue_park_cmd(ide_drive_t *drive, unsigned long timeout)
* timeout has expired, so power management will be reenabled.
*/
rq = blk_get_request(q, REQ_OP_DRV_IN, GFP_NOWAIT);
- scsi_req_init(rq);
if (IS_ERR(rq))
goto out;
diff --git a/drivers/ide/ide-pm.c b/drivers/ide/ide-pm.c
index 0977fc1f40ce..544f02d673ca 100644
--- a/drivers/ide/ide-pm.c
+++ b/drivers/ide/ide-pm.c
@@ -19,7 +19,6 @@ int generic_ide_suspend(struct device *dev, pm_message_t mesg)
memset(&rqpm, 0, sizeof(rqpm));
rq = blk_get_request(drive->queue, REQ_OP_DRV_IN, __GFP_RECLAIM);
- scsi_req_init(rq);
ide_req(rq)->type = ATA_PRIV_PM_SUSPEND;
rq->special = &rqpm;
rqpm.pm_step = IDE_PM_START_SUSPEND;
@@ -40,7 +39,7 @@ int generic_ide_suspend(struct device *dev, pm_message_t mesg)
return ret;
}
-static void ide_end_sync_rq(struct request *rq, int error)
+static void ide_end_sync_rq(struct request *rq, blk_status_t error)
{
complete(rq->end_io_data);
}
@@ -57,7 +56,7 @@ static int ide_pm_execute_rq(struct request *rq)
if (unlikely(blk_queue_dying(q))) {
rq->rq_flags |= RQF_QUIET;
scsi_req(rq)->result = -ENXIO;
- __blk_end_request_all(rq, 0);
+ __blk_end_request_all(rq, BLK_STS_OK);
spin_unlock_irq(q->queue_lock);
return -ENXIO;
}
@@ -91,7 +90,6 @@ int generic_ide_resume(struct device *dev)
memset(&rqpm, 0, sizeof(rqpm));
rq = blk_get_request(drive->queue, REQ_OP_DRV_IN, __GFP_RECLAIM);
- scsi_req_init(rq);
ide_req(rq)->type = ATA_PRIV_PM_RESUME;
rq->rq_flags |= RQF_PREEMPT;
rq->special = &rqpm;
@@ -235,7 +233,7 @@ void ide_complete_pm_rq(ide_drive_t *drive, struct request *rq)
drive->hwif->rq = NULL;
- if (blk_end_request(rq, 0, 0))
+ if (blk_end_request(rq, BLK_STS_OK, 0))
BUG();
}
diff --git a/drivers/ide/ide-probe.c b/drivers/ide/ide-probe.c
index 023562565d11..01b2adfd8226 100644
--- a/drivers/ide/ide-probe.c
+++ b/drivers/ide/ide-probe.c
@@ -741,12 +741,12 @@ static void ide_port_tune_devices(ide_hwif_t *hwif)
}
}
-static int ide_init_rq(struct request_queue *q, struct request *rq, gfp_t gfp)
+static void ide_initialize_rq(struct request *rq)
{
struct ide_request *req = blk_mq_rq_to_pdu(rq);
+ scsi_req_init(&req->sreq);
req->sreq.sense = req->sense;
- return 0;
}
/*
@@ -771,8 +771,9 @@ static int ide_init_queue(ide_drive_t *drive)
return 1;
q->request_fn = do_ide_request;
- q->init_rq_fn = ide_init_rq;
+ q->initialize_rq_fn = ide_initialize_rq;
q->cmd_size = sizeof(struct ide_request);
+ queue_flag_set_unlocked(QUEUE_FLAG_SCSI_PASSTHROUGH, q);
if (blk_init_allocated_queue(q) < 0) {
blk_cleanup_queue(q);
return 1;
diff --git a/drivers/ide/ide-tape.c b/drivers/ide/ide-tape.c
index a0651f948b76..fd57e8ccc47a 100644
--- a/drivers/ide/ide-tape.c
+++ b/drivers/ide/ide-tape.c
@@ -474,7 +474,7 @@ static ide_startstop_t ide_tape_issue_pc(ide_drive_t *drive,
drive->failed_pc = NULL;
drive->pc_callback(drive, 0);
- ide_complete_rq(drive, -EIO, blk_rq_bytes(rq));
+ ide_complete_rq(drive, BLK_STS_IOERR, blk_rq_bytes(rq));
return ide_stopped;
}
ide_debug_log(IDE_DBG_SENSE, "retry #%d, cmd: 0x%02x", pc->retries,
@@ -855,7 +855,6 @@ static int idetape_queue_rw_tail(ide_drive_t *drive, int cmd, int size)
BUG_ON(size < 0 || size % tape->blk_size);
rq = blk_get_request(drive->queue, REQ_OP_DRV_IN, __GFP_RECLAIM);
- scsi_req_init(rq);
ide_req(rq)->type = ATA_PRIV_MISC;
scsi_req(rq)->cmd[13] = cmd;
rq->rq_disk = tape->disk;
diff --git a/drivers/ide/ide-taskfile.c b/drivers/ide/ide-taskfile.c
index d71199d23c9e..4efe4c6e956c 100644
--- a/drivers/ide/ide-taskfile.c
+++ b/drivers/ide/ide-taskfile.c
@@ -318,7 +318,7 @@ static void ide_error_cmd(ide_drive_t *drive, struct ide_cmd *cmd)
}
if (nr_bytes > 0)
- ide_complete_rq(drive, 0, nr_bytes);
+ ide_complete_rq(drive, BLK_STS_OK, nr_bytes);
}
}
@@ -336,7 +336,7 @@ void ide_finish_cmd(ide_drive_t *drive, struct ide_cmd *cmd, u8 stat)
ide_driveid_update(drive);
}
- ide_complete_rq(drive, err ? -EIO : 0, blk_rq_bytes(rq));
+ ide_complete_rq(drive, err ? BLK_STS_IOERR : BLK_STS_OK, blk_rq_bytes(rq));
}
/*
@@ -394,7 +394,7 @@ out_end:
if ((cmd->tf_flags & IDE_TFLAG_FS) == 0)
ide_finish_cmd(drive, cmd, stat);
else
- ide_complete_rq(drive, 0, blk_rq_sectors(cmd->rq) << 9);
+ ide_complete_rq(drive, BLK_STS_OK, blk_rq_sectors(cmd->rq) << 9);
return ide_stopped;
out_err:
ide_error_cmd(drive, cmd);
@@ -433,7 +433,6 @@ int ide_raw_taskfile(ide_drive_t *drive, struct ide_cmd *cmd, u8 *buf,
rq = blk_get_request(drive->queue,
(cmd->tf_flags & IDE_TFLAG_WRITE) ?
REQ_OP_DRV_OUT : REQ_OP_DRV_IN, __GFP_RECLAIM);
- scsi_req_init(rq);
ide_req(rq)->type = ATA_PRIV_TASKFILE;
/*
diff --git a/drivers/ide/siimage.c b/drivers/ide/siimage.c
index 6a1849bb476c..57eea5a9047f 100644
--- a/drivers/ide/siimage.c
+++ b/drivers/ide/siimage.c
@@ -406,7 +406,7 @@ static int siimage_dma_test_irq(ide_drive_t *drive)
* yet.
*/
-static int sil_sata_reset_poll(ide_drive_t *drive)
+static blk_status_t sil_sata_reset_poll(ide_drive_t *drive)
{
ide_hwif_t *hwif = drive->hwif;
void __iomem *sata_status_addr
@@ -419,11 +419,11 @@ static int sil_sata_reset_poll(ide_drive_t *drive)
if ((sata_stat & 0x03) != 0x03) {
printk(KERN_WARNING "%s: reset phy dead, status=0x%08x\n",
hwif->name, sata_stat);
- return -ENXIO;
+ return BLK_STS_IOERR;
}
}
- return 0;
+ return BLK_STS_OK;
}
/**
diff --git a/drivers/iio/accel/hid-sensor-accel-3d.c b/drivers/iio/accel/hid-sensor-accel-3d.c
index 43a6cb078193..2238a26aba63 100644
--- a/drivers/iio/accel/hid-sensor-accel-3d.c
+++ b/drivers/iio/accel/hid-sensor-accel-3d.c
@@ -347,7 +347,7 @@ static int accel_3d_parse_report(struct platform_device *pdev,
static int hid_accel_3d_probe(struct platform_device *pdev)
{
int ret = 0;
- static const char *name;
+ const char *name;
struct iio_dev *indio_dev;
struct accel_3d_state *accel_state;
const struct iio_chan_spec *channel_spec;
diff --git a/drivers/iio/accel/mma9551.c b/drivers/iio/accel/mma9551.c
index bf2704435629..1f53f08476f5 100644
--- a/drivers/iio/accel/mma9551.c
+++ b/drivers/iio/accel/mma9551.c
@@ -27,7 +27,6 @@
#define MMA9551_DRV_NAME "mma9551"
#define MMA9551_IRQ_NAME "mma9551_event"
-#define MMA9551_GPIO_NAME "mma9551_int"
#define MMA9551_GPIO_COUNT 4
/* Tilt application (inclination in IIO terms). */
@@ -418,8 +417,7 @@ static int mma9551_gpio_probe(struct iio_dev *indio_dev)
struct device *dev = &data->client->dev;
for (i = 0; i < MMA9551_GPIO_COUNT; i++) {
- gpio = devm_gpiod_get_index(dev, MMA9551_GPIO_NAME, i,
- GPIOD_IN);
+ gpio = devm_gpiod_get_index(dev, NULL, i, GPIOD_IN);
if (IS_ERR(gpio)) {
dev_err(dev, "acpi gpio get index failed\n");
return PTR_ERR(gpio);
diff --git a/drivers/iio/accel/st_accel_core.c b/drivers/iio/accel/st_accel_core.c
index 784670e2736b..07d1489cd457 100644
--- a/drivers/iio/accel/st_accel_core.c
+++ b/drivers/iio/accel/st_accel_core.c
@@ -710,6 +710,8 @@ static const struct iio_trigger_ops st_accel_trigger_ops = {
int st_accel_common_probe(struct iio_dev *indio_dev)
{
struct st_sensor_data *adata = iio_priv(indio_dev);
+ struct st_sensors_platform_data *pdata =
+ (struct st_sensors_platform_data *)adata->dev->platform_data;
int irq = adata->get_irq_data_ready(indio_dev);
int err;
@@ -736,9 +738,8 @@ int st_accel_common_probe(struct iio_dev *indio_dev)
&adata->sensor_settings->fs.fs_avl[0];
adata->odr = adata->sensor_settings->odr.odr_avl[0].hz;
- if (!adata->dev->platform_data)
- adata->dev->platform_data =
- (struct st_sensors_platform_data *)&default_accel_pdata;
+ if (!pdata)
+ pdata = (struct st_sensors_platform_data *)&default_accel_pdata;
err = st_sensors_init_sensor(indio_dev, adata->dev->platform_data);
if (err < 0)
diff --git a/drivers/iio/accel/st_accel_spi.c b/drivers/iio/accel/st_accel_spi.c
index 29a15f27a51b..1a867f5563a4 100644
--- a/drivers/iio/accel/st_accel_spi.c
+++ b/drivers/iio/accel/st_accel_spi.c
@@ -47,15 +47,11 @@ static int st_accel_spi_remove(struct spi_device *spi)
}
static const struct spi_device_id st_accel_id_table[] = {
- { LSM303DLH_ACCEL_DEV_NAME },
- { LSM303DLHC_ACCEL_DEV_NAME },
{ LIS3DH_ACCEL_DEV_NAME },
{ LSM330D_ACCEL_DEV_NAME },
{ LSM330DL_ACCEL_DEV_NAME },
{ LSM330DLC_ACCEL_DEV_NAME },
{ LIS331DLH_ACCEL_DEV_NAME },
- { LSM303DL_ACCEL_DEV_NAME },
- { LSM303DLM_ACCEL_DEV_NAME },
{ LSM330_ACCEL_DEV_NAME },
{ LSM303AGR_ACCEL_DEV_NAME },
{ LIS2DH12_ACCEL_DEV_NAME },
diff --git a/drivers/iio/adc/Kconfig b/drivers/iio/adc/Kconfig
index 401f47b51d83..614fa41559b1 100644
--- a/drivers/iio/adc/Kconfig
+++ b/drivers/iio/adc/Kconfig
@@ -679,6 +679,18 @@ config TI_ADC0832
This driver can also be built as a module. If so, the module will be
called ti-adc0832.
+config TI_ADC084S021
+ tristate "Texas Instruments ADC084S021"
+ depends on SPI
+ select IIO_BUFFER
+ select IIO_TRIGGERED_BUFFER
+ help
+ If you say yes here you get support for Texas Instruments ADC084S021
+ chips.
+
+ This driver can also be built as a module. If so, the module will be
+ called ti-adc084s021.
+
config TI_ADC12138
tristate "Texas Instruments ADC12130/ADC12132/ADC12138"
depends on SPI
@@ -691,6 +703,18 @@ config TI_ADC12138
This driver can also be built as a module. If so, the module will be
called ti-adc12138.
+config TI_ADC108S102
+ tristate "Texas Instruments ADC108S102 and ADC128S102 driver"
+ depends on SPI
+ select IIO_BUFFER
+ select IIO_TRIGGERED_BUFFER
+ help
+ Say yes here to build support for Texas Instruments ADC108S102 and
+ ADC128S102 ADC.
+
+ To compile this driver as a module, choose M here: the module will
+ be called ti-adc108s102.
+
config TI_ADC128S052
tristate "Texas Instruments ADC128S052/ADC122S021/ADC124S021"
depends on SPI
diff --git a/drivers/iio/adc/Makefile b/drivers/iio/adc/Makefile
index 9339bec4babe..b546736a5541 100644
--- a/drivers/iio/adc/Makefile
+++ b/drivers/iio/adc/Makefile
@@ -62,7 +62,9 @@ obj-$(CONFIG_STM32_ADC_CORE) += stm32-adc-core.o
obj-$(CONFIG_STM32_ADC) += stm32-adc.o
obj-$(CONFIG_TI_ADC081C) += ti-adc081c.o
obj-$(CONFIG_TI_ADC0832) += ti-adc0832.o
+obj-$(CONFIG_TI_ADC084S021) += ti-adc084s021.o
obj-$(CONFIG_TI_ADC12138) += ti-adc12138.o
+obj-$(CONFIG_TI_ADC108S102) += ti-adc108s102.o
obj-$(CONFIG_TI_ADC128S052) += ti-adc128s052.o
obj-$(CONFIG_TI_ADC161S626) += ti-adc161s626.o
obj-$(CONFIG_TI_ADS1015) += ti-ads1015.o
diff --git a/drivers/iio/adc/ad7791.c b/drivers/iio/adc/ad7791.c
index 1817ebf5ad84..34e353c43ac8 100644
--- a/drivers/iio/adc/ad7791.c
+++ b/drivers/iio/adc/ad7791.c
@@ -272,11 +272,9 @@ static ssize_t ad7791_write_frequency(struct device *dev,
struct ad7791_state *st = iio_priv(indio_dev);
int i, ret;
- for (i = 0; i < ARRAY_SIZE(ad7791_sample_freq_avail); i++)
- if (sysfs_streq(ad7791_sample_freq_avail[i], buf))
- break;
- if (i == ARRAY_SIZE(ad7791_sample_freq_avail))
- return -EINVAL;
+ i = sysfs_match_string(ad7791_sample_freq_avail, buf);
+ if (i < 0)
+ return i;
ret = iio_device_claim_direct_mode(indio_dev);
if (ret)
diff --git a/drivers/iio/adc/aspeed_adc.c b/drivers/iio/adc/aspeed_adc.c
index 62670cbfa2bb..e0ea411a0b2d 100644
--- a/drivers/iio/adc/aspeed_adc.c
+++ b/drivers/iio/adc/aspeed_adc.c
@@ -212,7 +212,10 @@ static int aspeed_adc_probe(struct platform_device *pdev)
}
/* Start all channels in normal mode. */
- clk_prepare_enable(data->clk_scaler->clk);
+ ret = clk_prepare_enable(data->clk_scaler->clk);
+ if (ret)
+ goto clk_enable_error;
+
adc_engine_control_reg_val = GENMASK(31, 16) |
ASPEED_OPERATION_MODE_NORMAL | ASPEED_ENGINE_ENABLE;
writel(adc_engine_control_reg_val,
@@ -236,6 +239,7 @@ iio_register_error:
writel(ASPEED_OPERATION_MODE_POWER_DOWN,
data->base + ASPEED_REG_ENGINE_CONTROL);
clk_disable_unprepare(data->clk_scaler->clk);
+clk_enable_error:
clk_hw_unregister_divider(data->clk_scaler);
scaler_error:
diff --git a/drivers/iio/adc/bcm_iproc_adc.c b/drivers/iio/adc/bcm_iproc_adc.c
index 21d38c8af21e..7f4f9c4150e3 100644
--- a/drivers/iio/adc/bcm_iproc_adc.c
+++ b/drivers/iio/adc/bcm_iproc_adc.c
@@ -143,7 +143,7 @@ static void iproc_adc_reg_dump(struct iio_dev *indio_dev)
iproc_adc_dbg_reg(dev, adc_priv, IPROC_SOFT_BYPASS_DATA);
}
-static irqreturn_t iproc_adc_interrupt_handler(int irq, void *data)
+static irqreturn_t iproc_adc_interrupt_thread(int irq, void *data)
{
u32 channel_intr_status;
u32 intr_status;
@@ -167,7 +167,7 @@ static irqreturn_t iproc_adc_interrupt_handler(int irq, void *data)
return IRQ_NONE;
}
-static irqreturn_t iproc_adc_interrupt_thread(int irq, void *data)
+static irqreturn_t iproc_adc_interrupt_handler(int irq, void *data)
{
irqreturn_t retval = IRQ_NONE;
struct iproc_adc_priv *adc_priv;
@@ -181,7 +181,7 @@ static irqreturn_t iproc_adc_interrupt_thread(int irq, void *data)
adc_priv = iio_priv(indio_dev);
regmap_read(adc_priv->regmap, IPROC_INTERRUPT_STATUS, &intr_status);
- dev_dbg(&indio_dev->dev, "iproc_adc_interrupt_thread(),INTRPT_STS:%x\n",
+ dev_dbg(&indio_dev->dev, "iproc_adc_interrupt_handler(),INTRPT_STS:%x\n",
intr_status);
intr_channels = (intr_status & IPROC_ADC_INTR_MASK) >> IPROC_ADC_INTR;
@@ -566,8 +566,8 @@ static int iproc_adc_probe(struct platform_device *pdev)
}
ret = devm_request_threaded_irq(&pdev->dev, adc_priv->irqno,
- iproc_adc_interrupt_thread,
iproc_adc_interrupt_handler,
+ iproc_adc_interrupt_thread,
IRQF_SHARED, "iproc-adc", indio_dev);
if (ret) {
dev_err(&pdev->dev, "request_irq error %d\n", ret);
diff --git a/drivers/iio/adc/cpcap-adc.c b/drivers/iio/adc/cpcap-adc.c
index 62d37f8725b8..6e419d5a7c14 100644
--- a/drivers/iio/adc/cpcap-adc.c
+++ b/drivers/iio/adc/cpcap-adc.c
@@ -52,6 +52,10 @@
#define CPCAP_BIT_RAND0 BIT(1) /* Set with CAL_MODE */
#define CPCAP_BIT_ADEN BIT(0) /* Currently unused */
+#define CPCAP_REG_ADCC1_DEFAULTS (CPCAP_BIT_ADEN_AUTO_CLR | \
+ CPCAP_BIT_ADC_CLK_SEL0 | \
+ CPCAP_BIT_RAND1)
+
/* Register CPCAP_REG_ADCC2 bits */
#define CPCAP_BIT_CAL_FACTOR_ENABLE BIT(15) /* Currently unused */
#define CPCAP_BIT_BATDETB_EN BIT(14) /* Currently unused */
@@ -62,7 +66,7 @@
#define CPCAP_BIT_ADC_PS_FACTOR0 BIT(9)
#define CPCAP_BIT_AD4_SELECT BIT(8) /* Currently unused */
#define CPCAP_BIT_ADC_BUSY BIT(7) /* Currently unused */
-#define CPCAP_BIT_THERMBIAS_EN BIT(6) /* Currently unused */
+#define CPCAP_BIT_THERMBIAS_EN BIT(6) /* Bias for AD0_BATTDETB */
#define CPCAP_BIT_ADTRIG_DIS BIT(5) /* Disable interrupt */
#define CPCAP_BIT_LIADC BIT(4) /* Currently unused */
#define CPCAP_BIT_TS_REFEN BIT(3) /* Currently unused */
@@ -70,6 +74,12 @@
#define CPCAP_BIT_TS_M1 BIT(1) /* Currently unused */
#define CPCAP_BIT_TS_M0 BIT(0) /* Currently unused */
+#define CPCAP_REG_ADCC2_DEFAULTS (CPCAP_BIT_AD4_SELECT | \
+ CPCAP_BIT_ADTRIG_DIS | \
+ CPCAP_BIT_LIADC | \
+ CPCAP_BIT_TS_M2 | \
+ CPCAP_BIT_TS_M1)
+
#define CPCAP_MAX_TEMP_LVL 27
#define CPCAP_FOUR_POINT_TWO_ADC 801
#define ST_ADC_CAL_CHRGI_HIGH_THRESHOLD 530
@@ -78,7 +88,7 @@
#define ST_ADC_CAL_BATTI_LOW_THRESHOLD 494
#define ST_ADC_CALIBRATE_DIFF_THRESHOLD 3
-#define CPCAP_ADC_MAX_RETRIES 5 /* Calibration and quirk */
+#define CPCAP_ADC_MAX_RETRIES 5 /* Calibration */
/**
* struct cpcap_adc_ato - timing settings for cpcap adc
@@ -124,10 +134,10 @@ struct cpcap_adc {
*/
enum cpcap_adc_channel {
/* Bank0 channels */
- CPCAP_ADC_AD0_BATTDETB, /* Battery detection */
+ CPCAP_ADC_AD0, /* Battery temperature */
CPCAP_ADC_BATTP, /* Battery voltage */
CPCAP_ADC_VBUS, /* USB VBUS voltage */
- CPCAP_ADC_AD3, /* Battery temperature when charging */
+ CPCAP_ADC_AD3, /* Die temperature when charging */
CPCAP_ADC_BPLUS_AD4, /* Another battery or system voltage */
CPCAP_ADC_CHG_ISENSE, /* Calibrated charge current */
CPCAP_ADC_BATTI, /* Calibrated system current */
@@ -217,7 +227,7 @@ struct cpcap_adc_request {
/* Phasing table for channels. Note that channels 16 & 17 use BATTP and BATTI */
static const struct cpcap_adc_phasing_tbl bank_phasing[] = {
/* Bank0 */
- [CPCAP_ADC_AD0_BATTDETB] = {0, 0x80, 0x80, 0, 1023},
+ [CPCAP_ADC_AD0] = {0, 0x80, 0x80, 0, 1023},
[CPCAP_ADC_BATTP] = {0, 0x80, 0x80, 0, 1023},
[CPCAP_ADC_VBUS] = {0, 0x80, 0x80, 0, 1023},
[CPCAP_ADC_AD3] = {0, 0x80, 0x80, 0, 1023},
@@ -243,7 +253,7 @@ static const struct cpcap_adc_phasing_tbl bank_phasing[] = {
*/
static struct cpcap_adc_conversion_tbl bank_conversion[] = {
/* Bank0 */
- [CPCAP_ADC_AD0_BATTDETB] = {
+ [CPCAP_ADC_AD0] = {
IIO_CHAN_INFO_PROCESSED, 0, 0, 0, 1, 1,
},
[CPCAP_ADC_BATTP] = {
@@ -541,6 +551,15 @@ static void cpcap_adc_setup_bank(struct cpcap_adc *ddata,
return;
switch (req->channel) {
+ case CPCAP_ADC_AD0:
+ value2 |= CPCAP_BIT_THERMBIAS_EN;
+ error = regmap_update_bits(ddata->reg, CPCAP_REG_ADCC2,
+ CPCAP_BIT_THERMBIAS_EN,
+ value2);
+ if (error)
+ return;
+ usleep_range(800, 1000);
+ break;
case CPCAP_ADC_AD8 ... CPCAP_ADC_TSY2_AD15:
value1 |= CPCAP_BIT_AD_SEL1;
break;
@@ -583,7 +602,8 @@ static void cpcap_adc_setup_bank(struct cpcap_adc *ddata,
error = regmap_update_bits(ddata->reg, CPCAP_REG_ADCC2,
CPCAP_BIT_ATOX_PS_FACTOR |
CPCAP_BIT_ADC_PS_FACTOR1 |
- CPCAP_BIT_ADC_PS_FACTOR0,
+ CPCAP_BIT_ADC_PS_FACTOR0 |
+ CPCAP_BIT_THERMBIAS_EN,
value2);
if (error)
return;
@@ -614,27 +634,6 @@ static void cpcap_adc_setup_bank(struct cpcap_adc *ddata,
}
}
-/*
- * Occasionally the ADC does not seem to start and there will be no
- * interrupt. Let's re-init interrupt to prevent the ADC from hanging
- * for the next request. It is unclear why this happens, but the next
- * request will usually work after doing this.
- */
-static void cpcap_adc_quirk_reset_lost_irq(struct cpcap_adc *ddata)
-{
- int error;
-
- dev_info(ddata->dev, "lost ADC irq, attempting to reinit\n");
- disable_irq(ddata->irq);
- error = regmap_update_bits(ddata->reg, CPCAP_REG_ADCC2,
- CPCAP_BIT_ADTRIG_DIS,
- CPCAP_BIT_ADTRIG_DIS);
- if (error)
- dev_warn(ddata->dev, "%s reset failed: %i\n",
- __func__, error);
- enable_irq(ddata->irq);
-}
-
static int cpcap_adc_start_bank(struct cpcap_adc *ddata,
struct cpcap_adc_request *req)
{
@@ -652,7 +651,6 @@ static int cpcap_adc_start_bank(struct cpcap_adc *ddata,
return 0;
if (error == 0) {
- cpcap_adc_quirk_reset_lost_irq(ddata);
error = -ETIMEDOUT;
continue;
}
@@ -664,6 +662,21 @@ static int cpcap_adc_start_bank(struct cpcap_adc *ddata,
return error;
}
+static int cpcap_adc_stop_bank(struct cpcap_adc *ddata)
+{
+ int error;
+
+ error = regmap_update_bits(ddata->reg, CPCAP_REG_ADCC1,
+ 0xffff,
+ CPCAP_REG_ADCC1_DEFAULTS);
+ if (error)
+ return error;
+
+ return regmap_update_bits(ddata->reg, CPCAP_REG_ADCC2,
+ 0xffff,
+ CPCAP_REG_ADCC2_DEFAULTS);
+}
+
static void cpcap_adc_phase(struct cpcap_adc_request *req)
{
const struct cpcap_adc_conversion_tbl *conv_tbl = req->conv_tbl;
@@ -758,7 +771,7 @@ static void cpcap_adc_convert(struct cpcap_adc_request *req)
return;
/* Temperatures use a lookup table instead of conversion table */
- if ((req->channel == CPCAP_ADC_AD0_BATTDETB) ||
+ if ((req->channel == CPCAP_ADC_AD0) ||
(req->channel == CPCAP_ADC_AD3)) {
req->result =
cpcap_adc_table_to_millicelcius(req->result);
@@ -820,7 +833,7 @@ static int cpcap_adc_init_request(struct cpcap_adc_request *req,
req->conv_tbl = bank_conversion;
switch (channel) {
- case CPCAP_ADC_AD0_BATTDETB ... CPCAP_ADC_USB_ID:
+ case CPCAP_ADC_AD0 ... CPCAP_ADC_USB_ID:
req->bank_index = channel;
break;
case CPCAP_ADC_AD8 ... CPCAP_ADC_TSY2_AD15:
@@ -839,6 +852,22 @@ static int cpcap_adc_init_request(struct cpcap_adc_request *req,
return 0;
}
+static int cpcap_adc_read_st_die_temp(struct cpcap_adc *ddata,
+ int addr, int *val)
+{
+ int error;
+
+ error = regmap_read(ddata->reg, addr, val);
+ if (error)
+ return error;
+
+ *val -= 282;
+ *val *= 114;
+ *val += 25000;
+
+ return 0;
+}
+
static int cpcap_adc_read(struct iio_dev *indio_dev,
struct iio_chan_spec const *chan,
int *val, int *val2, long mask)
@@ -860,6 +889,9 @@ static int cpcap_adc_read(struct iio_dev *indio_dev,
error = regmap_read(ddata->reg, chan->address, val);
if (error)
goto err_unlock;
+ error = cpcap_adc_stop_bank(ddata);
+ if (error)
+ goto err_unlock;
mutex_unlock(&ddata->lock);
break;
case IIO_CHAN_INFO_PROCESSED:
@@ -867,7 +899,19 @@ static int cpcap_adc_read(struct iio_dev *indio_dev,
error = cpcap_adc_start_bank(ddata, &req);
if (error)
goto err_unlock;
- error = cpcap_adc_read_bank_scaled(ddata, &req);
+ if ((ddata->vendor == CPCAP_VENDOR_ST) &&
+ (chan->channel == CPCAP_ADC_AD3)) {
+ error = cpcap_adc_read_st_die_temp(ddata,
+ chan->address,
+ &req.result);
+ if (error)
+ goto err_unlock;
+ } else {
+ error = cpcap_adc_read_bank_scaled(ddata, &req);
+ if (error)
+ goto err_unlock;
+ }
+ error = cpcap_adc_stop_bank(ddata);
if (error)
goto err_unlock;
mutex_unlock(&ddata->lock);
diff --git a/drivers/iio/adc/hi8435.c b/drivers/iio/adc/hi8435.c
index 678e8c7ea763..adf7dc712937 100644
--- a/drivers/iio/adc/hi8435.c
+++ b/drivers/iio/adc/hi8435.c
@@ -105,6 +105,26 @@ static int hi8435_writew(struct hi8435_priv *priv, u8 reg, u16 val)
return spi_write(priv->spi, priv->reg_buffer, 3);
}
+static int hi8435_read_raw(struct iio_dev *idev,
+ const struct iio_chan_spec *chan,
+ int *val, int *val2, long mask)
+{
+ struct hi8435_priv *priv = iio_priv(idev);
+ u32 tmp;
+ int ret;
+
+ switch (mask) {
+ case IIO_CHAN_INFO_RAW:
+ ret = hi8435_readl(priv, HI8435_SO31_0_REG, &tmp);
+ if (ret < 0)
+ return ret;
+ *val = !!(tmp & BIT(chan->channel));
+ return IIO_VAL_INT;
+ default:
+ return -EINVAL;
+ }
+}
+
static int hi8435_read_event_config(struct iio_dev *idev,
const struct iio_chan_spec *chan,
enum iio_event_type type,
@@ -121,10 +141,21 @@ static int hi8435_write_event_config(struct iio_dev *idev,
enum iio_event_direction dir, int state)
{
struct hi8435_priv *priv = iio_priv(idev);
+ int ret;
+ u32 tmp;
+
+ if (state) {
+ ret = hi8435_readl(priv, HI8435_SO31_0_REG, &tmp);
+ if (ret < 0)
+ return ret;
+ if (tmp & BIT(chan->channel))
+ priv->event_prev_val |= BIT(chan->channel);
+ else
+ priv->event_prev_val &= ~BIT(chan->channel);
- priv->event_scan_mask &= ~BIT(chan->channel);
- if (state)
priv->event_scan_mask |= BIT(chan->channel);
+ } else
+ priv->event_scan_mask &= ~BIT(chan->channel);
return 0;
}
@@ -325,6 +356,7 @@ static const struct iio_enum hi8435_sensing_mode = {
static const struct iio_chan_spec_ext_info hi8435_ext_info[] = {
IIO_ENUM("sensing_mode", IIO_SEPARATE, &hi8435_sensing_mode),
+ IIO_ENUM_AVAILABLE("sensing_mode", &hi8435_sensing_mode),
{},
};
@@ -333,6 +365,7 @@ static const struct iio_chan_spec_ext_info hi8435_ext_info[] = {
.type = IIO_VOLTAGE, \
.indexed = 1, \
.channel = num, \
+ .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \
.event_spec = hi8435_events, \
.num_event_specs = ARRAY_SIZE(hi8435_events), \
.ext_info = hi8435_ext_info, \
@@ -376,11 +409,12 @@ static const struct iio_chan_spec hi8435_channels[] = {
static const struct iio_info hi8435_info = {
.driver_module = THIS_MODULE,
- .read_event_config = &hi8435_read_event_config,
+ .read_raw = hi8435_read_raw,
+ .read_event_config = hi8435_read_event_config,
.write_event_config = hi8435_write_event_config,
- .read_event_value = &hi8435_read_event_value,
- .write_event_value = &hi8435_write_event_value,
- .debugfs_reg_access = &hi8435_debugfs_reg_access,
+ .read_event_value = hi8435_read_event_value,
+ .write_event_value = hi8435_write_event_value,
+ .debugfs_reg_access = hi8435_debugfs_reg_access,
};
static void hi8435_iio_push_event(struct iio_dev *idev, unsigned int val)
diff --git a/drivers/iio/adc/ina2xx-adc.c b/drivers/iio/adc/ina2xx-adc.c
index db9838230257..232c0b80d658 100644
--- a/drivers/iio/adc/ina2xx-adc.c
+++ b/drivers/iio/adc/ina2xx-adc.c
@@ -42,13 +42,14 @@
#define INA2XX_CURRENT 0x04 /* readonly */
#define INA2XX_CALIBRATION 0x05
-#define INA226_ALERT_MASK GENMASK(2, 1)
-#define INA266_CVRF BIT(3)
+#define INA226_MASK_ENABLE 0x06
+#define INA226_CVRF BIT(3)
#define INA2XX_MAX_REGISTERS 8
/* settings - depend on use case */
#define INA219_CONFIG_DEFAULT 0x399F /* PGA=8 */
+#define INA219_DEFAULT_IT 532
#define INA226_CONFIG_DEFAULT 0x4327
#define INA226_DEFAULT_AVG 4
#define INA226_DEFAULT_IT 1110
@@ -56,19 +57,24 @@
#define INA2XX_RSHUNT_DEFAULT 10000
/*
- * bit mask for reading the averaging setting in the configuration register
+ * bit masks for reading the settings in the configuration register
* FIXME: use regmap_fields.
*/
#define INA2XX_MODE_MASK GENMASK(3, 0)
+/* Averaging for VBus/VShunt/Power */
#define INA226_AVG_MASK GENMASK(11, 9)
#define INA226_SHIFT_AVG(val) ((val) << 9)
/* Integration time for VBus */
+#define INA219_ITB_MASK GENMASK(10, 7)
+#define INA219_SHIFT_ITB(val) ((val) << 7)
#define INA226_ITB_MASK GENMASK(8, 6)
#define INA226_SHIFT_ITB(val) ((val) << 6)
/* Integration time for VShunt */
+#define INA219_ITS_MASK GENMASK(6, 3)
+#define INA219_SHIFT_ITS(val) ((val) << 3)
#define INA226_ITS_MASK GENMASK(5, 3)
#define INA226_SHIFT_ITS(val) ((val) << 3)
@@ -108,6 +114,7 @@ struct ina2xx_config {
int bus_voltage_shift;
int bus_voltage_lsb; /* uV */
int power_lsb; /* uW */
+ enum ina2xx_ids chip_id;
};
struct ina2xx_chip_info {
@@ -130,6 +137,7 @@ static const struct ina2xx_config ina2xx_config[] = {
.bus_voltage_shift = 3,
.bus_voltage_lsb = 4000,
.power_lsb = 20000,
+ .chip_id = ina219,
},
[ina226] = {
.config_default = INA226_CONFIG_DEFAULT,
@@ -138,6 +146,7 @@ static const struct ina2xx_config ina2xx_config[] = {
.bus_voltage_shift = 0,
.bus_voltage_lsb = 1250,
.power_lsb = 25000,
+ .chip_id = ina226,
},
};
@@ -283,6 +292,66 @@ static int ina226_set_int_time_vshunt(struct ina2xx_chip_info *chip,
return 0;
}
+/* Conversion times in uS. */
+static const int ina219_conv_time_tab_subsample[] = { 84, 148, 276, 532 };
+static const int ina219_conv_time_tab_average[] = { 532, 1060, 2130, 4260,
+ 8510, 17020, 34050, 68100};
+
+static int ina219_lookup_int_time(unsigned int *val_us, int *bits)
+{
+ if (*val_us > 68100 || *val_us < 84)
+ return -EINVAL;
+
+ if (*val_us <= 532) {
+ *bits = find_closest(*val_us, ina219_conv_time_tab_subsample,
+ ARRAY_SIZE(ina219_conv_time_tab_subsample));
+ *val_us = ina219_conv_time_tab_subsample[*bits];
+ } else {
+ *bits = find_closest(*val_us, ina219_conv_time_tab_average,
+ ARRAY_SIZE(ina219_conv_time_tab_average));
+ *val_us = ina219_conv_time_tab_average[*bits];
+ *bits |= 0x8;
+ }
+
+ return 0;
+}
+
+static int ina219_set_int_time_vbus(struct ina2xx_chip_info *chip,
+ unsigned int val_us, unsigned int *config)
+{
+ int bits, ret;
+ unsigned int val_us_best = val_us;
+
+ ret = ina219_lookup_int_time(&val_us_best, &bits);
+ if (ret)
+ return ret;
+
+ chip->int_time_vbus = val_us_best;
+
+ *config &= ~INA219_ITB_MASK;
+ *config |= INA219_SHIFT_ITB(bits) & INA219_ITB_MASK;
+
+ return 0;
+}
+
+static int ina219_set_int_time_vshunt(struct ina2xx_chip_info *chip,
+ unsigned int val_us, unsigned int *config)
+{
+ int bits, ret;
+ unsigned int val_us_best = val_us;
+
+ ret = ina219_lookup_int_time(&val_us_best, &bits);
+ if (ret)
+ return ret;
+
+ chip->int_time_vshunt = val_us_best;
+
+ *config &= ~INA219_ITS_MASK;
+ *config |= INA219_SHIFT_ITS(bits) & INA219_ITS_MASK;
+
+ return 0;
+}
+
static int ina2xx_write_raw(struct iio_dev *indio_dev,
struct iio_chan_spec const *chan,
int val, int val2, long mask)
@@ -308,10 +377,21 @@ static int ina2xx_write_raw(struct iio_dev *indio_dev,
break;
case IIO_CHAN_INFO_INT_TIME:
- if (chan->address == INA2XX_SHUNT_VOLTAGE)
- ret = ina226_set_int_time_vshunt(chip, val2, &tmp);
- else
- ret = ina226_set_int_time_vbus(chip, val2, &tmp);
+ if (chip->config->chip_id == ina226) {
+ if (chan->address == INA2XX_SHUNT_VOLTAGE)
+ ret = ina226_set_int_time_vshunt(chip, val2,
+ &tmp);
+ else
+ ret = ina226_set_int_time_vbus(chip, val2,
+ &tmp);
+ } else {
+ if (chan->address == INA2XX_SHUNT_VOLTAGE)
+ ret = ina219_set_int_time_vshunt(chip, val2,
+ &tmp);
+ else
+ ret = ina219_set_int_time_vbus(chip, val2,
+ &tmp);
+ }
break;
default:
@@ -412,13 +492,30 @@ static ssize_t ina2xx_shunt_resistor_store(struct device *dev,
return len;
}
-#define INA2XX_CHAN(_type, _index, _address) { \
+#define INA219_CHAN(_type, _index, _address) { \
+ .type = (_type), \
+ .address = (_address), \
+ .indexed = 1, \
+ .channel = (_index), \
+ .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | \
+ BIT(IIO_CHAN_INFO_SCALE), \
+ .info_mask_shared_by_dir = BIT(IIO_CHAN_INFO_SAMP_FREQ), \
+ .scan_index = (_index), \
+ .scan_type = { \
+ .sign = 'u', \
+ .realbits = 16, \
+ .storagebits = 16, \
+ .endianness = IIO_CPU, \
+ } \
+}
+
+#define INA226_CHAN(_type, _index, _address) { \
.type = (_type), \
.address = (_address), \
.indexed = 1, \
.channel = (_index), \
- .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) \
- | BIT(IIO_CHAN_INFO_SCALE), \
+ .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | \
+ BIT(IIO_CHAN_INFO_SCALE), \
.info_mask_shared_by_dir = BIT(IIO_CHAN_INFO_SAMP_FREQ) | \
BIT(IIO_CHAN_INFO_OVERSAMPLING_RATIO), \
.scan_index = (_index), \
@@ -434,7 +531,25 @@ static ssize_t ina2xx_shunt_resistor_store(struct device *dev,
* Sampling Freq is a consequence of the integration times of
* the Voltage channels.
*/
-#define INA2XX_CHAN_VOLTAGE(_index, _address) { \
+#define INA219_CHAN_VOLTAGE(_index, _address) { \
+ .type = IIO_VOLTAGE, \
+ .address = (_address), \
+ .indexed = 1, \
+ .channel = (_index), \
+ .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | \
+ BIT(IIO_CHAN_INFO_SCALE) | \
+ BIT(IIO_CHAN_INFO_INT_TIME), \
+ .info_mask_shared_by_dir = BIT(IIO_CHAN_INFO_SAMP_FREQ), \
+ .scan_index = (_index), \
+ .scan_type = { \
+ .sign = 'u', \
+ .realbits = 16, \
+ .storagebits = 16, \
+ .endianness = IIO_LE, \
+ } \
+}
+
+#define INA226_CHAN_VOLTAGE(_index, _address) { \
.type = IIO_VOLTAGE, \
.address = (_address), \
.indexed = 1, \
@@ -442,6 +557,8 @@ static ssize_t ina2xx_shunt_resistor_store(struct device *dev,
.info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | \
BIT(IIO_CHAN_INFO_SCALE) | \
BIT(IIO_CHAN_INFO_INT_TIME), \
+ .info_mask_shared_by_dir = BIT(IIO_CHAN_INFO_SAMP_FREQ) | \
+ BIT(IIO_CHAN_INFO_OVERSAMPLING_RATIO), \
.scan_index = (_index), \
.scan_type = { \
.sign = 'u', \
@@ -451,11 +568,20 @@ static ssize_t ina2xx_shunt_resistor_store(struct device *dev,
} \
}
-static const struct iio_chan_spec ina2xx_channels[] = {
- INA2XX_CHAN_VOLTAGE(0, INA2XX_SHUNT_VOLTAGE),
- INA2XX_CHAN_VOLTAGE(1, INA2XX_BUS_VOLTAGE),
- INA2XX_CHAN(IIO_POWER, 2, INA2XX_POWER),
- INA2XX_CHAN(IIO_CURRENT, 3, INA2XX_CURRENT),
+
+static const struct iio_chan_spec ina226_channels[] = {
+ INA226_CHAN_VOLTAGE(0, INA2XX_SHUNT_VOLTAGE),
+ INA226_CHAN_VOLTAGE(1, INA2XX_BUS_VOLTAGE),
+ INA226_CHAN(IIO_POWER, 2, INA2XX_POWER),
+ INA226_CHAN(IIO_CURRENT, 3, INA2XX_CURRENT),
+ IIO_CHAN_SOFT_TIMESTAMP(4),
+};
+
+static const struct iio_chan_spec ina219_channels[] = {
+ INA219_CHAN_VOLTAGE(0, INA2XX_SHUNT_VOLTAGE),
+ INA219_CHAN_VOLTAGE(1, INA2XX_BUS_VOLTAGE),
+ INA219_CHAN(IIO_POWER, 2, INA2XX_POWER),
+ INA219_CHAN(IIO_CURRENT, 3, INA2XX_CURRENT),
IIO_CHAN_SOFT_TIMESTAMP(4),
};
@@ -481,12 +607,12 @@ static int ina2xx_work_buffer(struct iio_dev *indio_dev)
*/
if (!chip->allow_async_readout)
do {
- ret = regmap_read(chip->regmap, INA226_ALERT_MASK,
+ ret = regmap_read(chip->regmap, INA226_MASK_ENABLE,
&alert);
if (ret < 0)
return ret;
- alert &= INA266_CVRF;
+ alert &= INA226_CVRF;
} while (!alert);
/*
@@ -590,7 +716,14 @@ static int ina2xx_debug_reg(struct iio_dev *indio_dev,
}
/* Possible integration times for vshunt and vbus */
-static IIO_CONST_ATTR_INT_TIME_AVAIL("0.000140 0.000204 0.000332 0.000588 0.001100 0.002116 0.004156 0.008244");
+static IIO_CONST_ATTR_NAMED(ina219_integration_time_available,
+ integration_time_available,
+ "0.000084 0.000148 0.000276 0.000532 0.001060 0.002130 0.004260 0.008510 0.017020 0.034050 0.068100");
+
+static IIO_CONST_ATTR_NAMED(ina226_integration_time_available,
+ integration_time_available,
+ "0.000140 0.000204 0.000332 0.000588 0.001100 0.002116 0.004156 0.008244");
+
static IIO_DEVICE_ATTR(in_allow_async_readout, S_IRUGO | S_IWUSR,
ina2xx_allow_async_readout_show,
@@ -600,20 +733,39 @@ static IIO_DEVICE_ATTR(in_shunt_resistor, S_IRUGO | S_IWUSR,
ina2xx_shunt_resistor_show,
ina2xx_shunt_resistor_store, 0);
-static struct attribute *ina2xx_attributes[] = {
+static struct attribute *ina219_attributes[] = {
+ &iio_dev_attr_in_allow_async_readout.dev_attr.attr,
+ &iio_const_attr_ina219_integration_time_available.dev_attr.attr,
+ &iio_dev_attr_in_shunt_resistor.dev_attr.attr,
+ NULL,
+};
+
+static struct attribute *ina226_attributes[] = {
&iio_dev_attr_in_allow_async_readout.dev_attr.attr,
- &iio_const_attr_integration_time_available.dev_attr.attr,
+ &iio_const_attr_ina226_integration_time_available.dev_attr.attr,
&iio_dev_attr_in_shunt_resistor.dev_attr.attr,
NULL,
};
-static const struct attribute_group ina2xx_attribute_group = {
- .attrs = ina2xx_attributes,
+static const struct attribute_group ina219_attribute_group = {
+ .attrs = ina219_attributes,
+};
+
+static const struct attribute_group ina226_attribute_group = {
+ .attrs = ina226_attributes,
};
-static const struct iio_info ina2xx_info = {
+static const struct iio_info ina219_info = {
.driver_module = THIS_MODULE,
- .attrs = &ina2xx_attribute_group,
+ .attrs = &ina219_attribute_group,
+ .read_raw = ina2xx_read_raw,
+ .write_raw = ina2xx_write_raw,
+ .debugfs_reg_access = ina2xx_debug_reg,
+};
+
+static const struct iio_info ina226_info = {
+ .driver_module = THIS_MODULE,
+ .attrs = &ina226_attribute_group,
.read_raw = ina2xx_read_raw,
.write_raw = ina2xx_write_raw,
.debugfs_reg_access = ina2xx_debug_reg,
@@ -684,6 +836,10 @@ static int ina2xx_probe(struct i2c_client *client,
ina226_set_average(chip, INA226_DEFAULT_AVG, &val);
ina226_set_int_time_vbus(chip, INA226_DEFAULT_IT, &val);
ina226_set_int_time_vshunt(chip, INA226_DEFAULT_IT, &val);
+ } else {
+ chip->avg = 1;
+ ina219_set_int_time_vbus(chip, INA219_DEFAULT_IT, &val);
+ ina219_set_int_time_vshunt(chip, INA219_DEFAULT_IT, &val);
}
ret = ina2xx_init(chip, val);
@@ -695,10 +851,16 @@ static int ina2xx_probe(struct i2c_client *client,
indio_dev->modes = INDIO_DIRECT_MODE | INDIO_BUFFER_SOFTWARE;
indio_dev->dev.parent = &client->dev;
indio_dev->dev.of_node = client->dev.of_node;
- indio_dev->channels = ina2xx_channels;
- indio_dev->num_channels = ARRAY_SIZE(ina2xx_channels);
+ if (id->driver_data == ina226) {
+ indio_dev->channels = ina226_channels;
+ indio_dev->num_channels = ARRAY_SIZE(ina226_channels);
+ indio_dev->info = &ina226_info;
+ } else {
+ indio_dev->channels = ina219_channels;
+ indio_dev->num_channels = ARRAY_SIZE(ina219_channels);
+ indio_dev->info = &ina219_info;
+ }
indio_dev->name = id->name;
- indio_dev->info = &ina2xx_info;
indio_dev->setup_ops = &ina2xx_setup_ops;
buffer = devm_iio_kfifo_allocate(&indio_dev->dev);
diff --git a/drivers/iio/adc/lpc32xx_adc.c b/drivers/iio/adc/lpc32xx_adc.c
index 0de709b4288b..6a5b9a9bc662 100644
--- a/drivers/iio/adc/lpc32xx_adc.c
+++ b/drivers/iio/adc/lpc32xx_adc.c
@@ -76,10 +76,14 @@ static int lpc32xx_read_raw(struct iio_dev *indio_dev,
long mask)
{
struct lpc32xx_adc_state *st = iio_priv(indio_dev);
-
+ int ret;
if (mask == IIO_CHAN_INFO_RAW) {
mutex_lock(&indio_dev->mlock);
- clk_prepare_enable(st->clk);
+ ret = clk_prepare_enable(st->clk);
+ if (ret) {
+ mutex_unlock(&indio_dev->mlock);
+ return ret;
+ }
/* Measurement setup */
__raw_writel(LPC32XXAD_INTERNAL | (chan->address) |
LPC32XXAD_REFp | LPC32XXAD_REFm,
diff --git a/drivers/iio/adc/max9611.c b/drivers/iio/adc/max9611.c
index ec82106480e1..b0526e4b9530 100644
--- a/drivers/iio/adc/max9611.c
+++ b/drivers/iio/adc/max9611.c
@@ -438,10 +438,10 @@ static ssize_t max9611_shunt_resistor_show(struct device *dev,
struct max9611_dev *max9611 = iio_priv(dev_to_iio_dev(dev));
unsigned int i, r;
- i = max9611->shunt_resistor_uohm / 1000;
- r = max9611->shunt_resistor_uohm % 1000;
+ i = max9611->shunt_resistor_uohm / 1000000;
+ r = max9611->shunt_resistor_uohm % 1000000;
- return sprintf(buf, "%u.%03u\n", i, r);
+ return sprintf(buf, "%u.%06u\n", i, r);
}
static IIO_DEVICE_ATTR(in_power_shunt_resistor, 0444,
@@ -536,8 +536,8 @@ static int max9611_probe(struct i2c_client *client,
int ret;
indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*max9611));
- if (IS_ERR(indio_dev))
- return PTR_ERR(indio_dev);
+ if (!indio_dev)
+ return -ENOMEM;
i2c_set_clientdata(client, indio_dev);
diff --git a/drivers/iio/adc/meson_saradc.c b/drivers/iio/adc/meson_saradc.c
index dd4190b50df6..83da50ed73ab 100644
--- a/drivers/iio/adc/meson_saradc.c
+++ b/drivers/iio/adc/meson_saradc.c
@@ -220,6 +220,7 @@ enum meson_sar_adc_chan7_mux_sel {
};
struct meson_sar_adc_data {
+ bool has_bl30_integration;
unsigned int resolution;
const char *name;
};
@@ -437,19 +438,24 @@ static int meson_sar_adc_lock(struct iio_dev *indio_dev)
mutex_lock(&indio_dev->mlock);
- /* prevent BL30 from using the SAR ADC while we are using it */
- regmap_update_bits(priv->regmap, MESON_SAR_ADC_DELAY,
- MESON_SAR_ADC_DELAY_KERNEL_BUSY,
- MESON_SAR_ADC_DELAY_KERNEL_BUSY);
-
- /* wait until BL30 releases it's lock (so we can use the SAR ADC) */
- do {
- udelay(1);
- regmap_read(priv->regmap, MESON_SAR_ADC_DELAY, &val);
- } while (val & MESON_SAR_ADC_DELAY_BL30_BUSY && timeout--);
-
- if (timeout < 0)
- return -ETIMEDOUT;
+ if (priv->data->has_bl30_integration) {
+ /* prevent BL30 from using the SAR ADC while we are using it */
+ regmap_update_bits(priv->regmap, MESON_SAR_ADC_DELAY,
+ MESON_SAR_ADC_DELAY_KERNEL_BUSY,
+ MESON_SAR_ADC_DELAY_KERNEL_BUSY);
+
+ /*
+ * wait until BL30 releases it's lock (so we can use the SAR
+ * ADC)
+ */
+ do {
+ udelay(1);
+ regmap_read(priv->regmap, MESON_SAR_ADC_DELAY, &val);
+ } while (val & MESON_SAR_ADC_DELAY_BL30_BUSY && timeout--);
+
+ if (timeout < 0)
+ return -ETIMEDOUT;
+ }
return 0;
}
@@ -458,9 +464,10 @@ static void meson_sar_adc_unlock(struct iio_dev *indio_dev)
{
struct meson_sar_adc_priv *priv = iio_priv(indio_dev);
- /* allow BL30 to use the SAR ADC again */
- regmap_update_bits(priv->regmap, MESON_SAR_ADC_DELAY,
- MESON_SAR_ADC_DELAY_KERNEL_BUSY, 0);
+ if (priv->data->has_bl30_integration)
+ /* allow BL30 to use the SAR ADC again */
+ regmap_update_bits(priv->regmap, MESON_SAR_ADC_DELAY,
+ MESON_SAR_ADC_DELAY_KERNEL_BUSY, 0);
mutex_unlock(&indio_dev->mlock);
}
@@ -468,13 +475,13 @@ static void meson_sar_adc_unlock(struct iio_dev *indio_dev)
static void meson_sar_adc_clear_fifo(struct iio_dev *indio_dev)
{
struct meson_sar_adc_priv *priv = iio_priv(indio_dev);
- int count;
+ unsigned int count, tmp;
for (count = 0; count < MESON_SAR_ADC_MAX_FIFO_SIZE; count++) {
if (!meson_sar_adc_get_fifo_count(indio_dev))
break;
- regmap_read(priv->regmap, MESON_SAR_ADC_FIFO_RD, 0);
+ regmap_read(priv->regmap, MESON_SAR_ADC_FIFO_RD, &tmp);
}
}
@@ -614,14 +621,16 @@ static int meson_sar_adc_init(struct iio_dev *indio_dev)
*/
meson_sar_adc_set_chan7_mux(indio_dev, CHAN7_MUX_CH7_INPUT);
- /*
- * leave sampling delay and the input clocks as configured by BL30 to
- * make sure BL30 gets the values it expects when reading the
- * temperature sensor.
- */
- regmap_read(priv->regmap, MESON_SAR_ADC_REG3, &regval);
- if (regval & MESON_SAR_ADC_REG3_BL30_INITIALIZED)
- return 0;
+ if (priv->data->has_bl30_integration) {
+ /*
+ * leave sampling delay and the input clocks as configured by
+ * BL30 to make sure BL30 gets the values it expects when
+ * reading the temperature sensor.
+ */
+ regmap_read(priv->regmap, MESON_SAR_ADC_REG3, &regval);
+ if (regval & MESON_SAR_ADC_REG3_BL30_INITIALIZED)
+ return 0;
+ }
meson_sar_adc_stop_sample_engine(indio_dev);
@@ -834,23 +843,46 @@ static const struct iio_info meson_sar_adc_iio_info = {
.driver_module = THIS_MODULE,
};
-struct meson_sar_adc_data meson_sar_adc_gxbb_data = {
+static const struct meson_sar_adc_data meson_sar_adc_meson8_data = {
+ .has_bl30_integration = false,
+ .resolution = 10,
+ .name = "meson-meson8-saradc",
+};
+
+static const struct meson_sar_adc_data meson_sar_adc_meson8b_data = {
+ .has_bl30_integration = false,
+ .resolution = 10,
+ .name = "meson-meson8b-saradc",
+};
+
+static const struct meson_sar_adc_data meson_sar_adc_gxbb_data = {
+ .has_bl30_integration = true,
.resolution = 10,
.name = "meson-gxbb-saradc",
};
-struct meson_sar_adc_data meson_sar_adc_gxl_data = {
+static const struct meson_sar_adc_data meson_sar_adc_gxl_data = {
+ .has_bl30_integration = true,
.resolution = 12,
.name = "meson-gxl-saradc",
};
-struct meson_sar_adc_data meson_sar_adc_gxm_data = {
+static const struct meson_sar_adc_data meson_sar_adc_gxm_data = {
+ .has_bl30_integration = true,
.resolution = 12,
.name = "meson-gxm-saradc",
};
static const struct of_device_id meson_sar_adc_of_match[] = {
{
+ .compatible = "amlogic,meson8-saradc",
+ .data = &meson_sar_adc_meson8_data,
+ },
+ {
+ .compatible = "amlogic,meson8b-saradc",
+ .data = &meson_sar_adc_meson8b_data,
+ },
+ {
.compatible = "amlogic,meson-gxbb-saradc",
.data = &meson_sar_adc_gxbb_data,
}, {
diff --git a/drivers/iio/adc/mxs-lradc-adc.c b/drivers/iio/adc/mxs-lradc-adc.c
index b0c7d8ee5cb8..d32b34638c2f 100644
--- a/drivers/iio/adc/mxs-lradc-adc.c
+++ b/drivers/iio/adc/mxs-lradc-adc.c
@@ -48,7 +48,7 @@
#define VREF_MV_BASE 1850
-const char *mx23_lradc_adc_irq_names[] = {
+static const char *mx23_lradc_adc_irq_names[] = {
"mxs-lradc-channel0",
"mxs-lradc-channel1",
"mxs-lradc-channel2",
@@ -57,7 +57,7 @@ const char *mx23_lradc_adc_irq_names[] = {
"mxs-lradc-channel5",
};
-const char *mx28_lradc_adc_irq_names[] = {
+static const char *mx28_lradc_adc_irq_names[] = {
"mxs-lradc-thresh0",
"mxs-lradc-thresh1",
"mxs-lradc-channel0",
@@ -344,20 +344,20 @@ static ssize_t mxs_lradc_adc_show_scale_avail(struct device *dev,
IIO_DEVICE_ATTR(in_voltage##ch##_scale_available, 0444,\
mxs_lradc_adc_show_scale_avail, NULL, ch)
-SHOW_SCALE_AVAILABLE_ATTR(0);
-SHOW_SCALE_AVAILABLE_ATTR(1);
-SHOW_SCALE_AVAILABLE_ATTR(2);
-SHOW_SCALE_AVAILABLE_ATTR(3);
-SHOW_SCALE_AVAILABLE_ATTR(4);
-SHOW_SCALE_AVAILABLE_ATTR(5);
-SHOW_SCALE_AVAILABLE_ATTR(6);
-SHOW_SCALE_AVAILABLE_ATTR(7);
-SHOW_SCALE_AVAILABLE_ATTR(10);
-SHOW_SCALE_AVAILABLE_ATTR(11);
-SHOW_SCALE_AVAILABLE_ATTR(12);
-SHOW_SCALE_AVAILABLE_ATTR(13);
-SHOW_SCALE_AVAILABLE_ATTR(14);
-SHOW_SCALE_AVAILABLE_ATTR(15);
+static SHOW_SCALE_AVAILABLE_ATTR(0);
+static SHOW_SCALE_AVAILABLE_ATTR(1);
+static SHOW_SCALE_AVAILABLE_ATTR(2);
+static SHOW_SCALE_AVAILABLE_ATTR(3);
+static SHOW_SCALE_AVAILABLE_ATTR(4);
+static SHOW_SCALE_AVAILABLE_ATTR(5);
+static SHOW_SCALE_AVAILABLE_ATTR(6);
+static SHOW_SCALE_AVAILABLE_ATTR(7);
+static SHOW_SCALE_AVAILABLE_ATTR(10);
+static SHOW_SCALE_AVAILABLE_ATTR(11);
+static SHOW_SCALE_AVAILABLE_ATTR(12);
+static SHOW_SCALE_AVAILABLE_ATTR(13);
+static SHOW_SCALE_AVAILABLE_ATTR(14);
+static SHOW_SCALE_AVAILABLE_ATTR(15);
static struct attribute *mxs_lradc_adc_attributes[] = {
&iio_dev_attr_in_voltage0_scale_available.dev_attr.attr,
@@ -718,9 +718,12 @@ static int mxs_lradc_adc_probe(struct platform_device *pdev)
adc->dev = dev;
iores = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (!iores)
+ return -EINVAL;
+
adc->base = devm_ioremap(dev, iores->start, resource_size(iores));
- if (IS_ERR(adc->base))
- return PTR_ERR(adc->base);
+ if (!adc->base)
+ return -ENOMEM;
init_completion(&adc->completion);
spin_lock_init(&adc->lock);
diff --git a/drivers/iio/adc/rcar-gyroadc.c b/drivers/iio/adc/rcar-gyroadc.c
index 018ed360e717..27a318164619 100644
--- a/drivers/iio/adc/rcar-gyroadc.c
+++ b/drivers/iio/adc/rcar-gyroadc.c
@@ -73,7 +73,7 @@ enum rcar_gyroadc_model {
struct rcar_gyroadc {
struct device *dev;
void __iomem *regs;
- struct clk *iclk;
+ struct clk *clk;
struct regulator *vref[8];
unsigned int num_channels;
enum rcar_gyroadc_model model;
@@ -83,7 +83,7 @@ struct rcar_gyroadc {
static void rcar_gyroadc_hw_init(struct rcar_gyroadc *priv)
{
- const unsigned long clk_mhz = clk_get_rate(priv->iclk) / 1000000;
+ const unsigned long clk_mhz = clk_get_rate(priv->clk) / 1000000;
const unsigned long clk_mul =
(priv->mode == RCAR_GYROADC_MODE_SELECT_1_MB88101A) ? 10 : 5;
unsigned long clk_len = clk_mhz * clk_mul;
@@ -510,9 +510,9 @@ static int rcar_gyroadc_probe(struct platform_device *pdev)
if (IS_ERR(priv->regs))
return PTR_ERR(priv->regs);
- priv->iclk = devm_clk_get(dev, "if");
- if (IS_ERR(priv->iclk)) {
- ret = PTR_ERR(priv->iclk);
+ priv->clk = devm_clk_get(dev, "fck");
+ if (IS_ERR(priv->clk)) {
+ ret = PTR_ERR(priv->clk);
if (ret != -EPROBE_DEFER)
dev_err(dev, "Failed to get IF clock (ret=%i)\n", ret);
return ret;
@@ -536,7 +536,7 @@ static int rcar_gyroadc_probe(struct platform_device *pdev)
indio_dev->info = &rcar_gyroadc_iio_info;
indio_dev->modes = INDIO_DIRECT_MODE;
- ret = clk_prepare_enable(priv->iclk);
+ ret = clk_prepare_enable(priv->clk);
if (ret) {
dev_err(dev, "Could not prepare or enable the IF clock.\n");
goto err_clk_if_enable;
@@ -565,7 +565,7 @@ err_iio_device_register:
pm_runtime_put_sync(dev);
pm_runtime_disable(dev);
pm_runtime_set_suspended(dev);
- clk_disable_unprepare(priv->iclk);
+ clk_disable_unprepare(priv->clk);
err_clk_if_enable:
rcar_gyroadc_deinit_supplies(indio_dev);
@@ -584,7 +584,7 @@ static int rcar_gyroadc_remove(struct platform_device *pdev)
pm_runtime_put_sync(dev);
pm_runtime_disable(dev);
pm_runtime_set_suspended(dev);
- clk_disable_unprepare(priv->iclk);
+ clk_disable_unprepare(priv->clk);
rcar_gyroadc_deinit_supplies(indio_dev);
return 0;
diff --git a/drivers/iio/adc/stm32-adc-core.c b/drivers/iio/adc/stm32-adc-core.c
index 22b7c9321e78..e09233b03c05 100644
--- a/drivers/iio/adc/stm32-adc-core.c
+++ b/drivers/iio/adc/stm32-adc-core.c
@@ -49,19 +49,66 @@
/* STM32 F4 maximum analog clock rate (from datasheet) */
#define STM32F4_ADC_MAX_CLK_RATE 36000000
+/* STM32H7 - common registers for all ADC instances */
+#define STM32H7_ADC_CSR (STM32_ADCX_COMN_OFFSET + 0x00)
+#define STM32H7_ADC_CCR (STM32_ADCX_COMN_OFFSET + 0x08)
+
+/* STM32H7_ADC_CSR - bit fields */
+#define STM32H7_EOC_SLV BIT(18)
+#define STM32H7_EOC_MST BIT(2)
+
+/* STM32H7_ADC_CCR - bit fields */
+#define STM32H7_PRESC_SHIFT 18
+#define STM32H7_PRESC_MASK GENMASK(21, 18)
+#define STM32H7_CKMODE_SHIFT 16
+#define STM32H7_CKMODE_MASK GENMASK(17, 16)
+
+/* STM32 H7 maximum analog clock rate (from datasheet) */
+#define STM32H7_ADC_MAX_CLK_RATE 72000000
+
+/**
+ * stm32_adc_common_regs - stm32 common registers, compatible dependent data
+ * @csr: common status register offset
+ * @eoc1: adc1 end of conversion flag in @csr
+ * @eoc2: adc2 end of conversion flag in @csr
+ * @eoc3: adc3 end of conversion flag in @csr
+ */
+struct stm32_adc_common_regs {
+ u32 csr;
+ u32 eoc1_msk;
+ u32 eoc2_msk;
+ u32 eoc3_msk;
+};
+
+struct stm32_adc_priv;
+
+/**
+ * stm32_adc_priv_cfg - stm32 core compatible configuration data
+ * @regs: common registers for all instances
+ * @clk_sel: clock selection routine
+ */
+struct stm32_adc_priv_cfg {
+ const struct stm32_adc_common_regs *regs;
+ int (*clk_sel)(struct platform_device *, struct stm32_adc_priv *);
+};
+
/**
* struct stm32_adc_priv - stm32 ADC core private data
* @irq: irq for ADC block
* @domain: irq domain reference
* @aclk: clock reference for the analog circuitry
+ * @bclk: bus clock common for all ADCs, depends on part used
* @vref: regulator reference
+ * @cfg: compatible configuration data
* @common: common data for all ADC instances
*/
struct stm32_adc_priv {
int irq;
struct irq_domain *domain;
struct clk *aclk;
+ struct clk *bclk;
struct regulator *vref;
+ const struct stm32_adc_priv_cfg *cfg;
struct stm32_adc_common common;
};
@@ -85,14 +132,23 @@ static int stm32f4_adc_clk_sel(struct platform_device *pdev,
u32 val;
int i;
+ /* stm32f4 has one clk input for analog (mandatory), enforce it here */
+ if (!priv->aclk) {
+ dev_err(&pdev->dev, "No 'adc' clock found\n");
+ return -ENOENT;
+ }
+
rate = clk_get_rate(priv->aclk);
for (i = 0; i < ARRAY_SIZE(stm32f4_pclk_div); i++) {
if ((rate / stm32f4_pclk_div[i]) <= STM32F4_ADC_MAX_CLK_RATE)
break;
}
- if (i >= ARRAY_SIZE(stm32f4_pclk_div))
+ if (i >= ARRAY_SIZE(stm32f4_pclk_div)) {
+ dev_err(&pdev->dev, "adc clk selection failed\n");
return -EINVAL;
+ }
+ priv->common.rate = rate;
val = readl_relaxed(priv->common.base + STM32F4_ADC_CCR);
val &= ~STM32F4_ADC_ADCPRE_MASK;
val |= i << STM32F4_ADC_ADCPRE_SHIFT;
@@ -104,6 +160,126 @@ static int stm32f4_adc_clk_sel(struct platform_device *pdev,
return 0;
}
+/**
+ * struct stm32h7_adc_ck_spec - specification for stm32h7 adc clock
+ * @ckmode: ADC clock mode, Async or sync with prescaler.
+ * @presc: prescaler bitfield for async clock mode
+ * @div: prescaler division ratio
+ */
+struct stm32h7_adc_ck_spec {
+ u32 ckmode;
+ u32 presc;
+ int div;
+};
+
+const struct stm32h7_adc_ck_spec stm32h7_adc_ckmodes_spec[] = {
+ /* 00: CK_ADC[1..3]: Asynchronous clock modes */
+ { 0, 0, 1 },
+ { 0, 1, 2 },
+ { 0, 2, 4 },
+ { 0, 3, 6 },
+ { 0, 4, 8 },
+ { 0, 5, 10 },
+ { 0, 6, 12 },
+ { 0, 7, 16 },
+ { 0, 8, 32 },
+ { 0, 9, 64 },
+ { 0, 10, 128 },
+ { 0, 11, 256 },
+ /* HCLK used: Synchronous clock modes (1, 2 or 4 prescaler) */
+ { 1, 0, 1 },
+ { 2, 0, 2 },
+ { 3, 0, 4 },
+};
+
+static int stm32h7_adc_clk_sel(struct platform_device *pdev,
+ struct stm32_adc_priv *priv)
+{
+ u32 ckmode, presc, val;
+ unsigned long rate;
+ int i, div;
+
+ /* stm32h7 bus clock is common for all ADC instances (mandatory) */
+ if (!priv->bclk) {
+ dev_err(&pdev->dev, "No 'bus' clock found\n");
+ return -ENOENT;
+ }
+
+ /*
+ * stm32h7 can use either 'bus' or 'adc' clock for analog circuitry.
+ * So, choice is to have bus clock mandatory and adc clock optional.
+ * If optional 'adc' clock has been found, then try to use it first.
+ */
+ if (priv->aclk) {
+ /*
+ * Asynchronous clock modes (e.g. ckmode == 0)
+ * From spec: PLL output musn't exceed max rate
+ */
+ rate = clk_get_rate(priv->aclk);
+
+ for (i = 0; i < ARRAY_SIZE(stm32h7_adc_ckmodes_spec); i++) {
+ ckmode = stm32h7_adc_ckmodes_spec[i].ckmode;
+ presc = stm32h7_adc_ckmodes_spec[i].presc;
+ div = stm32h7_adc_ckmodes_spec[i].div;
+
+ if (ckmode)
+ continue;
+
+ if ((rate / div) <= STM32H7_ADC_MAX_CLK_RATE)
+ goto out;
+ }
+ }
+
+ /* Synchronous clock modes (e.g. ckmode is 1, 2 or 3) */
+ rate = clk_get_rate(priv->bclk);
+
+ for (i = 0; i < ARRAY_SIZE(stm32h7_adc_ckmodes_spec); i++) {
+ ckmode = stm32h7_adc_ckmodes_spec[i].ckmode;
+ presc = stm32h7_adc_ckmodes_spec[i].presc;
+ div = stm32h7_adc_ckmodes_spec[i].div;
+
+ if (!ckmode)
+ continue;
+
+ if ((rate / div) <= STM32H7_ADC_MAX_CLK_RATE)
+ goto out;
+ }
+
+ dev_err(&pdev->dev, "adc clk selection failed\n");
+ return -EINVAL;
+
+out:
+ /* rate used later by each ADC instance to control BOOST mode */
+ priv->common.rate = rate;
+
+ /* Set common clock mode and prescaler */
+ val = readl_relaxed(priv->common.base + STM32H7_ADC_CCR);
+ val &= ~(STM32H7_CKMODE_MASK | STM32H7_PRESC_MASK);
+ val |= ckmode << STM32H7_CKMODE_SHIFT;
+ val |= presc << STM32H7_PRESC_SHIFT;
+ writel_relaxed(val, priv->common.base + STM32H7_ADC_CCR);
+
+ dev_dbg(&pdev->dev, "Using %s clock/%d source at %ld kHz\n",
+ ckmode ? "bus" : "adc", div, rate / (div * 1000));
+
+ return 0;
+}
+
+/* STM32F4 common registers definitions */
+static const struct stm32_adc_common_regs stm32f4_adc_common_regs = {
+ .csr = STM32F4_ADC_CSR,
+ .eoc1_msk = STM32F4_EOC1,
+ .eoc2_msk = STM32F4_EOC2,
+ .eoc3_msk = STM32F4_EOC3,
+};
+
+/* STM32H7 common registers definitions */
+static const struct stm32_adc_common_regs stm32h7_adc_common_regs = {
+ .csr = STM32H7_ADC_CSR,
+ .eoc1_msk = STM32H7_EOC_MST,
+ .eoc2_msk = STM32H7_EOC_SLV,
+};
+
/* ADC common interrupt for all instances */
static void stm32_adc_irq_handler(struct irq_desc *desc)
{
@@ -112,15 +288,15 @@ static void stm32_adc_irq_handler(struct irq_desc *desc)
u32 status;
chained_irq_enter(chip, desc);
- status = readl_relaxed(priv->common.base + STM32F4_ADC_CSR);
+ status = readl_relaxed(priv->common.base + priv->cfg->regs->csr);
- if (status & STM32F4_EOC1)
+ if (status & priv->cfg->regs->eoc1_msk)
generic_handle_irq(irq_find_mapping(priv->domain, 0));
- if (status & STM32F4_EOC2)
+ if (status & priv->cfg->regs->eoc2_msk)
generic_handle_irq(irq_find_mapping(priv->domain, 1));
- if (status & STM32F4_EOC3)
+ if (status & priv->cfg->regs->eoc3_msk)
generic_handle_irq(irq_find_mapping(priv->domain, 2));
chained_irq_exit(chip, desc);
@@ -186,6 +362,7 @@ static void stm32_adc_irq_remove(struct platform_device *pdev,
static int stm32_adc_probe(struct platform_device *pdev)
{
struct stm32_adc_priv *priv;
+ struct device *dev = &pdev->dev;
struct device_node *np = pdev->dev.of_node;
struct resource *res;
int ret;
@@ -197,6 +374,9 @@ static int stm32_adc_probe(struct platform_device *pdev)
if (!priv)
return -ENOMEM;
+ priv->cfg = (const struct stm32_adc_priv_cfg *)
+ of_match_device(dev->driver->of_match_table, dev)->data;
+
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
priv->common.base = devm_ioremap_resource(&pdev->dev, res);
if (IS_ERR(priv->common.base))
@@ -227,25 +407,48 @@ static int stm32_adc_probe(struct platform_device *pdev)
priv->aclk = devm_clk_get(&pdev->dev, "adc");
if (IS_ERR(priv->aclk)) {
ret = PTR_ERR(priv->aclk);
- dev_err(&pdev->dev, "Can't get 'adc' clock\n");
- goto err_regulator_disable;
+ if (ret == -ENOENT) {
+ priv->aclk = NULL;
+ } else {
+ dev_err(&pdev->dev, "Can't get 'adc' clock\n");
+ goto err_regulator_disable;
+ }
}
- ret = clk_prepare_enable(priv->aclk);
- if (ret < 0) {
- dev_err(&pdev->dev, "adc clk enable failed\n");
- goto err_regulator_disable;
+ if (priv->aclk) {
+ ret = clk_prepare_enable(priv->aclk);
+ if (ret < 0) {
+ dev_err(&pdev->dev, "adc clk enable failed\n");
+ goto err_regulator_disable;
+ }
}
- ret = stm32f4_adc_clk_sel(pdev, priv);
- if (ret < 0) {
- dev_err(&pdev->dev, "adc clk selection failed\n");
- goto err_clk_disable;
+ priv->bclk = devm_clk_get(&pdev->dev, "bus");
+ if (IS_ERR(priv->bclk)) {
+ ret = PTR_ERR(priv->bclk);
+ if (ret == -ENOENT) {
+ priv->bclk = NULL;
+ } else {
+ dev_err(&pdev->dev, "Can't get 'bus' clock\n");
+ goto err_aclk_disable;
+ }
+ }
+
+ if (priv->bclk) {
+ ret = clk_prepare_enable(priv->bclk);
+ if (ret < 0) {
+ dev_err(&pdev->dev, "adc clk enable failed\n");
+ goto err_aclk_disable;
+ }
}
+ ret = priv->cfg->clk_sel(pdev, priv);
+ if (ret < 0)
+ goto err_bclk_disable;
+
ret = stm32_adc_irq_probe(pdev, priv);
if (ret < 0)
- goto err_clk_disable;
+ goto err_bclk_disable;
platform_set_drvdata(pdev, &priv->common);
@@ -260,8 +463,13 @@ static int stm32_adc_probe(struct platform_device *pdev)
err_irq_remove:
stm32_adc_irq_remove(pdev, priv);
-err_clk_disable:
- clk_disable_unprepare(priv->aclk);
+err_bclk_disable:
+ if (priv->bclk)
+ clk_disable_unprepare(priv->bclk);
+
+err_aclk_disable:
+ if (priv->aclk)
+ clk_disable_unprepare(priv->aclk);
err_regulator_disable:
regulator_disable(priv->vref);
@@ -276,15 +484,34 @@ static int stm32_adc_remove(struct platform_device *pdev)
of_platform_depopulate(&pdev->dev);
stm32_adc_irq_remove(pdev, priv);
- clk_disable_unprepare(priv->aclk);
+ if (priv->bclk)
+ clk_disable_unprepare(priv->bclk);
+ if (priv->aclk)
+ clk_disable_unprepare(priv->aclk);
regulator_disable(priv->vref);
return 0;
}
+static const struct stm32_adc_priv_cfg stm32f4_adc_priv_cfg = {
+ .regs = &stm32f4_adc_common_regs,
+ .clk_sel = stm32f4_adc_clk_sel,
+};
+
+static const struct stm32_adc_priv_cfg stm32h7_adc_priv_cfg = {
+ .regs = &stm32h7_adc_common_regs,
+ .clk_sel = stm32h7_adc_clk_sel,
+};
+
static const struct of_device_id stm32_adc_of_match[] = {
- { .compatible = "st,stm32f4-adc-core" },
- {},
+ {
+ .compatible = "st,stm32f4-adc-core",
+ .data = (void *)&stm32f4_adc_priv_cfg
+ }, {
+ .compatible = "st,stm32h7-adc-core",
+ .data = (void *)&stm32h7_adc_priv_cfg
+ }, {
+ },
};
MODULE_DEVICE_TABLE(of, stm32_adc_of_match);
diff --git a/drivers/iio/adc/stm32-adc-core.h b/drivers/iio/adc/stm32-adc-core.h
index 2ec7abbfbcaa..250ee958a669 100644
--- a/drivers/iio/adc/stm32-adc-core.h
+++ b/drivers/iio/adc/stm32-adc-core.h
@@ -43,11 +43,13 @@
* struct stm32_adc_common - stm32 ADC driver common data (for all instances)
* @base: control registers base cpu addr
* @phys_base: control registers base physical addr
+ * @rate: clock rate used for analog circuitry
* @vref_mv: vref voltage (mv)
*/
struct stm32_adc_common {
void __iomem *base;
phys_addr_t phys_base;
+ unsigned long rate;
int vref_mv;
};
diff --git a/drivers/iio/adc/stm32-adc.c b/drivers/iio/adc/stm32-adc.c
index c28e7ff80e11..5bfcc1f13105 100644
--- a/drivers/iio/adc/stm32-adc.c
+++ b/drivers/iio/adc/stm32-adc.c
@@ -31,9 +31,11 @@
#include <linux/iio/triggered_buffer.h>
#include <linux/interrupt.h>
#include <linux/io.h>
+#include <linux/iopoll.h>
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/of.h>
+#include <linux/of_device.h>
#include "stm32-adc-core.h"
@@ -76,6 +78,78 @@
#define STM32F4_DMA BIT(8)
#define STM32F4_ADON BIT(0)
+/* STM32H7 - Registers for each ADC instance */
+#define STM32H7_ADC_ISR 0x00
+#define STM32H7_ADC_IER 0x04
+#define STM32H7_ADC_CR 0x08
+#define STM32H7_ADC_CFGR 0x0C
+#define STM32H7_ADC_PCSEL 0x1C
+#define STM32H7_ADC_SQR1 0x30
+#define STM32H7_ADC_SQR2 0x34
+#define STM32H7_ADC_SQR3 0x38
+#define STM32H7_ADC_SQR4 0x3C
+#define STM32H7_ADC_DR 0x40
+#define STM32H7_ADC_CALFACT 0xC4
+#define STM32H7_ADC_CALFACT2 0xC8
+
+/* STM32H7_ADC_ISR - bit fields */
+#define STM32H7_EOC BIT(2)
+#define STM32H7_ADRDY BIT(0)
+
+/* STM32H7_ADC_IER - bit fields */
+#define STM32H7_EOCIE STM32H7_EOC
+
+/* STM32H7_ADC_CR - bit fields */
+#define STM32H7_ADCAL BIT(31)
+#define STM32H7_ADCALDIF BIT(30)
+#define STM32H7_DEEPPWD BIT(29)
+#define STM32H7_ADVREGEN BIT(28)
+#define STM32H7_LINCALRDYW6 BIT(27)
+#define STM32H7_LINCALRDYW5 BIT(26)
+#define STM32H7_LINCALRDYW4 BIT(25)
+#define STM32H7_LINCALRDYW3 BIT(24)
+#define STM32H7_LINCALRDYW2 BIT(23)
+#define STM32H7_LINCALRDYW1 BIT(22)
+#define STM32H7_ADCALLIN BIT(16)
+#define STM32H7_BOOST BIT(8)
+#define STM32H7_ADSTP BIT(4)
+#define STM32H7_ADSTART BIT(2)
+#define STM32H7_ADDIS BIT(1)
+#define STM32H7_ADEN BIT(0)
+
+/* STM32H7_ADC_CFGR bit fields */
+#define STM32H7_EXTEN_SHIFT 10
+#define STM32H7_EXTEN_MASK GENMASK(11, 10)
+#define STM32H7_EXTSEL_SHIFT 5
+#define STM32H7_EXTSEL_MASK GENMASK(9, 5)
+#define STM32H7_RES_SHIFT 2
+#define STM32H7_RES_MASK GENMASK(4, 2)
+#define STM32H7_DMNGT_SHIFT 0
+#define STM32H7_DMNGT_MASK GENMASK(1, 0)
+
+enum stm32h7_adc_dmngt {
+ STM32H7_DMNGT_DR_ONLY, /* Regular data in DR only */
+ STM32H7_DMNGT_DMA_ONESHOT, /* DMA one shot mode */
+ STM32H7_DMNGT_DFSDM, /* DFSDM mode */
+ STM32H7_DMNGT_DMA_CIRC, /* DMA circular mode */
+};
+
+/* STM32H7_ADC_CALFACT - bit fields */
+#define STM32H7_CALFACT_D_SHIFT 16
+#define STM32H7_CALFACT_D_MASK GENMASK(26, 16)
+#define STM32H7_CALFACT_S_SHIFT 0
+#define STM32H7_CALFACT_S_MASK GENMASK(10, 0)
+
+/* STM32H7_ADC_CALFACT2 - bit fields */
+#define STM32H7_LINCALFACT_SHIFT 0
+#define STM32H7_LINCALFACT_MASK GENMASK(29, 0)
+
+/* Number of linear calibration shadow registers / LINCALRDYW control bits */
+#define STM32H7_LINCALFACT_NUM 6
+
+/* BOOST bit must be set on STM32H7 when ADC clock is above 20MHz */
+#define STM32H7_BOOST_CLKRATE 20000000UL
+
#define STM32_ADC_MAX_SQ 16 /* SQ1..SQ16 */
#define STM32_ADC_TIMEOUT_US 100000
#define STM32_ADC_TIMEOUT (msecs_to_jiffies(STM32_ADC_TIMEOUT_US / 1000))
@@ -121,6 +195,18 @@ struct stm32_adc_trig_info {
};
/**
+ * struct stm32_adc_calib - optional adc calibration data
+ * @calfact_s: Calibration offset for single ended channels
+ * @calfact_d: Calibration offset in differential
+ * @lincalfact: Linearity calibration factor
+ */
+struct stm32_adc_calib {
+ u32 calfact_s;
+ u32 calfact_d;
+ u32 lincalfact[STM32H7_LINCALFACT_NUM];
+};
+
+/**
* stm32_adc_regs - stm32 ADC misc registers & bitfield desc
* @reg: register offset
* @mask: bitfield mask
@@ -133,9 +219,56 @@ struct stm32_adc_regs {
};
/**
+ * stm32_adc_regspec - stm32 registers definition, compatible dependent data
+ * @dr: data register offset
+ * @ier_eoc: interrupt enable register & eocie bitfield
+ * @isr_eoc: interrupt status register & eoc bitfield
+ * @sqr: reference to sequence registers array
+ * @exten: trigger control register & bitfield
+ * @extsel: trigger selection register & bitfield
+ * @res: resolution selection register & bitfield
+ */
+struct stm32_adc_regspec {
+ const u32 dr;
+ const struct stm32_adc_regs ier_eoc;
+ const struct stm32_adc_regs isr_eoc;
+ const struct stm32_adc_regs *sqr;
+ const struct stm32_adc_regs exten;
+ const struct stm32_adc_regs extsel;
+ const struct stm32_adc_regs res;
+};
+
+struct stm32_adc;
+
+/**
+ * stm32_adc_cfg - stm32 compatible configuration data
+ * @regs: registers descriptions
+ * @adc_info: per instance input channels definitions
+ * @trigs: external trigger sources
+ * @clk_required: clock is required
+ * @selfcalib: optional routine for self-calibration
+ * @prepare: optional prepare routine (power-up, enable)
+ * @start_conv: routine to start conversions
+ * @stop_conv: routine to stop conversions
+ * @unprepare: optional unprepare routine (disable, power-down)
+ */
+struct stm32_adc_cfg {
+ const struct stm32_adc_regspec *regs;
+ const struct stm32_adc_info *adc_info;
+ struct stm32_adc_trig_info *trigs;
+ bool clk_required;
+ int (*selfcalib)(struct stm32_adc *);
+ int (*prepare)(struct stm32_adc *);
+ void (*start_conv)(struct stm32_adc *, bool dma);
+ void (*stop_conv)(struct stm32_adc *);
+ void (*unprepare)(struct stm32_adc *);
+};
+
+/**
* struct stm32_adc - private data of each ADC IIO instance
* @common: reference to ADC block common data
* @offset: ADC instance register offset in ADC block
+ * @cfg: compatible configuration data
* @completion: end of single conversion completion
* @buffer: data buffer
* @clk: clock for this adc instance
@@ -149,10 +282,13 @@ struct stm32_adc_regs {
* @rx_buf: dma rx buffer cpu address
* @rx_dma_buf: dma rx buffer bus address
* @rx_buf_sz: dma rx buffer size
+ * @pcsel bitmask to preselect channels on some devices
+ * @cal: optional calibration data on some devices
*/
struct stm32_adc {
struct stm32_adc_common *common;
u32 offset;
+ const struct stm32_adc_cfg *cfg;
struct completion completion;
u16 buffer[STM32_ADC_MAX_SQ];
struct clk *clk;
@@ -166,6 +302,8 @@ struct stm32_adc {
u8 *rx_buf;
dma_addr_t rx_dma_buf;
unsigned int rx_buf_sz;
+ u32 pcsel;
+ struct stm32_adc_calib cal;
};
/**
@@ -180,8 +318,26 @@ struct stm32_adc_chan_spec {
const char *name;
};
-/* Input definitions common for all STM32F4 instances */
-static const struct stm32_adc_chan_spec stm32f4_adc123_channels[] = {
+/**
+ * struct stm32_adc_info - stm32 ADC, per instance config data
+ * @channels: Reference to stm32 channels spec
+ * @max_channels: Number of channels
+ * @resolutions: available resolutions
+ * @num_res: number of available resolutions
+ */
+struct stm32_adc_info {
+ const struct stm32_adc_chan_spec *channels;
+ int max_channels;
+ const unsigned int *resolutions;
+ const unsigned int num_res;
+};
+
+/*
+ * Input definitions common for all instances:
+ * stm32f4 can have up to 16 channels
+ * stm32h7 can have up to 20 channels
+ */
+static const struct stm32_adc_chan_spec stm32_adc_channels[] = {
{ IIO_VOLTAGE, 0, "in0" },
{ IIO_VOLTAGE, 1, "in1" },
{ IIO_VOLTAGE, 2, "in2" },
@@ -198,6 +354,10 @@ static const struct stm32_adc_chan_spec stm32f4_adc123_channels[] = {
{ IIO_VOLTAGE, 13, "in13" },
{ IIO_VOLTAGE, 14, "in14" },
{ IIO_VOLTAGE, 15, "in15" },
+ { IIO_VOLTAGE, 16, "in16" },
+ { IIO_VOLTAGE, 17, "in17" },
+ { IIO_VOLTAGE, 18, "in18" },
+ { IIO_VOLTAGE, 19, "in19" },
};
static const unsigned int stm32f4_adc_resolutions[] = {
@@ -205,6 +365,25 @@ static const unsigned int stm32f4_adc_resolutions[] = {
12, 10, 8, 6,
};
+static const struct stm32_adc_info stm32f4_adc_info = {
+ .channels = stm32_adc_channels,
+ .max_channels = 16,
+ .resolutions = stm32f4_adc_resolutions,
+ .num_res = ARRAY_SIZE(stm32f4_adc_resolutions),
+};
+
+static const unsigned int stm32h7_adc_resolutions[] = {
+ /* sorted values so the index matches RES[2:0] in STM32H7_ADC_CFGR */
+ 16, 14, 12, 10, 8,
+};
+
+static const struct stm32_adc_info stm32h7_adc_info = {
+ .channels = stm32_adc_channels,
+ .max_channels = 20,
+ .resolutions = stm32h7_adc_resolutions,
+ .num_res = ARRAY_SIZE(stm32h7_adc_resolutions),
+};
+
/**
* stm32f4_sq - describe regular sequence registers
* - L: sequence len (register & bit field)
@@ -252,6 +431,69 @@ static struct stm32_adc_trig_info stm32f4_adc_trigs[] = {
{}, /* sentinel */
};
+static const struct stm32_adc_regspec stm32f4_adc_regspec = {
+ .dr = STM32F4_ADC_DR,
+ .ier_eoc = { STM32F4_ADC_CR1, STM32F4_EOCIE },
+ .isr_eoc = { STM32F4_ADC_SR, STM32F4_EOC },
+ .sqr = stm32f4_sq,
+ .exten = { STM32F4_ADC_CR2, STM32F4_EXTEN_MASK, STM32F4_EXTEN_SHIFT },
+ .extsel = { STM32F4_ADC_CR2, STM32F4_EXTSEL_MASK,
+ STM32F4_EXTSEL_SHIFT },
+ .res = { STM32F4_ADC_CR1, STM32F4_RES_MASK, STM32F4_RES_SHIFT },
+};
+
+static const struct stm32_adc_regs stm32h7_sq[STM32_ADC_MAX_SQ + 1] = {
+ /* L: len bit field description to be kept as first element */
+ { STM32H7_ADC_SQR1, GENMASK(3, 0), 0 },
+ /* SQ1..SQ16 registers & bit fields (reg, mask, shift) */
+ { STM32H7_ADC_SQR1, GENMASK(10, 6), 6 },
+ { STM32H7_ADC_SQR1, GENMASK(16, 12), 12 },
+ { STM32H7_ADC_SQR1, GENMASK(22, 18), 18 },
+ { STM32H7_ADC_SQR1, GENMASK(28, 24), 24 },
+ { STM32H7_ADC_SQR2, GENMASK(4, 0), 0 },
+ { STM32H7_ADC_SQR2, GENMASK(10, 6), 6 },
+ { STM32H7_ADC_SQR2, GENMASK(16, 12), 12 },
+ { STM32H7_ADC_SQR2, GENMASK(22, 18), 18 },
+ { STM32H7_ADC_SQR2, GENMASK(28, 24), 24 },
+ { STM32H7_ADC_SQR3, GENMASK(4, 0), 0 },
+ { STM32H7_ADC_SQR3, GENMASK(10, 6), 6 },
+ { STM32H7_ADC_SQR3, GENMASK(16, 12), 12 },
+ { STM32H7_ADC_SQR3, GENMASK(22, 18), 18 },
+ { STM32H7_ADC_SQR3, GENMASK(28, 24), 24 },
+ { STM32H7_ADC_SQR4, GENMASK(4, 0), 0 },
+ { STM32H7_ADC_SQR4, GENMASK(10, 6), 6 },
+};
+
+/* STM32H7 external trigger sources for all instances */
+static struct stm32_adc_trig_info stm32h7_adc_trigs[] = {
+ { TIM1_CH1, STM32_EXT0 },
+ { TIM1_CH2, STM32_EXT1 },
+ { TIM1_CH3, STM32_EXT2 },
+ { TIM2_CH2, STM32_EXT3 },
+ { TIM3_TRGO, STM32_EXT4 },
+ { TIM4_CH4, STM32_EXT5 },
+ { TIM8_TRGO, STM32_EXT7 },
+ { TIM8_TRGO2, STM32_EXT8 },
+ { TIM1_TRGO, STM32_EXT9 },
+ { TIM1_TRGO2, STM32_EXT10 },
+ { TIM2_TRGO, STM32_EXT11 },
+ { TIM4_TRGO, STM32_EXT12 },
+ { TIM6_TRGO, STM32_EXT13 },
+ { TIM3_CH4, STM32_EXT15 },
+ {},
+};
+
+static const struct stm32_adc_regspec stm32h7_adc_regspec = {
+ .dr = STM32H7_ADC_DR,
+ .ier_eoc = { STM32H7_ADC_IER, STM32H7_EOCIE },
+ .isr_eoc = { STM32H7_ADC_ISR, STM32H7_EOC },
+ .sqr = stm32h7_sq,
+ .exten = { STM32H7_ADC_CFGR, STM32H7_EXTEN_MASK, STM32H7_EXTEN_SHIFT },
+ .extsel = { STM32H7_ADC_CFGR, STM32H7_EXTSEL_MASK,
+ STM32H7_EXTSEL_SHIFT },
+ .res = { STM32H7_ADC_CFGR, STM32H7_RES_MASK, STM32H7_RES_SHIFT },
+};
+
/**
* STM32 ADC registers access routines
* @adc: stm32 adc instance
@@ -265,6 +507,12 @@ static u32 stm32_adc_readl(struct stm32_adc *adc, u32 reg)
return readl_relaxed(adc->common->base + adc->offset + reg);
}
+#define stm32_adc_readl_addr(addr) stm32_adc_readl(adc, addr)
+
+#define stm32_adc_readl_poll_timeout(reg, val, cond, sleep_us, timeout_us) \
+ readx_poll_timeout(stm32_adc_readl_addr, reg, val, \
+ cond, sleep_us, timeout_us)
+
static u16 stm32_adc_readw(struct stm32_adc *adc, u32 reg)
{
return readw_relaxed(adc->common->base + adc->offset + reg);
@@ -299,7 +547,8 @@ static void stm32_adc_clr_bits(struct stm32_adc *adc, u32 reg, u32 bits)
*/
static void stm32_adc_conv_irq_enable(struct stm32_adc *adc)
{
- stm32_adc_set_bits(adc, STM32F4_ADC_CR1, STM32F4_EOCIE);
+ stm32_adc_set_bits(adc, adc->cfg->regs->ier_eoc.reg,
+ adc->cfg->regs->ier_eoc.mask);
};
/**
@@ -308,19 +557,22 @@ static void stm32_adc_conv_irq_enable(struct stm32_adc *adc)
*/
static void stm32_adc_conv_irq_disable(struct stm32_adc *adc)
{
- stm32_adc_clr_bits(adc, STM32F4_ADC_CR1, STM32F4_EOCIE);
+ stm32_adc_clr_bits(adc, adc->cfg->regs->ier_eoc.reg,
+ adc->cfg->regs->ier_eoc.mask);
}
static void stm32_adc_set_res(struct stm32_adc *adc)
{
- u32 val = stm32_adc_readl(adc, STM32F4_ADC_CR1);
+ const struct stm32_adc_regs *res = &adc->cfg->regs->res;
+ u32 val;
- val = (val & ~STM32F4_RES_MASK) | (adc->res << STM32F4_RES_SHIFT);
- stm32_adc_writel(adc, STM32F4_ADC_CR1, val);
+ val = stm32_adc_readl(adc, res->reg);
+ val = (val & ~res->mask) | (adc->res << res->shift);
+ stm32_adc_writel(adc, res->reg, val);
}
/**
- * stm32_adc_start_conv() - Start conversions for regular channels.
+ * stm32f4_adc_start_conv() - Start conversions for regular channels.
* @adc: stm32 adc instance
* @dma: use dma to transfer conversion result
*
@@ -329,7 +581,7 @@ static void stm32_adc_set_res(struct stm32_adc *adc)
* conversions, in IIO buffer modes. Otherwise, use ADC interrupt with direct
* DR read instead (e.g. read_raw, or triggered buffer mode without DMA).
*/
-static void stm32_adc_start_conv(struct stm32_adc *adc, bool dma)
+static void stm32f4_adc_start_conv(struct stm32_adc *adc, bool dma)
{
stm32_adc_set_bits(adc, STM32F4_ADC_CR1, STM32F4_SCAN);
@@ -347,7 +599,7 @@ static void stm32_adc_start_conv(struct stm32_adc *adc, bool dma)
stm32_adc_set_bits(adc, STM32F4_ADC_CR2, STM32F4_SWSTART);
}
-static void stm32_adc_stop_conv(struct stm32_adc *adc)
+static void stm32f4_adc_stop_conv(struct stm32_adc *adc)
{
stm32_adc_clr_bits(adc, STM32F4_ADC_CR2, STM32F4_EXTEN_MASK);
stm32_adc_clr_bits(adc, STM32F4_ADC_SR, STM32F4_STRT);
@@ -357,6 +609,324 @@ static void stm32_adc_stop_conv(struct stm32_adc *adc)
STM32F4_ADON | STM32F4_DMA | STM32F4_DDS);
}
+static void stm32h7_adc_start_conv(struct stm32_adc *adc, bool dma)
+{
+ enum stm32h7_adc_dmngt dmngt;
+ unsigned long flags;
+ u32 val;
+
+ if (dma)
+ dmngt = STM32H7_DMNGT_DMA_CIRC;
+ else
+ dmngt = STM32H7_DMNGT_DR_ONLY;
+
+ spin_lock_irqsave(&adc->lock, flags);
+ val = stm32_adc_readl(adc, STM32H7_ADC_CFGR);
+ val = (val & ~STM32H7_DMNGT_MASK) | (dmngt << STM32H7_DMNGT_SHIFT);
+ stm32_adc_writel(adc, STM32H7_ADC_CFGR, val);
+ spin_unlock_irqrestore(&adc->lock, flags);
+
+ stm32_adc_set_bits(adc, STM32H7_ADC_CR, STM32H7_ADSTART);
+}
+
+static void stm32h7_adc_stop_conv(struct stm32_adc *adc)
+{
+ struct iio_dev *indio_dev = iio_priv_to_dev(adc);
+ int ret;
+ u32 val;
+
+ stm32_adc_set_bits(adc, STM32H7_ADC_CR, STM32H7_ADSTP);
+
+ ret = stm32_adc_readl_poll_timeout(STM32H7_ADC_CR, val,
+ !(val & (STM32H7_ADSTART)),
+ 100, STM32_ADC_TIMEOUT_US);
+ if (ret)
+ dev_warn(&indio_dev->dev, "stop failed\n");
+
+ stm32_adc_clr_bits(adc, STM32H7_ADC_CFGR, STM32H7_DMNGT_MASK);
+}
+
+static void stm32h7_adc_exit_pwr_down(struct stm32_adc *adc)
+{
+ /* Exit deep power down, then enable ADC voltage regulator */
+ stm32_adc_clr_bits(adc, STM32H7_ADC_CR, STM32H7_DEEPPWD);
+ stm32_adc_set_bits(adc, STM32H7_ADC_CR, STM32H7_ADVREGEN);
+
+ if (adc->common->rate > STM32H7_BOOST_CLKRATE)
+ stm32_adc_set_bits(adc, STM32H7_ADC_CR, STM32H7_BOOST);
+
+ /* Wait for startup time */
+ usleep_range(10, 20);
+}
+
+static void stm32h7_adc_enter_pwr_down(struct stm32_adc *adc)
+{
+ stm32_adc_clr_bits(adc, STM32H7_ADC_CR, STM32H7_BOOST);
+
+ /* Setting DEEPPWD disables ADC vreg and clears ADVREGEN */
+ stm32_adc_set_bits(adc, STM32H7_ADC_CR, STM32H7_DEEPPWD);
+}
+
+static int stm32h7_adc_enable(struct stm32_adc *adc)
+{
+ struct iio_dev *indio_dev = iio_priv_to_dev(adc);
+ int ret;
+ u32 val;
+
+ /* Clear ADRDY by writing one, then enable ADC */
+ stm32_adc_set_bits(adc, STM32H7_ADC_ISR, STM32H7_ADRDY);
+ stm32_adc_set_bits(adc, STM32H7_ADC_CR, STM32H7_ADEN);
+
+ /* Poll for ADRDY to be set (after adc startup time) */
+ ret = stm32_adc_readl_poll_timeout(STM32H7_ADC_ISR, val,
+ val & STM32H7_ADRDY,
+ 100, STM32_ADC_TIMEOUT_US);
+ if (ret) {
+ stm32_adc_clr_bits(adc, STM32H7_ADC_CR, STM32H7_ADEN);
+ dev_err(&indio_dev->dev, "Failed to enable ADC\n");
+ }
+
+ return ret;
+}
+
+static void stm32h7_adc_disable(struct stm32_adc *adc)
+{
+ struct iio_dev *indio_dev = iio_priv_to_dev(adc);
+ int ret;
+ u32 val;
+
+ /* Disable ADC and wait until it's effectively disabled */
+ stm32_adc_set_bits(adc, STM32H7_ADC_CR, STM32H7_ADDIS);
+ ret = stm32_adc_readl_poll_timeout(STM32H7_ADC_CR, val,
+ !(val & STM32H7_ADEN), 100,
+ STM32_ADC_TIMEOUT_US);
+ if (ret)
+ dev_warn(&indio_dev->dev, "Failed to disable\n");
+}
+
+/**
+ * stm32h7_adc_read_selfcalib() - read calibration shadow regs, save result
+ * @adc: stm32 adc instance
+ */
+static int stm32h7_adc_read_selfcalib(struct stm32_adc *adc)
+{
+ struct iio_dev *indio_dev = iio_priv_to_dev(adc);
+ int i, ret;
+ u32 lincalrdyw_mask, val;
+
+ /* Enable adc so LINCALRDYW1..6 bits are writable */
+ ret = stm32h7_adc_enable(adc);
+ if (ret)
+ return ret;
+
+ /* Read linearity calibration */
+ lincalrdyw_mask = STM32H7_LINCALRDYW6;
+ for (i = STM32H7_LINCALFACT_NUM - 1; i >= 0; i--) {
+ /* Clear STM32H7_LINCALRDYW[6..1]: transfer calib to CALFACT2 */
+ stm32_adc_clr_bits(adc, STM32H7_ADC_CR, lincalrdyw_mask);
+
+ /* Poll: wait calib data to be ready in CALFACT2 register */
+ ret = stm32_adc_readl_poll_timeout(STM32H7_ADC_CR, val,
+ !(val & lincalrdyw_mask),
+ 100, STM32_ADC_TIMEOUT_US);
+ if (ret) {
+ dev_err(&indio_dev->dev, "Failed to read calfact\n");
+ goto disable;
+ }
+
+ val = stm32_adc_readl(adc, STM32H7_ADC_CALFACT2);
+ adc->cal.lincalfact[i] = (val & STM32H7_LINCALFACT_MASK);
+ adc->cal.lincalfact[i] >>= STM32H7_LINCALFACT_SHIFT;
+
+ lincalrdyw_mask >>= 1;
+ }
+
+ /* Read offset calibration */
+ val = stm32_adc_readl(adc, STM32H7_ADC_CALFACT);
+ adc->cal.calfact_s = (val & STM32H7_CALFACT_S_MASK);
+ adc->cal.calfact_s >>= STM32H7_CALFACT_S_SHIFT;
+ adc->cal.calfact_d = (val & STM32H7_CALFACT_D_MASK);
+ adc->cal.calfact_d >>= STM32H7_CALFACT_D_SHIFT;
+
+disable:
+ stm32h7_adc_disable(adc);
+
+ return ret;
+}
+
+/**
+ * stm32h7_adc_restore_selfcalib() - Restore saved self-calibration result
+ * @adc: stm32 adc instance
+ * Note: ADC must be enabled, with no on-going conversions.
+ */
+static int stm32h7_adc_restore_selfcalib(struct stm32_adc *adc)
+{
+ struct iio_dev *indio_dev = iio_priv_to_dev(adc);
+ int i, ret;
+ u32 lincalrdyw_mask, val;
+
+ val = (adc->cal.calfact_s << STM32H7_CALFACT_S_SHIFT) |
+ (adc->cal.calfact_d << STM32H7_CALFACT_D_SHIFT);
+ stm32_adc_writel(adc, STM32H7_ADC_CALFACT, val);
+
+ lincalrdyw_mask = STM32H7_LINCALRDYW6;
+ for (i = STM32H7_LINCALFACT_NUM - 1; i >= 0; i--) {
+ /*
+ * Write saved calibration data to shadow registers:
+ * Write CALFACT2, and set LINCALRDYW[6..1] bit to trigger
+ * data write. Then poll to wait for complete transfer.
+ */
+ val = adc->cal.lincalfact[i] << STM32H7_LINCALFACT_SHIFT;
+ stm32_adc_writel(adc, STM32H7_ADC_CALFACT2, val);
+ stm32_adc_set_bits(adc, STM32H7_ADC_CR, lincalrdyw_mask);
+ ret = stm32_adc_readl_poll_timeout(STM32H7_ADC_CR, val,
+ val & lincalrdyw_mask,
+ 100, STM32_ADC_TIMEOUT_US);
+ if (ret) {
+ dev_err(&indio_dev->dev, "Failed to write calfact\n");
+ return ret;
+ }
+
+ /*
+ * Read back calibration data, has two effects:
+ * - It ensures bits LINCALRDYW[6..1] are kept cleared
+ * for next time calibration needs to be restored.
+ * - BTW, bit clear triggers a read, then check data has been
+ * correctly written.
+ */
+ stm32_adc_clr_bits(adc, STM32H7_ADC_CR, lincalrdyw_mask);
+ ret = stm32_adc_readl_poll_timeout(STM32H7_ADC_CR, val,
+ !(val & lincalrdyw_mask),
+ 100, STM32_ADC_TIMEOUT_US);
+ if (ret) {
+ dev_err(&indio_dev->dev, "Failed to read calfact\n");
+ return ret;
+ }
+ val = stm32_adc_readl(adc, STM32H7_ADC_CALFACT2);
+ if (val != adc->cal.lincalfact[i] << STM32H7_LINCALFACT_SHIFT) {
+ dev_err(&indio_dev->dev, "calfact not consistent\n");
+ return -EIO;
+ }
+
+ lincalrdyw_mask >>= 1;
+ }
+
+ return 0;
+}
+
+/**
+ * Fixed timeout value for ADC calibration.
+ * worst cases:
+ * - low clock frequency
+ * - maximum prescalers
+ * Calibration requires:
+ * - 131,072 ADC clock cycle for the linear calibration
+ * - 20 ADC clock cycle for the offset calibration
+ *
+ * Set to 100ms for now
+ */
+#define STM32H7_ADC_CALIB_TIMEOUT_US 100000
+
+/**
+ * stm32h7_adc_selfcalib() - Procedure to calibrate ADC (from power down)
+ * @adc: stm32 adc instance
+ * Exit from power down, calibrate ADC, then return to power down.
+ */
+static int stm32h7_adc_selfcalib(struct stm32_adc *adc)
+{
+ struct iio_dev *indio_dev = iio_priv_to_dev(adc);
+ int ret;
+ u32 val;
+
+ stm32h7_adc_exit_pwr_down(adc);
+
+ /*
+ * Select calibration mode:
+ * - Offset calibration for single ended inputs
+ * - No linearity calibration (do it later, before reading it)
+ */
+ stm32_adc_clr_bits(adc, STM32H7_ADC_CR, STM32H7_ADCALDIF);
+ stm32_adc_clr_bits(adc, STM32H7_ADC_CR, STM32H7_ADCALLIN);
+
+ /* Start calibration, then wait for completion */
+ stm32_adc_set_bits(adc, STM32H7_ADC_CR, STM32H7_ADCAL);
+ ret = stm32_adc_readl_poll_timeout(STM32H7_ADC_CR, val,
+ !(val & STM32H7_ADCAL), 100,
+ STM32H7_ADC_CALIB_TIMEOUT_US);
+ if (ret) {
+ dev_err(&indio_dev->dev, "calibration failed\n");
+ goto pwr_dwn;
+ }
+
+ /*
+ * Select calibration mode, then start calibration:
+ * - Offset calibration for differential input
+ * - Linearity calibration (needs to be done only once for single/diff)
+ * will run simultaneously with offset calibration.
+ */
+ stm32_adc_set_bits(adc, STM32H7_ADC_CR,
+ STM32H7_ADCALDIF | STM32H7_ADCALLIN);
+ stm32_adc_set_bits(adc, STM32H7_ADC_CR, STM32H7_ADCAL);
+ ret = stm32_adc_readl_poll_timeout(STM32H7_ADC_CR, val,
+ !(val & STM32H7_ADCAL), 100,
+ STM32H7_ADC_CALIB_TIMEOUT_US);
+ if (ret) {
+ dev_err(&indio_dev->dev, "calibration failed\n");
+ goto pwr_dwn;
+ }
+
+ stm32_adc_clr_bits(adc, STM32H7_ADC_CR,
+ STM32H7_ADCALDIF | STM32H7_ADCALLIN);
+
+ /* Read calibration result for future reference */
+ ret = stm32h7_adc_read_selfcalib(adc);
+
+pwr_dwn:
+ stm32h7_adc_enter_pwr_down(adc);
+
+ return ret;
+}
+
+/**
+ * stm32h7_adc_prepare() - Leave power down mode to enable ADC.
+ * @adc: stm32 adc instance
+ * Leave power down mode.
+ * Enable ADC.
+ * Restore calibration data.
+ * Pre-select channels that may be used in PCSEL (required by input MUX / IO).
+ */
+static int stm32h7_adc_prepare(struct stm32_adc *adc)
+{
+ int ret;
+
+ stm32h7_adc_exit_pwr_down(adc);
+
+ ret = stm32h7_adc_enable(adc);
+ if (ret)
+ goto pwr_dwn;
+
+ ret = stm32h7_adc_restore_selfcalib(adc);
+ if (ret)
+ goto disable;
+
+ stm32_adc_writel(adc, STM32H7_ADC_PCSEL, adc->pcsel);
+
+ return 0;
+
+disable:
+ stm32h7_adc_disable(adc);
+pwr_dwn:
+ stm32h7_adc_enter_pwr_down(adc);
+
+ return ret;
+}
+
+static void stm32h7_adc_unprepare(struct stm32_adc *adc)
+{
+ stm32h7_adc_disable(adc);
+ stm32h7_adc_enter_pwr_down(adc);
+}
+
/**
* stm32_adc_conf_scan_seq() - Build regular channels scan sequence
* @indio_dev: IIO device
@@ -371,6 +941,7 @@ static int stm32_adc_conf_scan_seq(struct iio_dev *indio_dev,
const unsigned long *scan_mask)
{
struct stm32_adc *adc = iio_priv(indio_dev);
+ const struct stm32_adc_regs *sqr = adc->cfg->regs->sqr;
const struct iio_chan_spec *chan;
u32 val, bit;
int i = 0;
@@ -388,20 +959,20 @@ static int stm32_adc_conf_scan_seq(struct iio_dev *indio_dev,
dev_dbg(&indio_dev->dev, "%s chan %d to SQ%d\n",
__func__, chan->channel, i);
- val = stm32_adc_readl(adc, stm32f4_sq[i].reg);
- val &= ~stm32f4_sq[i].mask;
- val |= chan->channel << stm32f4_sq[i].shift;
- stm32_adc_writel(adc, stm32f4_sq[i].reg, val);
+ val = stm32_adc_readl(adc, sqr[i].reg);
+ val &= ~sqr[i].mask;
+ val |= chan->channel << sqr[i].shift;
+ stm32_adc_writel(adc, sqr[i].reg, val);
}
if (!i)
return -EINVAL;
/* Sequence len */
- val = stm32_adc_readl(adc, stm32f4_sq[0].reg);
- val &= ~stm32f4_sq[0].mask;
- val |= ((i - 1) << stm32f4_sq[0].shift);
- stm32_adc_writel(adc, stm32f4_sq[0].reg, val);
+ val = stm32_adc_readl(adc, sqr[0].reg);
+ val &= ~sqr[0].mask;
+ val |= ((i - 1) << sqr[0].shift);
+ stm32_adc_writel(adc, sqr[0].reg, val);
return 0;
}
@@ -412,19 +983,21 @@ static int stm32_adc_conf_scan_seq(struct iio_dev *indio_dev,
*
* Returns trigger extsel value, if trig matches, -EINVAL otherwise.
*/
-static int stm32_adc_get_trig_extsel(struct iio_trigger *trig)
+static int stm32_adc_get_trig_extsel(struct iio_dev *indio_dev,
+ struct iio_trigger *trig)
{
+ struct stm32_adc *adc = iio_priv(indio_dev);
int i;
/* lookup triggers registered by stm32 timer trigger driver */
- for (i = 0; stm32f4_adc_trigs[i].name; i++) {
+ for (i = 0; adc->cfg->trigs[i].name; i++) {
/**
* Checking both stm32 timer trigger type and trig name
* should be safe against arbitrary trigger names.
*/
if (is_stm32_timer_trigger(trig) &&
- !strcmp(stm32f4_adc_trigs[i].name, trig->name)) {
- return stm32f4_adc_trigs[i].extsel;
+ !strcmp(adc->cfg->trigs[i].name, trig->name)) {
+ return adc->cfg->trigs[i].extsel;
}
}
@@ -449,7 +1022,7 @@ static int stm32_adc_set_trig(struct iio_dev *indio_dev,
int ret;
if (trig) {
- ret = stm32_adc_get_trig_extsel(trig);
+ ret = stm32_adc_get_trig_extsel(indio_dev, trig);
if (ret < 0)
return ret;
@@ -459,11 +1032,11 @@ static int stm32_adc_set_trig(struct iio_dev *indio_dev,
}
spin_lock_irqsave(&adc->lock, flags);
- val = stm32_adc_readl(adc, STM32F4_ADC_CR2);
- val &= ~(STM32F4_EXTEN_MASK | STM32F4_EXTSEL_MASK);
- val |= exten << STM32F4_EXTEN_SHIFT;
- val |= extsel << STM32F4_EXTSEL_SHIFT;
- stm32_adc_writel(adc, STM32F4_ADC_CR2, val);
+ val = stm32_adc_readl(adc, adc->cfg->regs->exten.reg);
+ val &= ~(adc->cfg->regs->exten.mask | adc->cfg->regs->extsel.mask);
+ val |= exten << adc->cfg->regs->exten.shift;
+ val |= extsel << adc->cfg->regs->extsel.shift;
+ stm32_adc_writel(adc, adc->cfg->regs->exten.reg, val);
spin_unlock_irqrestore(&adc->lock, flags);
return 0;
@@ -515,6 +1088,7 @@ static int stm32_adc_single_conv(struct iio_dev *indio_dev,
int *res)
{
struct stm32_adc *adc = iio_priv(indio_dev);
+ const struct stm32_adc_regspec *regs = adc->cfg->regs;
long timeout;
u32 val;
int ret;
@@ -523,21 +1097,27 @@ static int stm32_adc_single_conv(struct iio_dev *indio_dev,
adc->bufi = 0;
+ if (adc->cfg->prepare) {
+ ret = adc->cfg->prepare(adc);
+ if (ret)
+ return ret;
+ }
+
/* Program chan number in regular sequence (SQ1) */
- val = stm32_adc_readl(adc, stm32f4_sq[1].reg);
- val &= ~stm32f4_sq[1].mask;
- val |= chan->channel << stm32f4_sq[1].shift;
- stm32_adc_writel(adc, stm32f4_sq[1].reg, val);
+ val = stm32_adc_readl(adc, regs->sqr[1].reg);
+ val &= ~regs->sqr[1].mask;
+ val |= chan->channel << regs->sqr[1].shift;
+ stm32_adc_writel(adc, regs->sqr[1].reg, val);
/* Set regular sequence len (0 for 1 conversion) */
- stm32_adc_clr_bits(adc, stm32f4_sq[0].reg, stm32f4_sq[0].mask);
+ stm32_adc_clr_bits(adc, regs->sqr[0].reg, regs->sqr[0].mask);
/* Trigger detection disabled (conversion can be launched in SW) */
- stm32_adc_clr_bits(adc, STM32F4_ADC_CR2, STM32F4_EXTEN_MASK);
+ stm32_adc_clr_bits(adc, regs->exten.reg, regs->exten.mask);
stm32_adc_conv_irq_enable(adc);
- stm32_adc_start_conv(adc, false);
+ adc->cfg->start_conv(adc, false);
timeout = wait_for_completion_interruptible_timeout(
&adc->completion, STM32_ADC_TIMEOUT);
@@ -550,10 +1130,13 @@ static int stm32_adc_single_conv(struct iio_dev *indio_dev,
ret = IIO_VAL_INT;
}
- stm32_adc_stop_conv(adc);
+ adc->cfg->stop_conv(adc);
stm32_adc_conv_irq_disable(adc);
+ if (adc->cfg->unprepare)
+ adc->cfg->unprepare(adc);
+
return ret;
}
@@ -590,11 +1173,12 @@ static irqreturn_t stm32_adc_isr(int irq, void *data)
{
struct stm32_adc *adc = data;
struct iio_dev *indio_dev = iio_priv_to_dev(adc);
- u32 status = stm32_adc_readl(adc, STM32F4_ADC_SR);
+ const struct stm32_adc_regspec *regs = adc->cfg->regs;
+ u32 status = stm32_adc_readl(adc, regs->isr_eoc.reg);
- if (status & STM32F4_EOC) {
+ if (status & regs->isr_eoc.mask) {
/* Reading DR also clears EOC status flag */
- adc->buffer[adc->bufi] = stm32_adc_readw(adc, STM32F4_ADC_DR);
+ adc->buffer[adc->bufi] = stm32_adc_readw(adc, regs->dr);
if (iio_buffer_enabled(indio_dev)) {
adc->bufi++;
if (adc->bufi >= adc->num_conv) {
@@ -621,7 +1205,7 @@ static irqreturn_t stm32_adc_isr(int irq, void *data)
static int stm32_adc_validate_trigger(struct iio_dev *indio_dev,
struct iio_trigger *trig)
{
- return stm32_adc_get_trig_extsel(trig) < 0 ? -EINVAL : 0;
+ return stm32_adc_get_trig_extsel(indio_dev, trig) < 0 ? -EINVAL : 0;
}
static int stm32_adc_set_watermark(struct iio_dev *indio_dev, unsigned int val)
@@ -777,10 +1361,16 @@ static int stm32_adc_buffer_postenable(struct iio_dev *indio_dev)
struct stm32_adc *adc = iio_priv(indio_dev);
int ret;
+ if (adc->cfg->prepare) {
+ ret = adc->cfg->prepare(adc);
+ if (ret)
+ return ret;
+ }
+
ret = stm32_adc_set_trig(indio_dev, indio_dev->trig);
if (ret) {
dev_err(&indio_dev->dev, "Can't set trigger\n");
- return ret;
+ goto err_unprepare;
}
ret = stm32_adc_dma_start(indio_dev);
@@ -799,7 +1389,7 @@ static int stm32_adc_buffer_postenable(struct iio_dev *indio_dev)
if (!adc->dma_chan)
stm32_adc_conv_irq_enable(adc);
- stm32_adc_start_conv(adc, !!adc->dma_chan);
+ adc->cfg->start_conv(adc, !!adc->dma_chan);
return 0;
@@ -808,6 +1398,9 @@ err_stop_dma:
dmaengine_terminate_all(adc->dma_chan);
err_clr_trig:
stm32_adc_set_trig(indio_dev, NULL);
+err_unprepare:
+ if (adc->cfg->unprepare)
+ adc->cfg->unprepare(adc);
return ret;
}
@@ -817,7 +1410,7 @@ static int stm32_adc_buffer_predisable(struct iio_dev *indio_dev)
struct stm32_adc *adc = iio_priv(indio_dev);
int ret;
- stm32_adc_stop_conv(adc);
+ adc->cfg->stop_conv(adc);
if (!adc->dma_chan)
stm32_adc_conv_irq_disable(adc);
@@ -831,6 +1424,9 @@ static int stm32_adc_buffer_predisable(struct iio_dev *indio_dev)
if (stm32_adc_set_trig(indio_dev, NULL))
dev_err(&indio_dev->dev, "Can't clear trigger\n");
+ if (adc->cfg->unprepare)
+ adc->cfg->unprepare(adc);
+
return ret;
}
@@ -895,12 +1491,12 @@ static int stm32_adc_of_get_resolution(struct iio_dev *indio_dev)
u32 res;
if (of_property_read_u32(node, "assigned-resolution-bits", &res))
- res = stm32f4_adc_resolutions[0];
+ res = adc->cfg->adc_info->resolutions[0];
- for (i = 0; i < ARRAY_SIZE(stm32f4_adc_resolutions); i++)
- if (res == stm32f4_adc_resolutions[i])
+ for (i = 0; i < adc->cfg->adc_info->num_res; i++)
+ if (res == adc->cfg->adc_info->resolutions[i])
break;
- if (i >= ARRAY_SIZE(stm32f4_adc_resolutions)) {
+ if (i >= adc->cfg->adc_info->num_res) {
dev_err(&indio_dev->dev, "Bad resolution: %u bits\n", res);
return -EINVAL;
}
@@ -926,14 +1522,19 @@ static void stm32_adc_chan_init_one(struct iio_dev *indio_dev,
chan->info_mask_separate = BIT(IIO_CHAN_INFO_RAW);
chan->info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE);
chan->scan_type.sign = 'u';
- chan->scan_type.realbits = stm32f4_adc_resolutions[adc->res];
+ chan->scan_type.realbits = adc->cfg->adc_info->resolutions[adc->res];
chan->scan_type.storagebits = 16;
chan->ext_info = stm32_adc_ext_info;
+
+ /* pre-build selected channels mask */
+ adc->pcsel |= BIT(chan->channel);
}
static int stm32_adc_chan_of_init(struct iio_dev *indio_dev)
{
struct device_node *node = indio_dev->dev.of_node;
+ struct stm32_adc *adc = iio_priv(indio_dev);
+ const struct stm32_adc_info *adc_info = adc->cfg->adc_info;
struct property *prop;
const __be32 *cur;
struct iio_chan_spec *channels;
@@ -942,7 +1543,7 @@ static int stm32_adc_chan_of_init(struct iio_dev *indio_dev)
num_channels = of_property_count_u32_elems(node, "st,adc-channels");
if (num_channels < 0 ||
- num_channels >= ARRAY_SIZE(stm32f4_adc123_channels)) {
+ num_channels >= adc_info->max_channels) {
dev_err(&indio_dev->dev, "Bad st,adc-channels?\n");
return num_channels < 0 ? num_channels : -EINVAL;
}
@@ -953,12 +1554,12 @@ static int stm32_adc_chan_of_init(struct iio_dev *indio_dev)
return -ENOMEM;
of_property_for_each_u32(node, "st,adc-channels", prop, cur, val) {
- if (val >= ARRAY_SIZE(stm32f4_adc123_channels)) {
+ if (val >= adc_info->max_channels) {
dev_err(&indio_dev->dev, "Invalid channel %d\n", val);
return -EINVAL;
}
stm32_adc_chan_init_one(indio_dev, &channels[scan_index],
- &stm32f4_adc123_channels[val],
+ &adc_info->channels[val],
scan_index);
scan_index++;
}
@@ -990,7 +1591,7 @@ static int stm32_adc_dma_request(struct iio_dev *indio_dev)
/* Configure DMA channel to read data register */
memset(&config, 0, sizeof(config));
config.src_addr = (dma_addr_t)adc->common->phys_base;
- config.src_addr += adc->offset + STM32F4_ADC_DR;
+ config.src_addr += adc->offset + adc->cfg->regs->dr;
config.src_addr_width = DMA_SLAVE_BUSWIDTH_2_BYTES;
ret = dmaengine_slave_config(adc->dma_chan, &config);
@@ -1011,6 +1612,7 @@ err_release:
static int stm32_adc_probe(struct platform_device *pdev)
{
struct iio_dev *indio_dev;
+ struct device *dev = &pdev->dev;
struct stm32_adc *adc;
int ret;
@@ -1025,6 +1627,8 @@ static int stm32_adc_probe(struct platform_device *pdev)
adc->common = dev_get_drvdata(pdev->dev.parent);
spin_lock_init(&adc->lock);
init_completion(&adc->completion);
+ adc->cfg = (const struct stm32_adc_cfg *)
+ of_match_device(dev->driver->of_match_table, dev)->data;
indio_dev->name = dev_name(&pdev->dev);
indio_dev->dev.parent = &pdev->dev;
@@ -1055,14 +1659,21 @@ static int stm32_adc_probe(struct platform_device *pdev)
adc->clk = devm_clk_get(&pdev->dev, NULL);
if (IS_ERR(adc->clk)) {
- dev_err(&pdev->dev, "Can't get clock\n");
- return PTR_ERR(adc->clk);
+ ret = PTR_ERR(adc->clk);
+ if (ret == -ENOENT && !adc->cfg->clk_required) {
+ adc->clk = NULL;
+ } else {
+ dev_err(&pdev->dev, "Can't get clock\n");
+ return ret;
+ }
}
- ret = clk_prepare_enable(adc->clk);
- if (ret < 0) {
- dev_err(&pdev->dev, "clk enable failed\n");
- return ret;
+ if (adc->clk) {
+ ret = clk_prepare_enable(adc->clk);
+ if (ret < 0) {
+ dev_err(&pdev->dev, "clk enable failed\n");
+ return ret;
+ }
}
ret = stm32_adc_of_get_resolution(indio_dev);
@@ -1070,6 +1681,12 @@ static int stm32_adc_probe(struct platform_device *pdev)
goto err_clk_disable;
stm32_adc_set_res(adc);
+ if (adc->cfg->selfcalib) {
+ ret = adc->cfg->selfcalib(adc);
+ if (ret)
+ goto err_clk_disable;
+ }
+
ret = stm32_adc_chan_of_init(indio_dev);
if (ret < 0)
goto err_clk_disable;
@@ -1106,7 +1723,8 @@ err_dma_disable:
dma_release_channel(adc->dma_chan);
}
err_clk_disable:
- clk_disable_unprepare(adc->clk);
+ if (adc->clk)
+ clk_disable_unprepare(adc->clk);
return ret;
}
@@ -1124,13 +1742,35 @@ static int stm32_adc_remove(struct platform_device *pdev)
adc->rx_buf, adc->rx_dma_buf);
dma_release_channel(adc->dma_chan);
}
- clk_disable_unprepare(adc->clk);
+ if (adc->clk)
+ clk_disable_unprepare(adc->clk);
return 0;
}
+static const struct stm32_adc_cfg stm32f4_adc_cfg = {
+ .regs = &stm32f4_adc_regspec,
+ .adc_info = &stm32f4_adc_info,
+ .trigs = stm32f4_adc_trigs,
+ .clk_required = true,
+ .start_conv = stm32f4_adc_start_conv,
+ .stop_conv = stm32f4_adc_stop_conv,
+};
+
+static const struct stm32_adc_cfg stm32h7_adc_cfg = {
+ .regs = &stm32h7_adc_regspec,
+ .adc_info = &stm32h7_adc_info,
+ .trigs = stm32h7_adc_trigs,
+ .selfcalib = stm32h7_adc_selfcalib,
+ .start_conv = stm32h7_adc_start_conv,
+ .stop_conv = stm32h7_adc_stop_conv,
+ .prepare = stm32h7_adc_prepare,
+ .unprepare = stm32h7_adc_unprepare,
+};
+
static const struct of_device_id stm32_adc_of_match[] = {
- { .compatible = "st,stm32f4-adc" },
+ { .compatible = "st,stm32f4-adc", .data = (void *)&stm32f4_adc_cfg },
+ { .compatible = "st,stm32h7-adc", .data = (void *)&stm32h7_adc_cfg },
{},
};
MODULE_DEVICE_TABLE(of, stm32_adc_of_match);
diff --git a/drivers/iio/adc/sun4i-gpadc-iio.c b/drivers/iio/adc/sun4i-gpadc-iio.c
index b23527309088..81d4c39e414a 100644
--- a/drivers/iio/adc/sun4i-gpadc-iio.c
+++ b/drivers/iio/adc/sun4i-gpadc-iio.c
@@ -105,6 +105,8 @@ struct sun4i_gpadc_iio {
bool no_irq;
/* prevents concurrent reads of temperature and ADC */
struct mutex mutex;
+ struct thermal_zone_device *tzd;
+ struct device *sensor_device;
};
#define SUN4I_GPADC_ADC_CHANNEL(_channel, _name) { \
@@ -502,7 +504,6 @@ static int sun4i_gpadc_probe_dt(struct platform_device *pdev,
{
struct sun4i_gpadc_iio *info = iio_priv(indio_dev);
const struct of_device_id *of_dev;
- struct thermal_zone_device *tzd;
struct resource *mem;
void __iomem *base;
int ret;
@@ -532,13 +533,14 @@ static int sun4i_gpadc_probe_dt(struct platform_device *pdev,
if (!IS_ENABLED(CONFIG_THERMAL_OF))
return 0;
- tzd = devm_thermal_zone_of_sensor_register(&pdev->dev, 0, info,
- &sun4i_ts_tz_ops);
- if (IS_ERR(tzd))
+ info->sensor_device = &pdev->dev;
+ info->tzd = thermal_zone_of_sensor_register(info->sensor_device, 0,
+ info, &sun4i_ts_tz_ops);
+ if (IS_ERR(info->tzd))
dev_err(&pdev->dev, "could not register thermal sensor: %ld\n",
- PTR_ERR(tzd));
+ PTR_ERR(info->tzd));
- return PTR_ERR_OR_ZERO(tzd);
+ return PTR_ERR_OR_ZERO(info->tzd);
}
static int sun4i_gpadc_probe_mfd(struct platform_device *pdev,
@@ -584,15 +586,15 @@ static int sun4i_gpadc_probe_mfd(struct platform_device *pdev,
* of_node, and the device from this driver as third argument to
* return the temperature.
*/
- struct thermal_zone_device *tzd;
- tzd = devm_thermal_zone_of_sensor_register(pdev->dev.parent, 0,
- info,
- &sun4i_ts_tz_ops);
- if (IS_ERR(tzd)) {
+ info->sensor_device = pdev->dev.parent;
+ info->tzd = thermal_zone_of_sensor_register(info->sensor_device,
+ 0, info,
+ &sun4i_ts_tz_ops);
+ if (IS_ERR(info->tzd)) {
dev_err(&pdev->dev,
"could not register thermal sensor: %ld\n",
- PTR_ERR(tzd));
- return PTR_ERR(tzd);
+ PTR_ERR(info->tzd));
+ return PTR_ERR(info->tzd);
}
} else {
indio_dev->num_channels =
@@ -688,7 +690,13 @@ static int sun4i_gpadc_remove(struct platform_device *pdev)
pm_runtime_put(&pdev->dev);
pm_runtime_disable(&pdev->dev);
- if (!info->no_irq && IS_ENABLED(CONFIG_THERMAL_OF))
+
+ if (!IS_ENABLED(CONFIG_THERMAL_OF))
+ return 0;
+
+ thermal_zone_of_sensor_unregister(info->sensor_device, info->tzd);
+
+ if (!info->no_irq)
iio_map_array_unregister(indio_dev);
return 0;
@@ -700,6 +708,7 @@ static const struct platform_device_id sun4i_gpadc_id[] = {
{ "sun6i-a31-gpadc-iio", (kernel_ulong_t)&sun6i_gpadc_data },
{ /* sentinel */ },
};
+MODULE_DEVICE_TABLE(platform, sun4i_gpadc_id);
static struct platform_driver sun4i_gpadc_driver = {
.driver = {
@@ -711,6 +720,7 @@ static struct platform_driver sun4i_gpadc_driver = {
.probe = sun4i_gpadc_probe,
.remove = sun4i_gpadc_remove,
};
+MODULE_DEVICE_TABLE(of, sun4i_gpadc_of_id);
module_platform_driver(sun4i_gpadc_driver);
diff --git a/drivers/iio/adc/ti-adc084s021.c b/drivers/iio/adc/ti-adc084s021.c
new file mode 100644
index 000000000000..a355121c11a4
--- /dev/null
+++ b/drivers/iio/adc/ti-adc084s021.c
@@ -0,0 +1,275 @@
+/**
+ * Copyright (C) 2017 Axis Communications AB
+ *
+ * Driver for Texas Instruments' ADC084S021 ADC chip.
+ * Datasheets can be found here:
+ * http://www.ti.com/lit/ds/symlink/adc084s021.pdf
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/err.h>
+#include <linux/spi/spi.h>
+#include <linux/module.h>
+#include <linux/interrupt.h>
+#include <linux/iio/iio.h>
+#include <linux/iio/buffer.h>
+#include <linux/iio/triggered_buffer.h>
+#include <linux/iio/trigger_consumer.h>
+#include <linux/regulator/consumer.h>
+
+#define ADC084S021_DRIVER_NAME "adc084s021"
+
+struct adc084s021 {
+ struct spi_device *spi;
+ struct spi_message message;
+ struct spi_transfer spi_trans;
+ struct regulator *reg;
+ struct mutex lock;
+ /*
+ * DMA (thus cache coherency maintenance) requires the
+ * transfer buffers to live in their own cache line.
+ */
+ u16 tx_buf[4] ____cacheline_aligned;
+ __be16 rx_buf[5]; /* First 16-bits are trash */
+};
+
+#define ADC084S021_VOLTAGE_CHANNEL(num) \
+ { \
+ .type = IIO_VOLTAGE, \
+ .channel = (num), \
+ .indexed = 1, \
+ .scan_index = (num), \
+ .scan_type = { \
+ .sign = 'u', \
+ .realbits = 8, \
+ .storagebits = 16, \
+ .shift = 4, \
+ .endianness = IIO_BE, \
+ }, \
+ .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \
+ .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE),\
+ }
+
+static const struct iio_chan_spec adc084s021_channels[] = {
+ ADC084S021_VOLTAGE_CHANNEL(0),
+ ADC084S021_VOLTAGE_CHANNEL(1),
+ ADC084S021_VOLTAGE_CHANNEL(2),
+ ADC084S021_VOLTAGE_CHANNEL(3),
+ IIO_CHAN_SOFT_TIMESTAMP(4),
+};
+
+/**
+ * Read an ADC channel and return its value.
+ *
+ * @adc: The ADC SPI data.
+ * @data: Buffer for converted data.
+ */
+static int adc084s021_adc_conversion(struct adc084s021 *adc, void *data)
+{
+ int n_words = (adc->spi_trans.len >> 1) - 1; /* Discard first word */
+ int ret, i = 0;
+ u16 *p = data;
+
+ /* Do the transfer */
+ ret = spi_sync(adc->spi, &adc->message);
+ if (ret < 0)
+ return ret;
+
+ for (; i < n_words; i++)
+ *(p + i) = adc->rx_buf[i + 1];
+
+ return ret;
+}
+
+static int adc084s021_read_raw(struct iio_dev *indio_dev,
+ struct iio_chan_spec const *channel, int *val,
+ int *val2, long mask)
+{
+ struct adc084s021 *adc = iio_priv(indio_dev);
+ int ret;
+
+ switch (mask) {
+ case IIO_CHAN_INFO_RAW:
+ ret = iio_device_claim_direct_mode(indio_dev);
+ if (ret < 0)
+ return ret;
+
+ ret = regulator_enable(adc->reg);
+ if (ret) {
+ iio_device_release_direct_mode(indio_dev);
+ return ret;
+ }
+
+ adc->tx_buf[0] = channel->channel << 3;
+ ret = adc084s021_adc_conversion(adc, val);
+ iio_device_release_direct_mode(indio_dev);
+ regulator_disable(adc->reg);
+ if (ret < 0)
+ return ret;
+
+ *val = be16_to_cpu(*val);
+ *val = (*val >> channel->scan_type.shift) & 0xff;
+
+ return IIO_VAL_INT;
+ case IIO_CHAN_INFO_SCALE:
+ ret = regulator_enable(adc->reg);
+ if (ret)
+ return ret;
+
+ ret = regulator_get_voltage(adc->reg);
+ regulator_disable(adc->reg);
+ if (ret < 0)
+ return ret;
+
+ *val = ret / 1000;
+
+ return IIO_VAL_INT;
+ default:
+ return -EINVAL;
+ }
+}
+
+/**
+ * Read enabled ADC channels and push data to the buffer.
+ *
+ * @irq: The interrupt number (not used).
+ * @pollfunc: Pointer to the poll func.
+ */
+static irqreturn_t adc084s021_buffer_trigger_handler(int irq, void *pollfunc)
+{
+ struct iio_poll_func *pf = pollfunc;
+ struct iio_dev *indio_dev = pf->indio_dev;
+ struct adc084s021 *adc = iio_priv(indio_dev);
+ __be16 data[8] = {0}; /* 4 * 16-bit words of data + 8 bytes timestamp */
+
+ mutex_lock(&adc->lock);
+
+ if (adc084s021_adc_conversion(adc, &data) < 0)
+ dev_err(&adc->spi->dev, "Failed to read data\n");
+
+ iio_push_to_buffers_with_timestamp(indio_dev, data,
+ iio_get_time_ns(indio_dev));
+ mutex_unlock(&adc->lock);
+ iio_trigger_notify_done(indio_dev->trig);
+
+ return IRQ_HANDLED;
+}
+
+static int adc084s021_buffer_preenable(struct iio_dev *indio_dev)
+{
+ struct adc084s021 *adc = iio_priv(indio_dev);
+ int scan_index;
+ int i = 0;
+
+ for_each_set_bit(scan_index, indio_dev->active_scan_mask,
+ indio_dev->masklength) {
+ const struct iio_chan_spec *channel =
+ &indio_dev->channels[scan_index];
+ adc->tx_buf[i++] = channel->channel << 3;
+ }
+ adc->spi_trans.len = 2 + (i * sizeof(__be16)); /* Trash + channels */
+
+ return regulator_enable(adc->reg);
+}
+
+static int adc084s021_buffer_postdisable(struct iio_dev *indio_dev)
+{
+ struct adc084s021 *adc = iio_priv(indio_dev);
+
+ adc->spi_trans.len = 4; /* Trash + single channel */
+
+ return regulator_disable(adc->reg);
+}
+
+static const struct iio_info adc084s021_info = {
+ .read_raw = adc084s021_read_raw,
+ .driver_module = THIS_MODULE,
+};
+
+static const struct iio_buffer_setup_ops adc084s021_buffer_setup_ops = {
+ .preenable = adc084s021_buffer_preenable,
+ .postenable = iio_triggered_buffer_postenable,
+ .predisable = iio_triggered_buffer_predisable,
+ .postdisable = adc084s021_buffer_postdisable,
+};
+
+static int adc084s021_probe(struct spi_device *spi)
+{
+ struct iio_dev *indio_dev;
+ struct adc084s021 *adc;
+ int ret;
+
+ indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*adc));
+ if (!indio_dev) {
+ dev_err(&spi->dev, "Failed to allocate IIO device\n");
+ return -ENOMEM;
+ }
+
+ adc = iio_priv(indio_dev);
+ adc->spi = spi;
+
+ /* Connect the SPI device and the iio dev */
+ spi_set_drvdata(spi, indio_dev);
+
+ /* Initiate the Industrial I/O device */
+ indio_dev->dev.parent = &spi->dev;
+ indio_dev->dev.of_node = spi->dev.of_node;
+ indio_dev->name = spi_get_device_id(spi)->name;
+ indio_dev->modes = INDIO_DIRECT_MODE;
+ indio_dev->info = &adc084s021_info;
+ indio_dev->channels = adc084s021_channels;
+ indio_dev->num_channels = ARRAY_SIZE(adc084s021_channels);
+
+ /* Create SPI transfer for channel reads */
+ adc->spi_trans.tx_buf = adc->tx_buf;
+ adc->spi_trans.rx_buf = adc->rx_buf;
+ adc->spi_trans.len = 4; /* Trash + single channel */
+ spi_message_init_with_transfers(&adc->message, &adc->spi_trans, 1);
+
+ adc->reg = devm_regulator_get(&spi->dev, "vref");
+ if (IS_ERR(adc->reg))
+ return PTR_ERR(adc->reg);
+
+ mutex_init(&adc->lock);
+
+ /* Setup triggered buffer with pollfunction */
+ ret = devm_iio_triggered_buffer_setup(&spi->dev, indio_dev, NULL,
+ adc084s021_buffer_trigger_handler,
+ &adc084s021_buffer_setup_ops);
+ if (ret) {
+ dev_err(&spi->dev, "Failed to setup triggered buffer\n");
+ return ret;
+ }
+
+ return devm_iio_device_register(&spi->dev, indio_dev);
+}
+
+static const struct of_device_id adc084s021_of_match[] = {
+ { .compatible = "ti,adc084s021", },
+ {},
+};
+MODULE_DEVICE_TABLE(of, adc084s021_of_match);
+
+static const struct spi_device_id adc084s021_id[] = {
+ { ADC084S021_DRIVER_NAME, 0},
+ {}
+};
+MODULE_DEVICE_TABLE(spi, adc084s021_id);
+
+static struct spi_driver adc084s021_driver = {
+ .driver = {
+ .name = ADC084S021_DRIVER_NAME,
+ .of_match_table = of_match_ptr(adc084s021_of_match),
+ },
+ .probe = adc084s021_probe,
+ .id_table = adc084s021_id,
+};
+module_spi_driver(adc084s021_driver);
+
+MODULE_AUTHOR("MÃ¥rten Lindahl <martenli@axis.com>");
+MODULE_DESCRIPTION("Texas Instruments ADC084S021");
+MODULE_LICENSE("GPL v2");
+MODULE_VERSION("1.0");
diff --git a/drivers/iio/adc/ti-adc108s102.c b/drivers/iio/adc/ti-adc108s102.c
new file mode 100644
index 000000000000..de4e5ac98c6e
--- /dev/null
+++ b/drivers/iio/adc/ti-adc108s102.c
@@ -0,0 +1,348 @@
+/*
+ * TI ADC108S102 SPI ADC driver
+ *
+ * Copyright (c) 2013-2015 Intel Corporation.
+ * Copyright (c) 2017 Siemens AG
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * This IIO device driver is designed to work with the following
+ * analog to digital converters from Texas Instruments:
+ * ADC108S102
+ * ADC128S102
+ * The communication with ADC chip is via the SPI bus (mode 3).
+ */
+
+#include <linux/acpi.h>
+#include <linux/iio/iio.h>
+#include <linux/iio/buffer.h>
+#include <linux/iio/types.h>
+#include <linux/iio/triggered_buffer.h>
+#include <linux/iio/trigger_consumer.h>
+#include <linux/interrupt.h>
+#include <linux/module.h>
+#include <linux/property.h>
+#include <linux/regulator/consumer.h>
+#include <linux/spi/spi.h>
+
+/*
+ * In case of ACPI, we use the hard-wired 5000 mV of the Galileo and IOT2000
+ * boards as default for the reference pin VA. Device tree users encode that
+ * via the vref-supply regulator.
+ */
+#define ADC108S102_VA_MV_ACPI_DEFAULT 5000
+
+/*
+ * Defining the ADC resolution being 12 bits, we can use the same driver for
+ * both ADC108S102 (10 bits resolution) and ADC128S102 (12 bits resolution)
+ * chips. The ADC108S102 effectively returns a 12-bit result with the 2
+ * least-significant bits unset.
+ */
+#define ADC108S102_BITS 12
+#define ADC108S102_MAX_CHANNELS 8
+
+/*
+ * 16-bit SPI command format:
+ * [15:14] Ignored
+ * [13:11] 3-bit channel address
+ * [10:0] Ignored
+ */
+#define ADC108S102_CMD(ch) ((u16)(ch) << 11)
+
+/*
+ * 16-bit SPI response format:
+ * [15:12] Zeros
+ * [11:0] 12-bit ADC sample (for ADC108S102, [1:0] will always be 0).
+ */
+#define ADC108S102_RES_DATA(res) ((u16)res & GENMASK(11, 0))
+
+struct adc108s102_state {
+ struct spi_device *spi;
+ struct regulator *reg;
+ u32 va_millivolt;
+ /* SPI transfer used by triggered buffer handler*/
+ struct spi_transfer ring_xfer;
+ /* SPI transfer used by direct scan */
+ struct spi_transfer scan_single_xfer;
+ /* SPI message used by ring_xfer SPI transfer */
+ struct spi_message ring_msg;
+ /* SPI message used by scan_single_xfer SPI transfer */
+ struct spi_message scan_single_msg;
+
+ /*
+ * SPI message buffers:
+ * tx_buf: |C0|C1|C2|C3|C4|C5|C6|C7|XX|
+ * rx_buf: |XX|R0|R1|R2|R3|R4|R5|R6|R7|tt|tt|tt|tt|
+ *
+ * tx_buf: 8 channel read commands, plus 1 dummy command
+ * rx_buf: 1 dummy response, 8 channel responses, plus 64-bit timestamp
+ */
+ __be16 rx_buf[13] ____cacheline_aligned;
+ __be16 tx_buf[9] ____cacheline_aligned;
+};
+
+#define ADC108S102_V_CHAN(index) \
+ { \
+ .type = IIO_VOLTAGE, \
+ .indexed = 1, \
+ .channel = index, \
+ .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | \
+ BIT(IIO_CHAN_INFO_SCALE), \
+ .address = index, \
+ .scan_index = index, \
+ .scan_type = { \
+ .sign = 'u', \
+ .realbits = ADC108S102_BITS, \
+ .storagebits = 16, \
+ .endianness = IIO_BE, \
+ }, \
+ }
+
+static const struct iio_chan_spec adc108s102_channels[] = {
+ ADC108S102_V_CHAN(0),
+ ADC108S102_V_CHAN(1),
+ ADC108S102_V_CHAN(2),
+ ADC108S102_V_CHAN(3),
+ ADC108S102_V_CHAN(4),
+ ADC108S102_V_CHAN(5),
+ ADC108S102_V_CHAN(6),
+ ADC108S102_V_CHAN(7),
+ IIO_CHAN_SOFT_TIMESTAMP(8),
+};
+
+static int adc108s102_update_scan_mode(struct iio_dev *indio_dev,
+ unsigned long const *active_scan_mask)
+{
+ struct adc108s102_state *st = iio_priv(indio_dev);
+ unsigned int bit, cmds;
+
+ /*
+ * Fill in the first x shorts of tx_buf with the number of channels
+ * enabled for sampling by the triggered buffer.
+ */
+ cmds = 0;
+ for_each_set_bit(bit, active_scan_mask, ADC108S102_MAX_CHANNELS)
+ st->tx_buf[cmds++] = cpu_to_be16(ADC108S102_CMD(bit));
+
+ /* One dummy command added, to clock in the last response */
+ st->tx_buf[cmds++] = 0x00;
+
+ /* build SPI ring message */
+ st->ring_xfer.tx_buf = &st->tx_buf[0];
+ st->ring_xfer.rx_buf = &st->rx_buf[0];
+ st->ring_xfer.len = cmds * sizeof(st->tx_buf[0]);
+
+ spi_message_init_with_transfers(&st->ring_msg, &st->ring_xfer, 1);
+
+ return 0;
+}
+
+static irqreturn_t adc108s102_trigger_handler(int irq, void *p)
+{
+ struct iio_poll_func *pf = p;
+ struct iio_dev *indio_dev = pf->indio_dev;
+ struct adc108s102_state *st = iio_priv(indio_dev);
+ int ret;
+
+ ret = spi_sync(st->spi, &st->ring_msg);
+ if (ret < 0)
+ goto out_notify;
+
+ /* Skip the dummy response in the first slot */
+ iio_push_to_buffers_with_timestamp(indio_dev,
+ (u8 *)&st->rx_buf[1],
+ iio_get_time_ns(indio_dev));
+
+out_notify:
+ iio_trigger_notify_done(indio_dev->trig);
+
+ return IRQ_HANDLED;
+}
+
+static int adc108s102_scan_direct(struct adc108s102_state *st, unsigned int ch)
+{
+ int ret;
+
+ st->tx_buf[0] = cpu_to_be16(ADC108S102_CMD(ch));
+ ret = spi_sync(st->spi, &st->scan_single_msg);
+ if (ret)
+ return ret;
+
+ /* Skip the dummy response in the first slot */
+ return be16_to_cpu(st->rx_buf[1]);
+}
+
+static int adc108s102_read_raw(struct iio_dev *indio_dev,
+ struct iio_chan_spec const *chan,
+ int *val, int *val2, long m)
+{
+ struct adc108s102_state *st = iio_priv(indio_dev);
+ int ret;
+
+ switch (m) {
+ case IIO_CHAN_INFO_RAW:
+ ret = iio_device_claim_direct_mode(indio_dev);
+ if (ret)
+ return ret;
+
+ ret = adc108s102_scan_direct(st, chan->address);
+
+ iio_device_release_direct_mode(indio_dev);
+
+ if (ret < 0)
+ return ret;
+
+ *val = ADC108S102_RES_DATA(ret);
+
+ return IIO_VAL_INT;
+ case IIO_CHAN_INFO_SCALE:
+ if (chan->type != IIO_VOLTAGE)
+ break;
+
+ *val = st->va_millivolt;
+ *val2 = chan->scan_type.realbits;
+
+ return IIO_VAL_FRACTIONAL_LOG2;
+ default:
+ break;
+ }
+
+ return -EINVAL;
+}
+
+static const struct iio_info adc108s102_info = {
+ .read_raw = &adc108s102_read_raw,
+ .update_scan_mode = &adc108s102_update_scan_mode,
+ .driver_module = THIS_MODULE,
+};
+
+static int adc108s102_probe(struct spi_device *spi)
+{
+ struct adc108s102_state *st;
+ struct iio_dev *indio_dev;
+ int ret;
+
+ indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*st));
+ if (!indio_dev)
+ return -ENOMEM;
+
+ st = iio_priv(indio_dev);
+
+ if (ACPI_COMPANION(&spi->dev)) {
+ st->va_millivolt = ADC108S102_VA_MV_ACPI_DEFAULT;
+ } else {
+ st->reg = devm_regulator_get(&spi->dev, "vref");
+ if (IS_ERR(st->reg))
+ return PTR_ERR(st->reg);
+
+ ret = regulator_enable(st->reg);
+ if (ret < 0) {
+ dev_err(&spi->dev, "Cannot enable vref regulator\n");
+ return ret;
+ }
+
+ ret = regulator_get_voltage(st->reg);
+ if (ret < 0) {
+ dev_err(&spi->dev, "vref get voltage failed\n");
+ return ret;
+ }
+
+ st->va_millivolt = ret / 1000;
+ }
+
+ spi_set_drvdata(spi, indio_dev);
+ st->spi = spi;
+
+ indio_dev->name = spi->modalias;
+ indio_dev->dev.parent = &spi->dev;
+ indio_dev->modes = INDIO_DIRECT_MODE;
+ indio_dev->channels = adc108s102_channels;
+ indio_dev->num_channels = ARRAY_SIZE(adc108s102_channels);
+ indio_dev->info = &adc108s102_info;
+
+ /* Setup default message */
+ st->scan_single_xfer.tx_buf = st->tx_buf;
+ st->scan_single_xfer.rx_buf = st->rx_buf;
+ st->scan_single_xfer.len = 2 * sizeof(st->tx_buf[0]);
+
+ spi_message_init_with_transfers(&st->scan_single_msg,
+ &st->scan_single_xfer, 1);
+
+ ret = iio_triggered_buffer_setup(indio_dev, NULL,
+ &adc108s102_trigger_handler, NULL);
+ if (ret)
+ goto error_disable_reg;
+
+ ret = iio_device_register(indio_dev);
+ if (ret) {
+ dev_err(&spi->dev, "Failed to register IIO device\n");
+ goto error_cleanup_triggered_buffer;
+ }
+ return 0;
+
+error_cleanup_triggered_buffer:
+ iio_triggered_buffer_cleanup(indio_dev);
+
+error_disable_reg:
+ regulator_disable(st->reg);
+
+ return ret;
+}
+
+static int adc108s102_remove(struct spi_device *spi)
+{
+ struct iio_dev *indio_dev = spi_get_drvdata(spi);
+ struct adc108s102_state *st = iio_priv(indio_dev);
+
+ iio_device_unregister(indio_dev);
+ iio_triggered_buffer_cleanup(indio_dev);
+
+ regulator_disable(st->reg);
+
+ return 0;
+}
+
+#ifdef CONFIG_OF
+static const struct of_device_id adc108s102_of_match[] = {
+ { .compatible = "ti,adc108s102" },
+ { }
+};
+MODULE_DEVICE_TABLE(of, adc108s102_of_match);
+#endif
+
+#ifdef CONFIG_ACPI
+static const struct acpi_device_id adc108s102_acpi_ids[] = {
+ { "INT3495", 0 },
+ { }
+};
+MODULE_DEVICE_TABLE(acpi, adc108s102_acpi_ids);
+#endif
+
+static const struct spi_device_id adc108s102_id[] = {
+ { "adc108s102", 0 },
+ { }
+};
+MODULE_DEVICE_TABLE(spi, adc108s102_id);
+
+static struct spi_driver adc108s102_driver = {
+ .driver = {
+ .name = "adc108s102",
+ .of_match_table = of_match_ptr(adc108s102_of_match),
+ .acpi_match_table = ACPI_PTR(adc108s102_acpi_ids),
+ },
+ .probe = adc108s102_probe,
+ .remove = adc108s102_remove,
+ .id_table = adc108s102_id,
+};
+module_spi_driver(adc108s102_driver);
+
+MODULE_AUTHOR("Bogdan Pricop <bogdan.pricop@emutex.com>");
+MODULE_DESCRIPTION("Texas Instruments ADC108S102 and ADC128S102 driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/iio/adc/ti_am335x_adc.c b/drivers/iio/adc/ti_am335x_adc.c
index 4282ceca3d8f..6cbed7eb118a 100644
--- a/drivers/iio/adc/ti_am335x_adc.c
+++ b/drivers/iio/adc/ti_am335x_adc.c
@@ -614,7 +614,7 @@ static int tiadc_probe(struct platform_device *pdev)
return -EINVAL;
}
- indio_dev = devm_iio_device_alloc(&pdev->dev, sizeof(*indio_dev));
+ indio_dev = devm_iio_device_alloc(&pdev->dev, sizeof(*adc_dev));
if (indio_dev == NULL) {
dev_err(&pdev->dev, "failed to allocate iio device\n");
return -ENOMEM;
diff --git a/drivers/iio/adc/twl4030-madc.c b/drivers/iio/adc/twl4030-madc.c
index 0c74869a540a..bd3d37fc2144 100644
--- a/drivers/iio/adc/twl4030-madc.c
+++ b/drivers/iio/adc/twl4030-madc.c
@@ -36,7 +36,6 @@
#include <linux/platform_device.h>
#include <linux/slab.h>
#include <linux/i2c/twl.h>
-#include <linux/i2c/twl4030-madc.h>
#include <linux/module.h>
#include <linux/stddef.h>
#include <linux/mutex.h>
@@ -49,9 +48,121 @@
#include <linux/iio/iio.h>
+#define TWL4030_MADC_MAX_CHANNELS 16
+
+#define TWL4030_MADC_CTRL1 0x00
+#define TWL4030_MADC_CTRL2 0x01
+
+#define TWL4030_MADC_RTSELECT_LSB 0x02
+#define TWL4030_MADC_SW1SELECT_LSB 0x06
+#define TWL4030_MADC_SW2SELECT_LSB 0x0A
+
+#define TWL4030_MADC_RTAVERAGE_LSB 0x04
+#define TWL4030_MADC_SW1AVERAGE_LSB 0x08
+#define TWL4030_MADC_SW2AVERAGE_LSB 0x0C
+
+#define TWL4030_MADC_CTRL_SW1 0x12
+#define TWL4030_MADC_CTRL_SW2 0x13
+
+#define TWL4030_MADC_RTCH0_LSB 0x17
+#define TWL4030_MADC_GPCH0_LSB 0x37
+
+#define TWL4030_MADC_MADCON (1 << 0) /* MADC power on */
+#define TWL4030_MADC_BUSY (1 << 0) /* MADC busy */
+/* MADC conversion completion */
+#define TWL4030_MADC_EOC_SW (1 << 1)
+/* MADC SWx start conversion */
+#define TWL4030_MADC_SW_START (1 << 5)
+#define TWL4030_MADC_ADCIN0 (1 << 0)
+#define TWL4030_MADC_ADCIN1 (1 << 1)
+#define TWL4030_MADC_ADCIN2 (1 << 2)
+#define TWL4030_MADC_ADCIN3 (1 << 3)
+#define TWL4030_MADC_ADCIN4 (1 << 4)
+#define TWL4030_MADC_ADCIN5 (1 << 5)
+#define TWL4030_MADC_ADCIN6 (1 << 6)
+#define TWL4030_MADC_ADCIN7 (1 << 7)
+#define TWL4030_MADC_ADCIN8 (1 << 8)
+#define TWL4030_MADC_ADCIN9 (1 << 9)
+#define TWL4030_MADC_ADCIN10 (1 << 10)
+#define TWL4030_MADC_ADCIN11 (1 << 11)
+#define TWL4030_MADC_ADCIN12 (1 << 12)
+#define TWL4030_MADC_ADCIN13 (1 << 13)
+#define TWL4030_MADC_ADCIN14 (1 << 14)
+#define TWL4030_MADC_ADCIN15 (1 << 15)
+
+/* Fixed channels */
+#define TWL4030_MADC_BTEMP TWL4030_MADC_ADCIN1
+#define TWL4030_MADC_VBUS TWL4030_MADC_ADCIN8
+#define TWL4030_MADC_VBKB TWL4030_MADC_ADCIN9
+#define TWL4030_MADC_ICHG TWL4030_MADC_ADCIN10
+#define TWL4030_MADC_VCHG TWL4030_MADC_ADCIN11
+#define TWL4030_MADC_VBAT TWL4030_MADC_ADCIN12
+
+/* Step size and prescaler ratio */
+#define TEMP_STEP_SIZE 147
+#define TEMP_PSR_R 100
+#define CURR_STEP_SIZE 147
+#define CURR_PSR_R1 44
+#define CURR_PSR_R2 88
+
+#define TWL4030_BCI_BCICTL1 0x23
+#define TWL4030_BCI_CGAIN 0x020
+#define TWL4030_BCI_MESBAT (1 << 1)
+#define TWL4030_BCI_TYPEN (1 << 4)
+#define TWL4030_BCI_ITHEN (1 << 3)
+
+#define REG_BCICTL2 0x024
+#define TWL4030_BCI_ITHSENS 0x007
+
+/* Register and bits for GPBR1 register */
+#define TWL4030_REG_GPBR1 0x0c
+#define TWL4030_GPBR1_MADC_HFCLK_EN (1 << 7)
+
#define TWL4030_USB_SEL_MADC_MCPC (1<<3)
#define TWL4030_USB_CARKIT_ANA_CTRL 0xBB
+struct twl4030_madc_conversion_method {
+ u8 sel;
+ u8 avg;
+ u8 rbase;
+ u8 ctrl;
+};
+
+/**
+ * struct twl4030_madc_request - madc request packet for channel conversion
+ * @channels: 16 bit bitmap for individual channels
+ * @do_avg: sample the input channel for 4 consecutive cycles
+ * @method: RT, SW1, SW2
+ * @type: Polling or interrupt based method
+ * @active: Flag if request is active
+ * @result_pending: Flag from irq handler, that result is ready
+ * @raw: Return raw value, do not convert it
+ * @rbuf: Result buffer
+ */
+struct twl4030_madc_request {
+ unsigned long channels;
+ bool do_avg;
+ u16 method;
+ u16 type;
+ bool active;
+ bool result_pending;
+ bool raw;
+ int rbuf[TWL4030_MADC_MAX_CHANNELS];
+};
+
+enum conversion_methods {
+ TWL4030_MADC_RT,
+ TWL4030_MADC_SW1,
+ TWL4030_MADC_SW2,
+ TWL4030_MADC_NUM_METHODS
+};
+
+enum sample_type {
+ TWL4030_MADC_WAIT,
+ TWL4030_MADC_IRQ_ONESHOT,
+ TWL4030_MADC_IRQ_REARM
+};
+
/**
* struct twl4030_madc_data - a container for madc info
* @dev: Pointer to device structure for madc
@@ -72,6 +183,8 @@ struct twl4030_madc_data {
u8 isr;
};
+static int twl4030_madc_conversion(struct twl4030_madc_request *req);
+
static int twl4030_madc_read(struct iio_dev *iio_dev,
const struct iio_chan_spec *chan,
int *val, int *val2, long mask)
@@ -84,7 +197,6 @@ static int twl4030_madc_read(struct iio_dev *iio_dev,
req.channels = BIT(chan->channel);
req.active = false;
- req.func_cb = NULL;
req.type = TWL4030_MADC_WAIT;
req.raw = !(mask == IIO_CHAN_INFO_PROCESSED);
req.do_avg = (mask == IIO_CHAN_INFO_AVERAGE_RAW);
@@ -341,37 +453,6 @@ static int twl4030_madc_read_channels(struct twl4030_madc_data *madc,
}
/*
- * Enables irq.
- * @madc - pointer to twl4030_madc_data struct
- * @id - irq number to be enabled
- * can take one of TWL4030_MADC_RT, TWL4030_MADC_SW1, TWL4030_MADC_SW2
- * corresponding to RT, SW1, SW2 conversion requests.
- * If the i2c read fails it returns an error else returns 0.
- */
-static int twl4030_madc_enable_irq(struct twl4030_madc_data *madc, u8 id)
-{
- u8 val;
- int ret;
-
- ret = twl_i2c_read_u8(TWL4030_MODULE_MADC, &val, madc->imr);
- if (ret) {
- dev_err(madc->dev, "unable to read imr register 0x%X\n",
- madc->imr);
- return ret;
- }
-
- val &= ~(1 << id);
- ret = twl_i2c_write_u8(TWL4030_MODULE_MADC, val, madc->imr);
- if (ret) {
- dev_err(madc->dev,
- "unable to write imr register 0x%X\n", madc->imr);
- return ret;
- }
-
- return 0;
-}
-
-/*
* Disables irq.
* @madc - pointer to twl4030_madc_data struct
* @id - irq number to be disabled
@@ -440,11 +521,6 @@ static irqreturn_t twl4030_madc_threaded_irq_handler(int irq, void *_madc)
/* Read results */
len = twl4030_madc_read_channels(madc, method->rbase,
r->channels, r->rbuf, r->raw);
- /* Return results to caller */
- if (r->func_cb != NULL) {
- r->func_cb(len, r->channels, r->rbuf);
- r->func_cb = NULL;
- }
/* Free request */
r->result_pending = 0;
r->active = 0;
@@ -466,11 +542,6 @@ err_i2c:
/* Read results */
len = twl4030_madc_read_channels(madc, method->rbase,
r->channels, r->rbuf, r->raw);
- /* Return results to caller */
- if (r->func_cb != NULL) {
- r->func_cb(len, r->channels, r->rbuf);
- r->func_cb = NULL;
- }
/* Free request */
r->result_pending = 0;
r->active = 0;
@@ -480,23 +551,6 @@ err_i2c:
return IRQ_HANDLED;
}
-static int twl4030_madc_set_irq(struct twl4030_madc_data *madc,
- struct twl4030_madc_request *req)
-{
- struct twl4030_madc_request *p;
- int ret;
-
- p = &madc->requests[req->method];
- memcpy(p, req, sizeof(*req));
- ret = twl4030_madc_enable_irq(madc, req->method);
- if (ret < 0) {
- dev_err(madc->dev, "enable irq failed!!\n");
- return ret;
- }
-
- return 0;
-}
-
/*
* Function which enables the madc conversion
* by writing to the control register.
@@ -568,7 +622,7 @@ static int twl4030_madc_wait_conversion_ready(struct twl4030_madc_data *madc,
* be a negative error value in the corresponding array element.
* returns 0 if succeeds else error value
*/
-int twl4030_madc_conversion(struct twl4030_madc_request *req)
+static int twl4030_madc_conversion(struct twl4030_madc_request *req)
{
const struct twl4030_madc_conversion_method *method;
int ret;
@@ -605,17 +659,6 @@ int twl4030_madc_conversion(struct twl4030_madc_request *req)
goto out;
}
}
- if (req->type == TWL4030_MADC_IRQ_ONESHOT && req->func_cb != NULL) {
- ret = twl4030_madc_set_irq(twl4030_madc, req);
- if (ret < 0)
- goto out;
- ret = twl4030_madc_start_conversion(twl4030_madc, req->method);
- if (ret < 0)
- goto out;
- twl4030_madc->requests[req->method].active = 1;
- ret = 0;
- goto out;
- }
/* With RT method we should not be here anymore */
if (req->method == TWL4030_MADC_RT) {
ret = -EINVAL;
@@ -640,28 +683,6 @@ out:
return ret;
}
-EXPORT_SYMBOL_GPL(twl4030_madc_conversion);
-
-int twl4030_get_madc_conversion(int channel_no)
-{
- struct twl4030_madc_request req;
- int temp = 0;
- int ret;
-
- req.channels = (1 << channel_no);
- req.method = TWL4030_MADC_SW2;
- req.active = 0;
- req.raw = 0;
- req.func_cb = NULL;
- ret = twl4030_madc_conversion(&req);
- if (ret < 0)
- return ret;
- if (req.rbuf[channel_no] > 0)
- temp = req.rbuf[channel_no];
-
- return temp;
-}
-EXPORT_SYMBOL_GPL(twl4030_get_madc_conversion);
/**
* twl4030_madc_set_current_generator() - setup bias current
diff --git a/drivers/iio/adc/xilinx-xadc-core.c b/drivers/iio/adc/xilinx-xadc-core.c
index 56cf5907a5f0..4a60497a1f19 100644
--- a/drivers/iio/adc/xilinx-xadc-core.c
+++ b/drivers/iio/adc/xilinx-xadc-core.c
@@ -1204,7 +1204,10 @@ static int xadc_probe(struct platform_device *pdev)
ret = PTR_ERR(xadc->clk);
goto err_free_samplerate_trigger;
}
- clk_prepare_enable(xadc->clk);
+
+ ret = clk_prepare_enable(xadc->clk);
+ if (ret)
+ goto err_free_samplerate_trigger;
ret = xadc->ops->setup(pdev, indio_dev, irq);
if (ret)
diff --git a/drivers/iio/buffer/industrialio-buffer-dma.c b/drivers/iio/buffer/industrialio-buffer-dma.c
index dd99d273bae9..ff03324dee13 100644
--- a/drivers/iio/buffer/industrialio-buffer-dma.c
+++ b/drivers/iio/buffer/industrialio-buffer-dma.c
@@ -14,6 +14,7 @@
#include <linux/sched.h>
#include <linux/poll.h>
#include <linux/iio/buffer.h>
+#include <linux/iio/buffer_impl.h>
#include <linux/iio/buffer-dma.h>
#include <linux/dma-mapping.h>
#include <linux/sizes.h>
diff --git a/drivers/iio/buffer/industrialio-buffer-dmaengine.c b/drivers/iio/buffer/industrialio-buffer-dmaengine.c
index 9fabed47053d..2b5a320f42c5 100644
--- a/drivers/iio/buffer/industrialio-buffer-dmaengine.c
+++ b/drivers/iio/buffer/industrialio-buffer-dmaengine.c
@@ -14,6 +14,7 @@
#include <linux/iio/iio.h>
#include <linux/iio/buffer.h>
+#include <linux/iio/buffer_impl.h>
#include <linux/iio/buffer-dma.h>
#include <linux/iio/buffer-dmaengine.h>
diff --git a/drivers/iio/common/hid-sensors/Kconfig b/drivers/iio/common/hid-sensors/Kconfig
index 39188b72cd3b..80105378b0ba 100644
--- a/drivers/iio/common/hid-sensors/Kconfig
+++ b/drivers/iio/common/hid-sensors/Kconfig
@@ -16,7 +16,7 @@ config HID_SENSOR_IIO_COMMON
config HID_SENSOR_IIO_TRIGGER
tristate "Common module (trigger) for all HID Sensor IIO drivers"
- depends on HID_SENSOR_HUB && HID_SENSOR_IIO_COMMON
+ depends on HID_SENSOR_HUB && HID_SENSOR_IIO_COMMON && IIO_BUFFER
select IIO_TRIGGER
help
Say yes here to build trigger support for HID sensors.
diff --git a/drivers/iio/common/hid-sensors/hid-sensor-attributes.c b/drivers/iio/common/hid-sensors/hid-sensor-attributes.c
index 1c0874cdf665..f5d4d786e193 100644
--- a/drivers/iio/common/hid-sensors/hid-sensor-attributes.c
+++ b/drivers/iio/common/hid-sensors/hid-sensor-attributes.c
@@ -69,6 +69,12 @@ static struct {
{HID_USAGE_SENSOR_TIME_TIMESTAMP, HID_USAGE_SENSOR_UNITS_MILLISECOND,
1000000, 0},
+ {HID_USAGE_SENSOR_DEVICE_ORIENTATION, 0, 1, 0},
+
+ {HID_USAGE_SENSOR_RELATIVE_ORIENTATION, 0, 1, 0},
+
+ {HID_USAGE_SENSOR_GEOMAGNETIC_ORIENTATION, 0, 1, 0},
+
{HID_USAGE_SENSOR_TEMPERATURE, 0, 1000, 0},
{HID_USAGE_SENSOR_TEMPERATURE, HID_USAGE_SENSOR_UNITS_DEGREES, 1000, 0},
@@ -230,7 +236,7 @@ int hid_sensor_write_samp_freq_value(struct hid_sensor_common *st,
ret = sensor_hub_set_feature(st->hsdev, st->poll.report_id,
st->poll.index, sizeof(value), &value);
if (ret < 0 || value < 0)
- ret = -EINVAL;
+ return -EINVAL;
ret = sensor_hub_get_feature(st->hsdev,
st->poll.report_id,
@@ -283,7 +289,7 @@ int hid_sensor_write_raw_hyst_value(struct hid_sensor_common *st,
st->sensitivity.index, sizeof(value),
&value);
if (ret < 0 || value < 0)
- ret = -EINVAL;
+ return -EINVAL;
ret = sensor_hub_get_feature(st->hsdev,
st->sensitivity.report_id,
@@ -404,6 +410,48 @@ int hid_sensor_get_reporting_interval(struct hid_sensor_hub_device *hsdev,
}
+static void hid_sensor_get_report_latency_info(struct hid_sensor_hub_device *hsdev,
+ u32 usage_id,
+ struct hid_sensor_common *st)
+{
+ sensor_hub_input_get_attribute_info(hsdev, HID_FEATURE_REPORT,
+ usage_id,
+ HID_USAGE_SENSOR_PROP_REPORT_LATENCY,
+ &st->report_latency);
+
+ hid_dbg(hsdev->hdev, "Report latency attributes: %x:%x\n",
+ st->report_latency.index, st->report_latency.report_id);
+}
+
+int hid_sensor_get_report_latency(struct hid_sensor_common *st)
+{
+ int ret;
+ int value;
+
+ ret = sensor_hub_get_feature(st->hsdev, st->report_latency.report_id,
+ st->report_latency.index, sizeof(value),
+ &value);
+ if (ret < 0)
+ return ret;
+
+ return value;
+}
+EXPORT_SYMBOL(hid_sensor_get_report_latency);
+
+int hid_sensor_set_report_latency(struct hid_sensor_common *st, int latency_ms)
+{
+ return sensor_hub_set_feature(st->hsdev, st->report_latency.report_id,
+ st->report_latency.index,
+ sizeof(latency_ms), &latency_ms);
+}
+EXPORT_SYMBOL(hid_sensor_set_report_latency);
+
+bool hid_sensor_batch_mode_supported(struct hid_sensor_common *st)
+{
+ return st->report_latency.index > 0 && st->report_latency.report_id > 0;
+}
+EXPORT_SYMBOL(hid_sensor_batch_mode_supported);
+
int hid_sensor_parse_common_attributes(struct hid_sensor_hub_device *hsdev,
u32 usage_id,
struct hid_sensor_common *st)
@@ -445,6 +493,8 @@ int hid_sensor_parse_common_attributes(struct hid_sensor_hub_device *hsdev,
} else
st->timestamp_ns_scale = 1000000000;
+ hid_sensor_get_report_latency_info(hsdev, usage_id, st);
+
hid_dbg(hsdev->hdev, "common attributes: %x:%x, %x:%x, %x:%x %x:%x %x:%x\n",
st->poll.index, st->poll.report_id,
st->report_state.index, st->report_state.report_id,
diff --git a/drivers/iio/common/hid-sensors/hid-sensor-trigger.c b/drivers/iio/common/hid-sensors/hid-sensor-trigger.c
index 0b5dea050239..16ade0a0327b 100644
--- a/drivers/iio/common/hid-sensors/hid-sensor-trigger.c
+++ b/drivers/iio/common/hid-sensors/hid-sensor-trigger.c
@@ -26,9 +26,84 @@
#include <linux/hid-sensor-hub.h>
#include <linux/iio/iio.h>
#include <linux/iio/trigger.h>
+#include <linux/iio/buffer.h>
#include <linux/iio/sysfs.h>
#include "hid-sensor-trigger.h"
+static ssize_t _hid_sensor_set_report_latency(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t len)
+{
+ struct iio_dev *indio_dev = dev_to_iio_dev(dev);
+ struct hid_sensor_common *attrb = iio_device_get_drvdata(indio_dev);
+ int integer, fract, ret;
+ int latency;
+
+ ret = iio_str_to_fixpoint(buf, 100000, &integer, &fract);
+ if (ret)
+ return ret;
+
+ latency = integer * 1000 + fract / 1000;
+ ret = hid_sensor_set_report_latency(attrb, latency);
+ if (ret < 0)
+ return len;
+
+ attrb->latency_ms = hid_sensor_get_report_latency(attrb);
+
+ return len;
+}
+
+static ssize_t _hid_sensor_get_report_latency(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ struct iio_dev *indio_dev = dev_to_iio_dev(dev);
+ struct hid_sensor_common *attrb = iio_device_get_drvdata(indio_dev);
+ int latency;
+
+ latency = hid_sensor_get_report_latency(attrb);
+ if (latency < 0)
+ return latency;
+
+ return sprintf(buf, "%d.%06u\n", latency / 1000, (latency % 1000) * 1000);
+}
+
+static ssize_t _hid_sensor_get_fifo_state(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ struct iio_dev *indio_dev = dev_to_iio_dev(dev);
+ struct hid_sensor_common *attrb = iio_device_get_drvdata(indio_dev);
+ int latency;
+
+ latency = hid_sensor_get_report_latency(attrb);
+ if (latency < 0)
+ return latency;
+
+ return sprintf(buf, "%d\n", !!latency);
+}
+
+static IIO_DEVICE_ATTR(hwfifo_timeout, 0644,
+ _hid_sensor_get_report_latency,
+ _hid_sensor_set_report_latency, 0);
+static IIO_DEVICE_ATTR(hwfifo_enabled, 0444,
+ _hid_sensor_get_fifo_state, NULL, 0);
+
+static const struct attribute *hid_sensor_fifo_attributes[] = {
+ &iio_dev_attr_hwfifo_timeout.dev_attr.attr,
+ &iio_dev_attr_hwfifo_enabled.dev_attr.attr,
+ NULL,
+};
+
+static void hid_sensor_setup_batch_mode(struct iio_dev *indio_dev,
+ struct hid_sensor_common *st)
+{
+ if (!hid_sensor_batch_mode_supported(st))
+ return;
+
+ iio_buffer_set_attrs(indio_dev->buffer, hid_sensor_fifo_attributes);
+}
+
static int _hid_sensor_power_state(struct hid_sensor_common *st, bool state)
{
int state_val;
@@ -141,6 +216,9 @@ static void hid_sensor_set_power_work(struct work_struct *work)
sizeof(attrb->raw_hystersis),
&attrb->raw_hystersis);
+ if (attrb->latency_ms > 0)
+ hid_sensor_set_report_latency(attrb, attrb->latency_ms);
+
_hid_sensor_power_state(attrb, true);
}
@@ -192,6 +270,8 @@ int hid_sensor_setup_trigger(struct iio_dev *indio_dev, const char *name,
attrb->trigger = trig;
indio_dev->trig = iio_trigger_get(trig);
+ hid_sensor_setup_batch_mode(indio_dev, attrb);
+
ret = pm_runtime_set_active(&indio_dev->dev);
if (ret)
goto error_unreg_trigger;
diff --git a/drivers/iio/dac/Kconfig b/drivers/iio/dac/Kconfig
index df5abc46cd3f..25bed2d7d2b9 100644
--- a/drivers/iio/dac/Kconfig
+++ b/drivers/iio/dac/Kconfig
@@ -13,7 +13,8 @@ config AD5064
AD5045, AD5064, AD5064-1, AD5065, AD5625, AD5625R, AD5627, AD5627R,
AD5628, AD5629R, AD5645R, AD5647R, AD5648, AD5665, AD5665R, AD5666,
AD5667, AD5667R, AD5668, AD5669R, LTC2606, LTC2607, LTC2609, LTC2616,
- LTC2617, LTC2619, LTC2626, LTC2627, LTC2629 Digital to Analog Converter.
+ LTC2617, LTC2619, LTC2626, LTC2627, LTC2629, LTC2631, LTC2633, LTC2635
+ Digital to Analog Converter.
To compile this driver as a module, choose M here: the
module will be called ad5064.
diff --git a/drivers/iio/dac/ad5064.c b/drivers/iio/dac/ad5064.c
index 6803e4a137cd..3f9399c27869 100644
--- a/drivers/iio/dac/ad5064.c
+++ b/drivers/iio/dac/ad5064.c
@@ -2,8 +2,8 @@
* AD5024, AD5025, AD5044, AD5045, AD5064, AD5064-1, AD5065, AD5625, AD5625R,
* AD5627, AD5627R, AD5628, AD5629R, AD5645R, AD5647R, AD5648, AD5665, AD5665R,
* AD5666, AD5667, AD5667R, AD5668, AD5669R, LTC2606, LTC2607, LTC2609, LTC2616,
- * LTC2617, LTC2619, LTC2626, LTC2627, LTC2629 Digital to analog converters
- * driver
+ * LTC2617, LTC2619, LTC2626, LTC2627, LTC2629, LTC2631, LTC2633, LTC2635
+ * Digital to analog converters driver
*
* Copyright 2011 Analog Devices Inc.
*
@@ -168,6 +168,24 @@ enum ad5064_type {
ID_LTC2626,
ID_LTC2627,
ID_LTC2629,
+ ID_LTC2631_L12,
+ ID_LTC2631_H12,
+ ID_LTC2631_L10,
+ ID_LTC2631_H10,
+ ID_LTC2631_L8,
+ ID_LTC2631_H8,
+ ID_LTC2633_L12,
+ ID_LTC2633_H12,
+ ID_LTC2633_L10,
+ ID_LTC2633_H10,
+ ID_LTC2633_L8,
+ ID_LTC2633_H8,
+ ID_LTC2635_L12,
+ ID_LTC2635_H12,
+ ID_LTC2635_L10,
+ ID_LTC2635_H10,
+ ID_LTC2635_L8,
+ ID_LTC2635_H8,
};
static int ad5064_write(struct ad5064_state *st, unsigned int cmd,
@@ -425,6 +443,19 @@ static DECLARE_AD5064_CHANNELS(ad5669_channels, 16, 0, ad5064_ext_info);
static DECLARE_AD5064_CHANNELS(ltc2607_channels, 16, 0, ltc2617_ext_info);
static DECLARE_AD5064_CHANNELS(ltc2617_channels, 14, 2, ltc2617_ext_info);
static DECLARE_AD5064_CHANNELS(ltc2627_channels, 12, 4, ltc2617_ext_info);
+#define ltc2631_12_channels ltc2627_channels
+static DECLARE_AD5064_CHANNELS(ltc2631_10_channels, 10, 6, ltc2617_ext_info);
+static DECLARE_AD5064_CHANNELS(ltc2631_8_channels, 8, 8, ltc2617_ext_info);
+
+#define LTC2631_INFO(vref, pchannels, nchannels) \
+ { \
+ .shared_vref = true, \
+ .internal_vref = vref, \
+ .channels = pchannels, \
+ .num_channels = nchannels, \
+ .regmap_type = AD5064_REGMAP_LTC, \
+ }
+
static const struct ad5064_chip_info ad5064_chip_info_tbl[] = {
[ID_AD5024] = {
@@ -724,6 +755,24 @@ static const struct ad5064_chip_info ad5064_chip_info_tbl[] = {
.num_channels = 4,
.regmap_type = AD5064_REGMAP_LTC,
},
+ [ID_LTC2631_L12] = LTC2631_INFO(2500000, ltc2631_12_channels, 1),
+ [ID_LTC2631_H12] = LTC2631_INFO(4096000, ltc2631_12_channels, 1),
+ [ID_LTC2631_L10] = LTC2631_INFO(2500000, ltc2631_10_channels, 1),
+ [ID_LTC2631_H10] = LTC2631_INFO(4096000, ltc2631_10_channels, 1),
+ [ID_LTC2631_L8] = LTC2631_INFO(2500000, ltc2631_8_channels, 1),
+ [ID_LTC2631_H8] = LTC2631_INFO(4096000, ltc2631_8_channels, 1),
+ [ID_LTC2633_L12] = LTC2631_INFO(2500000, ltc2631_12_channels, 2),
+ [ID_LTC2633_H12] = LTC2631_INFO(4096000, ltc2631_12_channels, 2),
+ [ID_LTC2633_L10] = LTC2631_INFO(2500000, ltc2631_10_channels, 2),
+ [ID_LTC2633_H10] = LTC2631_INFO(4096000, ltc2631_10_channels, 2),
+ [ID_LTC2633_L8] = LTC2631_INFO(2500000, ltc2631_8_channels, 2),
+ [ID_LTC2633_H8] = LTC2631_INFO(4096000, ltc2631_8_channels, 2),
+ [ID_LTC2635_L12] = LTC2631_INFO(2500000, ltc2631_12_channels, 4),
+ [ID_LTC2635_H12] = LTC2631_INFO(4096000, ltc2631_12_channels, 4),
+ [ID_LTC2635_L10] = LTC2631_INFO(2500000, ltc2631_10_channels, 4),
+ [ID_LTC2635_H10] = LTC2631_INFO(4096000, ltc2631_10_channels, 4),
+ [ID_LTC2635_L8] = LTC2631_INFO(2500000, ltc2631_8_channels, 4),
+ [ID_LTC2635_H8] = LTC2631_INFO(4096000, ltc2631_8_channels, 4),
};
static inline unsigned int ad5064_num_vref(struct ad5064_state *st)
@@ -982,6 +1031,24 @@ static const struct i2c_device_id ad5064_i2c_ids[] = {
{"ltc2626", ID_LTC2626},
{"ltc2627", ID_LTC2627},
{"ltc2629", ID_LTC2629},
+ {"ltc2631-l12", ID_LTC2631_L12},
+ {"ltc2631-h12", ID_LTC2631_H12},
+ {"ltc2631-l10", ID_LTC2631_L10},
+ {"ltc2631-h10", ID_LTC2631_H10},
+ {"ltc2631-l8", ID_LTC2631_L8},
+ {"ltc2631-h8", ID_LTC2631_H8},
+ {"ltc2633-l12", ID_LTC2633_L12},
+ {"ltc2633-h12", ID_LTC2633_H12},
+ {"ltc2633-l10", ID_LTC2633_L10},
+ {"ltc2633-h10", ID_LTC2633_H10},
+ {"ltc2633-l8", ID_LTC2633_L8},
+ {"ltc2633-h8", ID_LTC2633_H8},
+ {"ltc2635-l12", ID_LTC2635_L12},
+ {"ltc2635-h12", ID_LTC2635_H12},
+ {"ltc2635-l10", ID_LTC2635_L10},
+ {"ltc2635-h10", ID_LTC2635_H10},
+ {"ltc2635-l8", ID_LTC2635_L8},
+ {"ltc2635-h8", ID_LTC2635_H8},
{}
};
MODULE_DEVICE_TABLE(i2c, ad5064_i2c_ids);
diff --git a/drivers/iio/humidity/hts221.h b/drivers/iio/humidity/hts221.h
index c7154665512e..94510266e0a5 100644
--- a/drivers/iio/humidity/hts221.h
+++ b/drivers/iio/humidity/hts221.h
@@ -57,12 +57,15 @@ struct hts221_hw {
struct hts221_sensor sensors[HTS221_SENSOR_MAX];
+ bool enabled;
u8 odr;
const struct hts221_transfer_function *tf;
struct hts221_transfer_buffer tb;
};
+extern const struct dev_pm_ops hts221_pm_ops;
+
int hts221_config_drdy(struct hts221_hw *hw, bool enable);
int hts221_probe(struct iio_dev *iio_dev);
int hts221_power_on(struct hts221_hw *hw);
diff --git a/drivers/iio/humidity/hts221_core.c b/drivers/iio/humidity/hts221_core.c
index 3f3ef4a1a474..a56da3999e00 100644
--- a/drivers/iio/humidity/hts221_core.c
+++ b/drivers/iio/humidity/hts221_core.c
@@ -13,6 +13,7 @@
#include <linux/device.h>
#include <linux/iio/sysfs.h>
#include <linux/delay.h>
+#include <linux/pm.h>
#include <asm/unaligned.h>
#include "hts221.h"
@@ -307,15 +308,30 @@ hts221_sysfs_temp_oversampling_avail(struct device *dev,
int hts221_power_on(struct hts221_hw *hw)
{
- return hts221_update_odr(hw, hw->odr);
+ int err;
+
+ err = hts221_update_odr(hw, hw->odr);
+ if (err < 0)
+ return err;
+
+ hw->enabled = true;
+
+ return 0;
}
int hts221_power_off(struct hts221_hw *hw)
{
- u8 data[] = {0x00, 0x00};
+ __le16 data = 0;
+ int err;
- return hw->tf->write(hw->dev, HTS221_REG_CNTRL1_ADDR, sizeof(data),
- data);
+ err = hw->tf->write(hw->dev, HTS221_REG_CNTRL1_ADDR, sizeof(data),
+ (u8 *)&data);
+ if (err < 0)
+ return err;
+
+ hw->enabled = false;
+
+ return 0;
}
static int hts221_parse_temp_caldata(struct hts221_hw *hw)
@@ -682,6 +698,36 @@ int hts221_probe(struct iio_dev *iio_dev)
}
EXPORT_SYMBOL(hts221_probe);
+static int __maybe_unused hts221_suspend(struct device *dev)
+{
+ struct iio_dev *iio_dev = dev_get_drvdata(dev);
+ struct hts221_hw *hw = iio_priv(iio_dev);
+ __le16 data = 0;
+ int err;
+
+ err = hw->tf->write(hw->dev, HTS221_REG_CNTRL1_ADDR, sizeof(data),
+ (u8 *)&data);
+
+ return err < 0 ? err : 0;
+}
+
+static int __maybe_unused hts221_resume(struct device *dev)
+{
+ struct iio_dev *iio_dev = dev_get_drvdata(dev);
+ struct hts221_hw *hw = iio_priv(iio_dev);
+ int err = 0;
+
+ if (hw->enabled)
+ err = hts221_update_odr(hw, hw->odr);
+
+ return err;
+}
+
+const struct dev_pm_ops hts221_pm_ops = {
+ SET_SYSTEM_SLEEP_PM_OPS(hts221_suspend, hts221_resume)
+};
+EXPORT_SYMBOL(hts221_pm_ops);
+
MODULE_AUTHOR("Lorenzo Bianconi <lorenzo.bianconi@st.com>");
MODULE_DESCRIPTION("STMicroelectronics hts221 sensor driver");
MODULE_LICENSE("GPL v2");
diff --git a/drivers/iio/humidity/hts221_i2c.c b/drivers/iio/humidity/hts221_i2c.c
index 8333c0296c0e..f38e4b7e0160 100644
--- a/drivers/iio/humidity/hts221_i2c.c
+++ b/drivers/iio/humidity/hts221_i2c.c
@@ -105,6 +105,7 @@ MODULE_DEVICE_TABLE(i2c, hts221_i2c_id_table);
static struct i2c_driver hts221_driver = {
.driver = {
.name = "hts221_i2c",
+ .pm = &hts221_pm_ops,
.of_match_table = of_match_ptr(hts221_i2c_of_match),
.acpi_match_table = ACPI_PTR(hts221_acpi_match),
},
diff --git a/drivers/iio/humidity/hts221_spi.c b/drivers/iio/humidity/hts221_spi.c
index 70df5e7150c1..57cbc256771b 100644
--- a/drivers/iio/humidity/hts221_spi.c
+++ b/drivers/iio/humidity/hts221_spi.c
@@ -113,6 +113,7 @@ MODULE_DEVICE_TABLE(spi, hts221_spi_id_table);
static struct spi_driver hts221_driver = {
.driver = {
.name = "hts221_spi",
+ .pm = &hts221_pm_ops,
.of_match_table = of_match_ptr(hts221_spi_of_match),
},
.probe = hts221_spi_probe,
diff --git a/drivers/iio/imu/inv_mpu6050/inv_mpu_core.c b/drivers/iio/imu/inv_mpu6050/inv_mpu_core.c
index 96dabbd2f004..44830bce13df 100644
--- a/drivers/iio/imu/inv_mpu6050/inv_mpu_core.c
+++ b/drivers/iio/imu/inv_mpu6050/inv_mpu_core.c
@@ -41,6 +41,7 @@ static const int accel_scale[] = {598, 1196, 2392, 4785};
static const struct inv_mpu6050_reg_map reg_set_6500 = {
.sample_rate_div = INV_MPU6050_REG_SAMPLE_RATE_DIV,
.lpf = INV_MPU6050_REG_CONFIG,
+ .accel_lpf = INV_MPU6500_REG_ACCEL_CONFIG_2,
.user_ctrl = INV_MPU6050_REG_USER_CTRL,
.fifo_en = INV_MPU6050_REG_FIFO_EN,
.gyro_config = INV_MPU6050_REG_GYRO_CONFIG,
@@ -187,7 +188,6 @@ int inv_mpu6050_set_power_itg(struct inv_mpu6050_state *st, bool power_on)
int result = 0;
if (power_on) {
- /* Already under indio-dev->mlock mutex */
if (!st->powerup_count)
result = regmap_write(st->map, st->reg->pwr_mgmt_1, 0);
if (!result)
@@ -211,6 +211,37 @@ int inv_mpu6050_set_power_itg(struct inv_mpu6050_state *st, bool power_on)
EXPORT_SYMBOL_GPL(inv_mpu6050_set_power_itg);
/**
+ * inv_mpu6050_set_lpf_regs() - set low pass filter registers, chip dependent
+ *
+ * MPU60xx/MPU9150 use only 1 register for accelerometer + gyroscope
+ * MPU6500 and above have a dedicated register for accelerometer
+ */
+static int inv_mpu6050_set_lpf_regs(struct inv_mpu6050_state *st,
+ enum inv_mpu6050_filter_e val)
+{
+ int result;
+
+ result = regmap_write(st->map, st->reg->lpf, val);
+ if (result)
+ return result;
+
+ switch (st->chip_type) {
+ case INV_MPU6050:
+ case INV_MPU6000:
+ case INV_MPU9150:
+ /* old chips, nothing to do */
+ result = 0;
+ break;
+ default:
+ /* set accel lpf */
+ result = regmap_write(st->map, st->reg->accel_lpf, val);
+ break;
+ }
+
+ return result;
+}
+
+/**
* inv_mpu6050_init_config() - Initialize hardware, disable FIFO.
*
* Initial configuration:
@@ -233,8 +264,7 @@ static int inv_mpu6050_init_config(struct iio_dev *indio_dev)
if (result)
return result;
- d = INV_MPU6050_FILTER_20HZ;
- result = regmap_write(st->map, st->reg->lpf, d);
+ result = inv_mpu6050_set_lpf_regs(st, INV_MPU6050_FILTER_20HZ);
if (result)
return result;
@@ -298,50 +328,37 @@ inv_mpu6050_read_raw(struct iio_dev *indio_dev,
int result;
ret = IIO_VAL_INT;
- result = 0;
- mutex_lock(&indio_dev->mlock);
- if (!st->chip_config.enable) {
- result = inv_mpu6050_set_power_itg(st, true);
- if (result)
- goto error_read_raw;
- }
- /* when enable is on, power is already on */
+ mutex_lock(&st->lock);
+ result = iio_device_claim_direct_mode(indio_dev);
+ if (result)
+ goto error_read_raw_unlock;
+ result = inv_mpu6050_set_power_itg(st, true);
+ if (result)
+ goto error_read_raw_release;
switch (chan->type) {
case IIO_ANGL_VEL:
- if (!st->chip_config.gyro_fifo_enable ||
- !st->chip_config.enable) {
- result = inv_mpu6050_switch_engine(st, true,
- INV_MPU6050_BIT_PWR_GYRO_STBY);
- if (result)
- goto error_read_raw;
- }
+ result = inv_mpu6050_switch_engine(st, true,
+ INV_MPU6050_BIT_PWR_GYRO_STBY);
+ if (result)
+ goto error_read_raw_power_off;
ret = inv_mpu6050_sensor_show(st, st->reg->raw_gyro,
chan->channel2, val);
- if (!st->chip_config.gyro_fifo_enable ||
- !st->chip_config.enable) {
- result = inv_mpu6050_switch_engine(st, false,
- INV_MPU6050_BIT_PWR_GYRO_STBY);
- if (result)
- goto error_read_raw;
- }
+ result = inv_mpu6050_switch_engine(st, false,
+ INV_MPU6050_BIT_PWR_GYRO_STBY);
+ if (result)
+ goto error_read_raw_power_off;
break;
case IIO_ACCEL:
- if (!st->chip_config.accl_fifo_enable ||
- !st->chip_config.enable) {
- result = inv_mpu6050_switch_engine(st, true,
- INV_MPU6050_BIT_PWR_ACCL_STBY);
- if (result)
- goto error_read_raw;
- }
+ result = inv_mpu6050_switch_engine(st, true,
+ INV_MPU6050_BIT_PWR_ACCL_STBY);
+ if (result)
+ goto error_read_raw_power_off;
ret = inv_mpu6050_sensor_show(st, st->reg->raw_accl,
chan->channel2, val);
- if (!st->chip_config.accl_fifo_enable ||
- !st->chip_config.enable) {
- result = inv_mpu6050_switch_engine(st, false,
- INV_MPU6050_BIT_PWR_ACCL_STBY);
- if (result)
- goto error_read_raw;
- }
+ result = inv_mpu6050_switch_engine(st, false,
+ INV_MPU6050_BIT_PWR_ACCL_STBY);
+ if (result)
+ goto error_read_raw_power_off;
break;
case IIO_TEMP:
/* wait for stablization */
@@ -353,10 +370,12 @@ inv_mpu6050_read_raw(struct iio_dev *indio_dev,
ret = -EINVAL;
break;
}
-error_read_raw:
- if (!st->chip_config.enable)
- result |= inv_mpu6050_set_power_itg(st, false);
- mutex_unlock(&indio_dev->mlock);
+error_read_raw_power_off:
+ result |= inv_mpu6050_set_power_itg(st, false);
+error_read_raw_release:
+ iio_device_release_direct_mode(indio_dev);
+error_read_raw_unlock:
+ mutex_unlock(&st->lock);
if (result)
return result;
@@ -365,13 +384,17 @@ error_read_raw:
case IIO_CHAN_INFO_SCALE:
switch (chan->type) {
case IIO_ANGL_VEL:
+ mutex_lock(&st->lock);
*val = 0;
*val2 = gyro_scale_6050[st->chip_config.fsr];
+ mutex_unlock(&st->lock);
return IIO_VAL_INT_PLUS_NANO;
case IIO_ACCEL:
+ mutex_lock(&st->lock);
*val = 0;
*val2 = accel_scale[st->chip_config.accl_fs];
+ mutex_unlock(&st->lock);
return IIO_VAL_INT_PLUS_MICRO;
case IIO_TEMP:
@@ -394,12 +417,16 @@ error_read_raw:
case IIO_CHAN_INFO_CALIBBIAS:
switch (chan->type) {
case IIO_ANGL_VEL:
+ mutex_lock(&st->lock);
ret = inv_mpu6050_sensor_show(st, st->reg->gyro_offset,
chan->channel2, val);
+ mutex_unlock(&st->lock);
return IIO_VAL_INT;
case IIO_ACCEL:
+ mutex_lock(&st->lock);
ret = inv_mpu6050_sensor_show(st, st->reg->accl_offset,
chan->channel2, val);
+ mutex_unlock(&st->lock);
return IIO_VAL_INT;
default:
@@ -475,18 +502,17 @@ static int inv_mpu6050_write_raw(struct iio_dev *indio_dev,
struct inv_mpu6050_state *st = iio_priv(indio_dev);
int result;
- mutex_lock(&indio_dev->mlock);
+ mutex_lock(&st->lock);
/*
* we should only update scale when the chip is disabled, i.e.
* not running
*/
- if (st->chip_config.enable) {
- result = -EBUSY;
- goto error_write_raw;
- }
+ result = iio_device_claim_direct_mode(indio_dev);
+ if (result)
+ goto error_write_raw_unlock;
result = inv_mpu6050_set_power_itg(st, true);
if (result)
- goto error_write_raw;
+ goto error_write_raw_release;
switch (mask) {
case IIO_CHAN_INFO_SCALE:
@@ -522,9 +548,11 @@ static int inv_mpu6050_write_raw(struct iio_dev *indio_dev,
break;
}
-error_write_raw:
result |= inv_mpu6050_set_power_itg(st, false);
- mutex_unlock(&indio_dev->mlock);
+error_write_raw_release:
+ iio_device_release_direct_mode(indio_dev);
+error_write_raw_unlock:
+ mutex_unlock(&st->lock);
return result;
}
@@ -537,6 +565,8 @@ error_write_raw:
* would be alising. This function basically search for the
* correct low pass parameters based on the fifo rate, e.g,
* sampling frequency.
+ *
+ * lpf is set automatically when setting sampling rate to avoid any aliases.
*/
static int inv_mpu6050_set_lpf(struct inv_mpu6050_state *st, int rate)
{
@@ -552,7 +582,7 @@ static int inv_mpu6050_set_lpf(struct inv_mpu6050_state *st, int rate)
while ((h < hz[i]) && (i < ARRAY_SIZE(d) - 1))
i++;
data = d[i];
- result = regmap_write(st->map, st->reg->lpf, data);
+ result = inv_mpu6050_set_lpf_regs(st, data);
if (result)
return result;
st->chip_config.lpf = data;
@@ -578,31 +608,35 @@ inv_mpu6050_fifo_rate_store(struct device *dev, struct device_attribute *attr,
if (fifo_rate < INV_MPU6050_MIN_FIFO_RATE ||
fifo_rate > INV_MPU6050_MAX_FIFO_RATE)
return -EINVAL;
- if (fifo_rate == st->chip_config.fifo_rate)
- return count;
- mutex_lock(&indio_dev->mlock);
- if (st->chip_config.enable) {
- result = -EBUSY;
- goto fifo_rate_fail;
+ mutex_lock(&st->lock);
+ if (fifo_rate == st->chip_config.fifo_rate) {
+ result = 0;
+ goto fifo_rate_fail_unlock;
}
+ result = iio_device_claim_direct_mode(indio_dev);
+ if (result)
+ goto fifo_rate_fail_unlock;
result = inv_mpu6050_set_power_itg(st, true);
if (result)
- goto fifo_rate_fail;
+ goto fifo_rate_fail_release;
d = INV_MPU6050_ONE_K_HZ / fifo_rate - 1;
result = regmap_write(st->map, st->reg->sample_rate_div, d);
if (result)
- goto fifo_rate_fail;
+ goto fifo_rate_fail_power_off;
st->chip_config.fifo_rate = fifo_rate;
result = inv_mpu6050_set_lpf(st, fifo_rate);
if (result)
- goto fifo_rate_fail;
+ goto fifo_rate_fail_power_off;
-fifo_rate_fail:
+fifo_rate_fail_power_off:
result |= inv_mpu6050_set_power_itg(st, false);
- mutex_unlock(&indio_dev->mlock);
+fifo_rate_fail_release:
+ iio_device_release_direct_mode(indio_dev);
+fifo_rate_fail_unlock:
+ mutex_unlock(&st->lock);
if (result)
return result;
@@ -617,8 +651,13 @@ inv_fifo_rate_show(struct device *dev, struct device_attribute *attr,
char *buf)
{
struct inv_mpu6050_state *st = iio_priv(dev_to_iio_dev(dev));
+ unsigned fifo_rate;
- return sprintf(buf, "%d\n", st->chip_config.fifo_rate);
+ mutex_lock(&st->lock);
+ fifo_rate = st->chip_config.fifo_rate;
+ mutex_unlock(&st->lock);
+
+ return scnprintf(buf, PAGE_SIZE, "%u\n", fifo_rate);
}
/**
@@ -645,7 +684,8 @@ static ssize_t inv_attr_show(struct device *dev, struct device_attribute *attr,
case ATTR_ACCL_MATRIX:
m = st->plat_data.orientation;
- return sprintf(buf, "%d, %d, %d; %d, %d, %d; %d, %d, %d\n",
+ return scnprintf(buf, PAGE_SIZE,
+ "%d, %d, %d; %d, %d, %d; %d, %d, %d\n",
m[0], m[1], m[2], m[3], m[4], m[5], m[6], m[7], m[8]);
default:
return -EINVAL;
@@ -770,27 +810,42 @@ static int inv_check_and_setup_chip(struct inv_mpu6050_state *st)
{
int result;
unsigned int regval;
+ int i;
st->hw = &hw_info[st->chip_type];
st->reg = hw_info[st->chip_type].reg;
- /* reset to make sure previous state are not there */
- result = regmap_write(st->map, st->reg->pwr_mgmt_1,
- INV_MPU6050_BIT_H_RESET);
- if (result)
- return result;
- msleep(INV_MPU6050_POWER_UP_TIME);
-
/* check chip self-identification */
result = regmap_read(st->map, INV_MPU6050_REG_WHOAMI, &regval);
if (result)
return result;
if (regval != st->hw->whoami) {
- dev_warn(regmap_get_device(st->map),
- "whoami mismatch got %#02x expected %#02hhx for %s\n",
+ /* check whoami against all possible values */
+ for (i = 0; i < INV_NUM_PARTS; ++i) {
+ if (regval == hw_info[i].whoami) {
+ dev_warn(regmap_get_device(st->map),
+ "whoami mismatch got %#02x (%s)"
+ "expected %#02hhx (%s)\n",
+ regval, hw_info[i].name,
+ st->hw->whoami, st->hw->name);
+ break;
+ }
+ }
+ if (i >= INV_NUM_PARTS) {
+ dev_err(regmap_get_device(st->map),
+ "invalid whoami %#02x expected %#02hhx (%s)\n",
regval, st->hw->whoami, st->hw->name);
+ return -ENODEV;
+ }
}
+ /* reset to make sure previous state are not there */
+ result = regmap_write(st->map, st->reg->pwr_mgmt_1,
+ INV_MPU6050_BIT_H_RESET);
+ if (result)
+ return result;
+ msleep(INV_MPU6050_POWER_UP_TIME);
+
/*
* toggle power state. After reset, the sleep bit could be on
* or off depending on the OTP settings. Toggling power would
@@ -836,6 +891,7 @@ int inv_mpu_core_probe(struct regmap *regmap, int irq, const char *name,
return -ENODEV;
}
st = iio_priv(indio_dev);
+ mutex_init(&st->lock);
st->chip_type = chip_type;
st->powerup_count = 0;
st->irq = irq;
@@ -929,12 +985,26 @@ EXPORT_SYMBOL_GPL(inv_mpu_core_remove);
static int inv_mpu_resume(struct device *dev)
{
- return inv_mpu6050_set_power_itg(iio_priv(dev_get_drvdata(dev)), true);
+ struct inv_mpu6050_state *st = iio_priv(dev_get_drvdata(dev));
+ int result;
+
+ mutex_lock(&st->lock);
+ result = inv_mpu6050_set_power_itg(st, true);
+ mutex_unlock(&st->lock);
+
+ return result;
}
static int inv_mpu_suspend(struct device *dev)
{
- return inv_mpu6050_set_power_itg(iio_priv(dev_get_drvdata(dev)), false);
+ struct inv_mpu6050_state *st = iio_priv(dev_get_drvdata(dev));
+ int result;
+
+ mutex_lock(&st->lock);
+ result = inv_mpu6050_set_power_itg(st, false);
+ mutex_unlock(&st->lock);
+
+ return result;
}
#endif /* CONFIG_PM_SLEEP */
diff --git a/drivers/iio/imu/inv_mpu6050/inv_mpu_i2c.c b/drivers/iio/imu/inv_mpu6050/inv_mpu_i2c.c
index 64b5f5b92200..fcd7a92b6cf8 100644
--- a/drivers/iio/imu/inv_mpu6050/inv_mpu_i2c.c
+++ b/drivers/iio/imu/inv_mpu6050/inv_mpu_i2c.c
@@ -32,7 +32,7 @@ static int inv_mpu6050_select_bypass(struct i2c_mux_core *muxc, u32 chan_id)
int ret = 0;
/* Use the same mutex which was used everywhere to protect power-op */
- mutex_lock(&indio_dev->mlock);
+ mutex_lock(&st->lock);
if (!st->powerup_count) {
ret = regmap_write(st->map, st->reg->pwr_mgmt_1, 0);
if (ret)
@@ -48,7 +48,7 @@ static int inv_mpu6050_select_bypass(struct i2c_mux_core *muxc, u32 chan_id)
INV_MPU6050_BIT_BYPASS_EN);
}
write_error:
- mutex_unlock(&indio_dev->mlock);
+ mutex_unlock(&st->lock);
return ret;
}
@@ -58,14 +58,14 @@ static int inv_mpu6050_deselect_bypass(struct i2c_mux_core *muxc, u32 chan_id)
struct iio_dev *indio_dev = i2c_mux_priv(muxc);
struct inv_mpu6050_state *st = iio_priv(indio_dev);
- mutex_lock(&indio_dev->mlock);
+ mutex_lock(&st->lock);
/* It doesn't really mattter, if any of the calls fails */
regmap_write(st->map, st->reg->int_pin_cfg, INV_MPU6050_INT_PIN_CFG);
st->powerup_count--;
if (!st->powerup_count)
regmap_write(st->map, st->reg->pwr_mgmt_1,
INV_MPU6050_BIT_SLEEP);
- mutex_unlock(&indio_dev->mlock);
+ mutex_unlock(&st->lock);
return 0;
}
diff --git a/drivers/iio/imu/inv_mpu6050/inv_mpu_iio.h b/drivers/iio/imu/inv_mpu6050/inv_mpu_iio.h
index ef13de7a2c20..065794162d65 100644
--- a/drivers/iio/imu/inv_mpu6050/inv_mpu_iio.h
+++ b/drivers/iio/imu/inv_mpu6050/inv_mpu_iio.h
@@ -14,6 +14,7 @@
#include <linux/i2c-mux.h>
#include <linux/kfifo.h>
#include <linux/spinlock.h>
+#include <linux/mutex.h>
#include <linux/iio/iio.h>
#include <linux/iio/buffer.h>
#include <linux/regmap.h>
@@ -28,6 +29,7 @@
* struct inv_mpu6050_reg_map - Notable registers.
* @sample_rate_div: Divider applied to gyro output rate.
* @lpf: Configures internal low pass filter.
+ * @accel_lpf: Configures accelerometer low pass filter.
* @user_ctrl: Enables/resets the FIFO.
* @fifo_en: Determines which data will appear in FIFO.
* @gyro_config: gyro config register.
@@ -47,6 +49,7 @@
struct inv_mpu6050_reg_map {
u8 sample_rate_div;
u8 lpf;
+ u8 accel_lpf;
u8 user_ctrl;
u8 fifo_en;
u8 gyro_config;
@@ -80,7 +83,6 @@ enum inv_devices {
* @fsr: Full scale range.
* @lpf: Digital low pass filter frequency.
* @accl_fs: accel full scale range.
- * @enable: master enable state.
* @accl_fifo_enable: enable accel data output
* @gyro_fifo_enable: enable gyro data output
* @fifo_rate: FIFO update rate.
@@ -89,7 +91,6 @@ struct inv_mpu6050_chip_config {
unsigned int fsr:2;
unsigned int lpf:3;
unsigned int accl_fs:2;
- unsigned int enable:1;
unsigned int accl_fifo_enable:1;
unsigned int gyro_fifo_enable:1;
u16 fifo_rate;
@@ -112,6 +113,7 @@ struct inv_mpu6050_hw {
/*
* struct inv_mpu6050_state - Driver state variables.
* @TIMESTAMP_FIFO_SIZE: fifo size for timestamp.
+ * @lock: Chip access lock.
* @trig: IIO trigger.
* @chip_config: Cached attribute information.
* @reg: Map of important registers.
@@ -126,6 +128,7 @@ struct inv_mpu6050_hw {
*/
struct inv_mpu6050_state {
#define TIMESTAMP_FIFO_SIZE 16
+ struct mutex lock;
struct iio_trigger *trig;
struct inv_mpu6050_chip_config chip_config;
const struct inv_mpu6050_reg_map *reg;
@@ -188,6 +191,7 @@ struct inv_mpu6050_state {
#define INV_MPU6050_FIFO_THRESHOLD 500
/* mpu6500 registers */
+#define INV_MPU6500_REG_ACCEL_CONFIG_2 0x1D
#define INV_MPU6500_REG_ACCEL_OFFSET 0x77
/* delay time in milliseconds */
diff --git a/drivers/iio/imu/inv_mpu6050/inv_mpu_ring.c b/drivers/iio/imu/inv_mpu6050/inv_mpu_ring.c
index 3a9f3eac91ab..ff81c6aa009d 100644
--- a/drivers/iio/imu/inv_mpu6050/inv_mpu_ring.c
+++ b/drivers/iio/imu/inv_mpu6050/inv_mpu_ring.c
@@ -128,7 +128,7 @@ irqreturn_t inv_mpu6050_read_fifo(int irq, void *p)
u16 fifo_count;
s64 timestamp;
- mutex_lock(&indio_dev->mlock);
+ mutex_lock(&st->lock);
if (!(st->chip_config.accl_fifo_enable |
st->chip_config.gyro_fifo_enable))
goto end_session;
@@ -178,7 +178,7 @@ irqreturn_t inv_mpu6050_read_fifo(int irq, void *p)
}
end_session:
- mutex_unlock(&indio_dev->mlock);
+ mutex_unlock(&st->lock);
iio_trigger_notify_done(indio_dev->trig);
return IRQ_HANDLED;
@@ -186,7 +186,7 @@ end_session:
flush_fifo:
/* Flush HW and SW FIFOs. */
inv_reset_fifo(indio_dev);
- mutex_unlock(&indio_dev->mlock);
+ mutex_unlock(&st->lock);
iio_trigger_notify_done(indio_dev->trig);
return IRQ_HANDLED;
diff --git a/drivers/iio/imu/inv_mpu6050/inv_mpu_trigger.c b/drivers/iio/imu/inv_mpu6050/inv_mpu_trigger.c
index e8818d4dd4b8..540070f0a230 100644
--- a/drivers/iio/imu/inv_mpu6050/inv_mpu_trigger.c
+++ b/drivers/iio/imu/inv_mpu6050/inv_mpu_trigger.c
@@ -90,7 +90,6 @@ static int inv_mpu6050_set_enable(struct iio_dev *indio_dev, bool enable)
if (result)
return result;
}
- st->chip_config.enable = enable;
return 0;
}
@@ -103,7 +102,15 @@ static int inv_mpu6050_set_enable(struct iio_dev *indio_dev, bool enable)
static int inv_mpu_data_rdy_trigger_set_state(struct iio_trigger *trig,
bool state)
{
- return inv_mpu6050_set_enable(iio_trigger_get_drvdata(trig), state);
+ struct iio_dev *indio_dev = iio_trigger_get_drvdata(trig);
+ struct inv_mpu6050_state *st = iio_priv(indio_dev);
+ int result;
+
+ mutex_lock(&st->lock);
+ result = inv_mpu6050_set_enable(indio_dev, state);
+ mutex_unlock(&st->lock);
+
+ return result;
}
static const struct iio_trigger_ops inv_mpu_trigger_ops = {
diff --git a/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx.h b/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx.h
index 4839db7b9690..46352c7bff43 100644
--- a/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx.h
+++ b/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx.h
@@ -135,6 +135,8 @@ struct st_lsm6dsx_hw {
#endif /* CONFIG_SPI_MASTER */
};
+extern const struct dev_pm_ops st_lsm6dsx_pm_ops;
+
int st_lsm6dsx_probe(struct device *dev, int irq, int hw_id, const char *name,
const struct st_lsm6dsx_transfer_function *tf_ops);
int st_lsm6dsx_sensor_enable(struct st_lsm6dsx_sensor *sensor);
@@ -144,5 +146,8 @@ int st_lsm6dsx_write_with_mask(struct st_lsm6dsx_hw *hw, u8 addr, u8 mask,
u8 val);
int st_lsm6dsx_update_watermark(struct st_lsm6dsx_sensor *sensor,
u16 watermark);
+int st_lsm6dsx_flush_fifo(struct st_lsm6dsx_hw *hw);
+int st_lsm6dsx_set_fifo_mode(struct st_lsm6dsx_hw *hw,
+ enum st_lsm6dsx_fifo_mode fifo_mode);
#endif /* ST_LSM6DSX_H */
diff --git a/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_buffer.c b/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_buffer.c
index c8e5cfd0ef0b..2a72acc6e049 100644
--- a/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_buffer.c
+++ b/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_buffer.c
@@ -37,6 +37,8 @@
#define ST_LSM6DSX_REG_FIFO_THH_ADDR 0x07
#define ST_LSM6DSX_FIFO_TH_MASK GENMASK(11, 0)
#define ST_LSM6DSX_REG_FIFO_DEC_GXL_ADDR 0x08
+#define ST_LSM6DSX_REG_HLACTIVE_ADDR 0x12
+#define ST_LSM6DSX_REG_HLACTIVE_MASK BIT(5)
#define ST_LSM6DSX_REG_FIFO_MODE_ADDR 0x0a
#define ST_LSM6DSX_FIFO_MODE_MASK GENMASK(2, 0)
#define ST_LSM6DSX_FIFO_ODR_MASK GENMASK(6, 3)
@@ -130,8 +132,8 @@ static int st_lsm6dsx_update_decimators(struct st_lsm6dsx_hw *hw)
return 0;
}
-static int st_lsm6dsx_set_fifo_mode(struct st_lsm6dsx_hw *hw,
- enum st_lsm6dsx_fifo_mode fifo_mode)
+int st_lsm6dsx_set_fifo_mode(struct st_lsm6dsx_hw *hw,
+ enum st_lsm6dsx_fifo_mode fifo_mode)
{
u8 data;
int err;
@@ -303,7 +305,7 @@ static int st_lsm6dsx_read_fifo(struct st_lsm6dsx_hw *hw)
return read_len;
}
-static int st_lsm6dsx_flush_fifo(struct st_lsm6dsx_hw *hw)
+int st_lsm6dsx_flush_fifo(struct st_lsm6dsx_hw *hw)
{
int err;
@@ -417,6 +419,7 @@ int st_lsm6dsx_fifo_setup(struct st_lsm6dsx_hw *hw)
{
struct iio_buffer *buffer;
unsigned long irq_type;
+ bool irq_active_low;
int i, err;
irq_type = irqd_get_trigger_type(irq_get_irq_data(hw->irq));
@@ -424,12 +427,23 @@ int st_lsm6dsx_fifo_setup(struct st_lsm6dsx_hw *hw)
switch (irq_type) {
case IRQF_TRIGGER_HIGH:
case IRQF_TRIGGER_RISING:
+ irq_active_low = false;
+ break;
+ case IRQF_TRIGGER_LOW:
+ case IRQF_TRIGGER_FALLING:
+ irq_active_low = true;
break;
default:
dev_info(hw->dev, "mode %lx unsupported\n", irq_type);
return -EINVAL;
}
+ err = st_lsm6dsx_write_with_mask(hw, ST_LSM6DSX_REG_HLACTIVE_ADDR,
+ ST_LSM6DSX_REG_HLACTIVE_MASK,
+ irq_active_low);
+ if (err < 0)
+ return err;
+
err = devm_request_threaded_irq(hw->dev, hw->irq,
st_lsm6dsx_handler_irq,
st_lsm6dsx_handler_thread,
diff --git a/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_core.c b/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_core.c
index 462a27b70453..b485540da89e 100644
--- a/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_core.c
+++ b/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_core.c
@@ -36,6 +36,7 @@
#include <linux/delay.h>
#include <linux/iio/iio.h>
#include <linux/iio/sysfs.h>
+#include <linux/pm.h>
#include <linux/platform_data/st_sensors_pdata.h>
@@ -731,6 +732,57 @@ int st_lsm6dsx_probe(struct device *dev, int irq, int hw_id, const char *name,
}
EXPORT_SYMBOL(st_lsm6dsx_probe);
+static int __maybe_unused st_lsm6dsx_suspend(struct device *dev)
+{
+ struct st_lsm6dsx_hw *hw = dev_get_drvdata(dev);
+ struct st_lsm6dsx_sensor *sensor;
+ int i, err = 0;
+
+ for (i = 0; i < ST_LSM6DSX_ID_MAX; i++) {
+ sensor = iio_priv(hw->iio_devs[i]);
+ if (!(hw->enable_mask & BIT(sensor->id)))
+ continue;
+
+ err = st_lsm6dsx_write_with_mask(hw,
+ st_lsm6dsx_odr_table[sensor->id].reg.addr,
+ st_lsm6dsx_odr_table[sensor->id].reg.mask, 0);
+ if (err < 0)
+ return err;
+ }
+
+ if (hw->fifo_mode != ST_LSM6DSX_FIFO_BYPASS)
+ err = st_lsm6dsx_flush_fifo(hw);
+
+ return err;
+}
+
+static int __maybe_unused st_lsm6dsx_resume(struct device *dev)
+{
+ struct st_lsm6dsx_hw *hw = dev_get_drvdata(dev);
+ struct st_lsm6dsx_sensor *sensor;
+ int i, err = 0;
+
+ for (i = 0; i < ST_LSM6DSX_ID_MAX; i++) {
+ sensor = iio_priv(hw->iio_devs[i]);
+ if (!(hw->enable_mask & BIT(sensor->id)))
+ continue;
+
+ err = st_lsm6dsx_set_odr(sensor, sensor->odr);
+ if (err < 0)
+ return err;
+ }
+
+ if (hw->enable_mask)
+ err = st_lsm6dsx_set_fifo_mode(hw, ST_LSM6DSX_FIFO_CONT);
+
+ return err;
+}
+
+const struct dev_pm_ops st_lsm6dsx_pm_ops = {
+ SET_SYSTEM_SLEEP_PM_OPS(st_lsm6dsx_suspend, st_lsm6dsx_resume)
+};
+EXPORT_SYMBOL(st_lsm6dsx_pm_ops);
+
MODULE_AUTHOR("Lorenzo Bianconi <lorenzo.bianconi@st.com>");
MODULE_AUTHOR("Denis Ciocca <denis.ciocca@st.com>");
MODULE_DESCRIPTION("STMicroelectronics st_lsm6dsx driver");
diff --git a/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_i2c.c b/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_i2c.c
index 09a51cfb9b5e..305fec712ab0 100644
--- a/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_i2c.c
+++ b/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_i2c.c
@@ -98,6 +98,7 @@ MODULE_DEVICE_TABLE(i2c, st_lsm6dsx_i2c_id_table);
static struct i2c_driver st_lsm6dsx_driver = {
.driver = {
.name = "st_lsm6dsx_i2c",
+ .pm = &st_lsm6dsx_pm_ops,
.of_match_table = of_match_ptr(st_lsm6dsx_i2c_of_match),
},
.probe = st_lsm6dsx_i2c_probe,
diff --git a/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_spi.c b/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_spi.c
index f765a5058488..95472f153ad2 100644
--- a/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_spi.c
+++ b/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_spi.c
@@ -115,6 +115,7 @@ MODULE_DEVICE_TABLE(spi, st_lsm6dsx_spi_id_table);
static struct spi_driver st_lsm6dsx_driver = {
.driver = {
.name = "st_lsm6dsx_spi",
+ .pm = &st_lsm6dsx_pm_ops,
.of_match_table = of_match_ptr(st_lsm6dsx_spi_of_match),
},
.probe = st_lsm6dsx_spi_probe,
diff --git a/drivers/iio/industrialio-core.c b/drivers/iio/industrialio-core.c
index 57c14da5708f..17ec4cee51dc 100644
--- a/drivers/iio/industrialio-core.c
+++ b/drivers/iio/industrialio-core.c
@@ -478,21 +478,16 @@ ssize_t iio_enum_write(struct iio_dev *indio_dev,
size_t len)
{
const struct iio_enum *e = (const struct iio_enum *)priv;
- unsigned int i;
int ret;
if (!e->set)
return -EINVAL;
- for (i = 0; i < e->num_items; i++) {
- if (sysfs_streq(buf, e->items[i]))
- break;
- }
-
- if (i == e->num_items)
- return -EINVAL;
+ ret = __sysfs_match_string(e->items, e->num_items, buf);
+ if (ret < 0)
+ return ret;
- ret = e->set(indio_dev, chan, i);
+ ret = e->set(indio_dev, chan, ret);
return ret ? ret : len;
}
EXPORT_SYMBOL_GPL(iio_enum_write);
@@ -1089,7 +1084,7 @@ static int iio_device_add_info_mask_type(struct iio_dev *indio_dev,
{
int i, ret, attrcount = 0;
- for_each_set_bit(i, infomask, sizeof(infomask)*8) {
+ for_each_set_bit(i, infomask, sizeof(*infomask)*8) {
if (i >= ARRAY_SIZE(iio_chan_info_postfix))
return -EINVAL;
ret = __iio_add_chan_devattr(iio_chan_info_postfix[i],
@@ -1118,7 +1113,7 @@ static int iio_device_add_info_mask_type_avail(struct iio_dev *indio_dev,
int i, ret, attrcount = 0;
char *avail_postfix;
- for_each_set_bit(i, infomask, sizeof(infomask) * 8) {
+ for_each_set_bit(i, infomask, sizeof(*infomask) * 8) {
avail_postfix = kasprintf(GFP_KERNEL,
"%s_available",
iio_chan_info_postfix[i]);
@@ -1428,7 +1423,7 @@ static void iio_device_unregister_sysfs(struct iio_dev *indio_dev)
static void iio_dev_release(struct device *device)
{
struct iio_dev *indio_dev = dev_to_iio_dev(device);
- if (indio_dev->modes & (INDIO_BUFFER_TRIGGERED | INDIO_EVENT_TRIGGERED))
+ if (indio_dev->modes & INDIO_ALL_TRIGGERED_MODES)
iio_device_unregister_trigger_consumer(indio_dev);
iio_device_unregister_eventset(indio_dev);
iio_device_unregister_sysfs(indio_dev);
@@ -1710,7 +1705,7 @@ int iio_device_register(struct iio_dev *indio_dev)
"Failed to register event set\n");
goto error_free_sysfs;
}
- if (indio_dev->modes & (INDIO_BUFFER_TRIGGERED | INDIO_EVENT_TRIGGERED))
+ if (indio_dev->modes & INDIO_ALL_TRIGGERED_MODES)
iio_device_register_trigger_consumer(indio_dev);
if ((indio_dev->modes & INDIO_ALL_BUFFER_MODES) &&
diff --git a/drivers/iio/industrialio-trigger.c b/drivers/iio/industrialio-trigger.c
index 978e1592c2a3..4061fed93f1f 100644
--- a/drivers/iio/industrialio-trigger.c
+++ b/drivers/iio/industrialio-trigger.c
@@ -451,7 +451,8 @@ static ssize_t iio_trigger_write_current(struct device *dev,
return len;
out_trigger_put:
- iio_trigger_put(trig);
+ if (trig)
+ iio_trigger_put(trig);
return ret;
}
diff --git a/drivers/iio/inkern.c b/drivers/iio/inkern.c
index 7a13535dc3e9..a3941bade6a7 100644
--- a/drivers/iio/inkern.c
+++ b/drivers/iio/inkern.c
@@ -750,11 +750,9 @@ int iio_read_avail_channel_raw(struct iio_channel *chan,
err_unlock:
mutex_unlock(&chan->indio_dev->info_exist_lock);
- if (ret >= 0 && type != IIO_VAL_INT) {
+ if (ret >= 0 && type != IIO_VAL_INT)
/* raw values are assumed to be IIO_VAL_INT */
ret = -EINVAL;
- goto err_unlock;
- }
return ret;
}
diff --git a/drivers/iio/light/Kconfig b/drivers/iio/light/Kconfig
index 33e755d8d825..2356ed9285df 100644
--- a/drivers/iio/light/Kconfig
+++ b/drivers/iio/light/Kconfig
@@ -172,6 +172,16 @@ config SENSORS_ISL29018
in lux, proximity infrared sensing and normal infrared sensing.
Data from sensor is accessible via sysfs.
+config SENSORS_ISL29028
+ tristate "Intersil ISL29028 Concurrent Light and Proximity Sensor"
+ depends on I2C
+ select REGMAP_I2C
+ help
+ Provides driver for the Intersil's ISL29028 device.
+ This driver supports the sysfs interface to get the ALS, IR intensity,
+ Proximity value via iio. The ISL29028 provides the concurrent sensing
+ of ambient light and proximity.
+
config ISL29125
tristate "Intersil ISL29125 digital color light sensor"
depends on I2C
diff --git a/drivers/iio/light/Makefile b/drivers/iio/light/Makefile
index 681363c2b298..fa32fa459e2e 100644
--- a/drivers/iio/light/Makefile
+++ b/drivers/iio/light/Makefile
@@ -20,6 +20,7 @@ obj-$(CONFIG_GP2AP020A00F) += gp2ap020a00f.o
obj-$(CONFIG_HID_SENSOR_ALS) += hid-sensor-als.o
obj-$(CONFIG_HID_SENSOR_PROX) += hid-sensor-prox.o
obj-$(CONFIG_SENSORS_ISL29018) += isl29018.o
+obj-$(CONFIG_SENSORS_ISL29028) += isl29028.o
obj-$(CONFIG_ISL29125) += isl29125.o
obj-$(CONFIG_JSA1212) += jsa1212.o
obj-$(CONFIG_SENSORS_LM3533) += lm3533-als.o
diff --git a/drivers/iio/light/isl29018.c b/drivers/iio/light/isl29018.c
index 917dd8b43e72..61f5924b472d 100644
--- a/drivers/iio/light/isl29018.c
+++ b/drivers/iio/light/isl29018.c
@@ -807,6 +807,7 @@ static SIMPLE_DEV_PM_OPS(isl29018_pm_ops, isl29018_suspend, isl29018_resume);
#define ISL29018_PM_OPS NULL
#endif
+#ifdef CONFIG_ACPI
static const struct acpi_device_id isl29018_acpi_match[] = {
{"ISL29018", isl29018},
{"ISL29023", isl29023},
@@ -814,6 +815,7 @@ static const struct acpi_device_id isl29018_acpi_match[] = {
{},
};
MODULE_DEVICE_TABLE(acpi, isl29018_acpi_match);
+#endif
static const struct i2c_device_id isl29018_id[] = {
{"isl29018", isl29018},
diff --git a/drivers/staging/iio/light/isl29028.c b/drivers/iio/light/isl29028.c
index 5375e7a81205..3d09c1fc4dad 100644
--- a/drivers/staging/iio/light/isl29028.c
+++ b/drivers/iio/light/isl29028.c
@@ -16,6 +16,10 @@
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * Datasheets:
+ * - http://www.intersil.com/content/dam/Intersil/documents/isl2/isl29028.pdf
+ * - http://www.intersil.com/content/dam/Intersil/documents/isl2/isl29030.pdf
*/
#include <linux/module.h>
@@ -64,8 +68,25 @@
#define ISL29028_POWER_OFF_DELAY_MS 2000
-static const unsigned int isl29028_prox_sleep_time[] = {800, 400, 200, 100, 75,
- 50, 12, 0};
+struct isl29028_prox_data {
+ int sampling_int;
+ int sampling_fract;
+ int sleep_time;
+};
+
+static const struct isl29028_prox_data isl29028_prox_data[] = {
+ { 1, 250000, 800 },
+ { 2, 500000, 400 },
+ { 5, 0, 200 },
+ { 10, 0, 100 },
+ { 13, 300000, 75 },
+ { 20, 0, 50 },
+ { 80, 0, 13 }, /*
+ * Note: Data sheet lists 12.5 ms sleep time.
+ * Round up a half millisecond for msleep().
+ */
+ { 100, 0, 0 }
+};
enum isl29028_als_ir_mode {
ISL29028_MODE_NONE = 0,
@@ -76,32 +97,37 @@ enum isl29028_als_ir_mode {
struct isl29028_chip {
struct mutex lock;
struct regmap *regmap;
- unsigned int prox_sampling;
+ int prox_sampling_int;
+ int prox_sampling_frac;
bool enable_prox;
int lux_scale;
enum isl29028_als_ir_mode als_ir_mode;
};
-static int isl29028_find_prox_sleep_time_index(int sampling)
+static int isl29028_find_prox_sleep_index(int sampling_int, int sampling_fract)
{
- unsigned int period = DIV_ROUND_UP(1000, sampling);
int i;
- for (i = 0; i < ARRAY_SIZE(isl29028_prox_sleep_time); ++i) {
- if (period >= isl29028_prox_sleep_time[i])
- break;
+ for (i = 0; i < ARRAY_SIZE(isl29028_prox_data); ++i) {
+ if (isl29028_prox_data[i].sampling_int == sampling_int &&
+ isl29028_prox_data[i].sampling_fract == sampling_fract)
+ return i;
}
- return i;
+ return -EINVAL;
}
static int isl29028_set_proxim_sampling(struct isl29028_chip *chip,
- unsigned int sampling)
+ int sampling_int, int sampling_fract)
{
struct device *dev = regmap_get_device(chip->regmap);
int sleep_index, ret;
- sleep_index = isl29028_find_prox_sleep_time_index(sampling);
+ sleep_index = isl29028_find_prox_sleep_index(sampling_int,
+ sampling_fract);
+ if (sleep_index < 0)
+ return sleep_index;
+
ret = regmap_update_bits(chip->regmap, ISL29028_REG_CONFIGURE,
ISL29028_CONF_PROX_SLP_MASK,
sleep_index << ISL29028_CONF_PROX_SLP_SH);
@@ -112,16 +138,18 @@ static int isl29028_set_proxim_sampling(struct isl29028_chip *chip,
return ret;
}
- chip->prox_sampling = sampling;
+ chip->prox_sampling_int = sampling_int;
+ chip->prox_sampling_frac = sampling_fract;
return ret;
}
static int isl29028_enable_proximity(struct isl29028_chip *chip)
{
- int sleep_index, ret;
+ int prox_index, ret;
- ret = isl29028_set_proxim_sampling(chip, chip->prox_sampling);
+ ret = isl29028_set_proxim_sampling(chip, chip->prox_sampling_int,
+ chip->prox_sampling_frac);
if (ret < 0)
return ret;
@@ -132,8 +160,12 @@ static int isl29028_enable_proximity(struct isl29028_chip *chip)
return ret;
/* Wait for conversion to be complete for first sample */
- sleep_index = isl29028_find_prox_sleep_time_index(chip->prox_sampling);
- msleep(isl29028_prox_sleep_time[sleep_index]);
+ prox_index = isl29028_find_prox_sleep_index(chip->prox_sampling_int,
+ chip->prox_sampling_frac);
+ if (prox_index < 0)
+ return prox_index;
+
+ msleep(isl29028_prox_data[prox_index].sleep_time);
return 0;
}
@@ -361,7 +393,7 @@ static int isl29028_write_raw(struct iio_dev *indio_dev,
break;
}
- ret = isl29028_set_proxim_sampling(chip, val);
+ ret = isl29028_set_proxim_sampling(chip, val, val2);
break;
case IIO_LIGHT:
if (mask != IIO_CHAN_INFO_SCALE) {
@@ -439,7 +471,8 @@ static int isl29028_read_raw(struct iio_dev *indio_dev,
if (chan->type != IIO_PROXIMITY)
break;
- *val = chip->prox_sampling;
+ *val = chip->prox_sampling_int;
+ *val2 = chip->prox_sampling_frac;
ret = IIO_VAL_INT;
break;
case IIO_CHAN_INFO_SCALE:
@@ -472,7 +505,7 @@ static int isl29028_read_raw(struct iio_dev *indio_dev,
}
static IIO_CONST_ATTR(in_proximity_sampling_frequency_available,
- "1 3 5 10 13 20 83 100");
+ "1.25 2.5 5 10 13.3 20 80 100");
static IIO_CONST_ATTR(in_illuminance_scale_available, "125 2000");
#define ISL29028_CONST_ATTR(name) (&iio_const_attr_##name.dev_attr.attr)
@@ -571,7 +604,8 @@ static int isl29028_probe(struct i2c_client *client,
}
chip->enable_prox = false;
- chip->prox_sampling = 20;
+ chip->prox_sampling_int = 20;
+ chip->prox_sampling_frac = 0;
chip->lux_scale = 2000;
ret = regmap_write(chip->regmap, ISL29028_REG_TEST1_MODE, 0x0);
@@ -664,6 +698,7 @@ static const struct dev_pm_ops isl29028_pm_ops = {
static const struct i2c_device_id isl29028_id[] = {
{"isl29028", 0},
+ {"isl29030", 0},
{}
};
MODULE_DEVICE_TABLE(i2c, isl29028_id);
@@ -671,6 +706,7 @@ MODULE_DEVICE_TABLE(i2c, isl29028_id);
static const struct of_device_id isl29028_of_match[] = {
{ .compatible = "isl,isl29028", }, /* for backward compat., don't use */
{ .compatible = "isil,isl29028", },
+ { .compatible = "isil,isl29030", },
{ },
};
MODULE_DEVICE_TABLE(of, isl29028_of_match);
diff --git a/drivers/iio/light/ltr501.c b/drivers/iio/light/ltr501.c
index b30e0c1c6cc4..67838edd8b37 100644
--- a/drivers/iio/light/ltr501.c
+++ b/drivers/iio/light/ltr501.c
@@ -74,9 +74,9 @@ static const int int_time_mapping[] = {100000, 50000, 200000, 400000};
static const struct reg_field reg_field_it =
REG_FIELD(LTR501_ALS_MEAS_RATE, 3, 4);
static const struct reg_field reg_field_als_intr =
- REG_FIELD(LTR501_INTR, 0, 0);
-static const struct reg_field reg_field_ps_intr =
REG_FIELD(LTR501_INTR, 1, 1);
+static const struct reg_field reg_field_ps_intr =
+ REG_FIELD(LTR501_INTR, 0, 0);
static const struct reg_field reg_field_als_rate =
REG_FIELD(LTR501_ALS_MEAS_RATE, 0, 2);
static const struct reg_field reg_field_ps_rate =
diff --git a/drivers/iio/light/rpr0521.c b/drivers/iio/light/rpr0521.c
index 7de0f397194b..9d0c2e859bb2 100644
--- a/drivers/iio/light/rpr0521.c
+++ b/drivers/iio/light/rpr0521.c
@@ -9,7 +9,7 @@
*
* IIO driver for RPR-0521RS (7-bit I2C slave address 0x38).
*
- * TODO: illuminance channel, PM support, buffer
+ * TODO: illuminance channel, buffer
*/
#include <linux/module.h>
@@ -30,6 +30,7 @@
#define RPR0521_REG_PXS_DATA 0x44 /* 16-bit, little endian */
#define RPR0521_REG_ALS_DATA0 0x46 /* 16-bit, little endian */
#define RPR0521_REG_ALS_DATA1 0x48 /* 16-bit, little endian */
+#define RPR0521_REG_PS_OFFSET_LSB 0x53
#define RPR0521_REG_ID 0x92
#define RPR0521_MODE_ALS_MASK BIT(7)
@@ -77,9 +78,9 @@ static const struct rpr0521_gain rpr0521_pxs_gain[3] = {
};
enum rpr0521_channel {
+ RPR0521_CHAN_PXS,
RPR0521_CHAN_ALS_DATA0,
RPR0521_CHAN_ALS_DATA1,
- RPR0521_CHAN_PXS,
};
struct rpr0521_reg_desc {
@@ -88,6 +89,10 @@ struct rpr0521_reg_desc {
};
static const struct rpr0521_reg_desc rpr0521_data_reg[] = {
+ [RPR0521_CHAN_PXS] = {
+ .address = RPR0521_REG_PXS_DATA,
+ .device_mask = RPR0521_MODE_PXS_MASK,
+ },
[RPR0521_CHAN_ALS_DATA0] = {
.address = RPR0521_REG_ALS_DATA0,
.device_mask = RPR0521_MODE_ALS_MASK,
@@ -96,10 +101,6 @@ static const struct rpr0521_reg_desc rpr0521_data_reg[] = {
.address = RPR0521_REG_ALS_DATA1,
.device_mask = RPR0521_MODE_ALS_MASK,
},
- [RPR0521_CHAN_PXS] = {
- .address = RPR0521_REG_PXS_DATA,
- .device_mask = RPR0521_MODE_PXS_MASK,
- },
};
static const struct rpr0521_gain_info {
@@ -109,6 +110,13 @@ static const struct rpr0521_gain_info {
const struct rpr0521_gain *gain;
int size;
} rpr0521_gain[] = {
+ [RPR0521_CHAN_PXS] = {
+ .reg = RPR0521_REG_PXS_CTRL,
+ .mask = RPR0521_PXS_GAIN_MASK,
+ .shift = RPR0521_PXS_GAIN_SHIFT,
+ .gain = rpr0521_pxs_gain,
+ .size = ARRAY_SIZE(rpr0521_pxs_gain),
+ },
[RPR0521_CHAN_ALS_DATA0] = {
.reg = RPR0521_REG_ALS_CTRL,
.mask = RPR0521_ALS_DATA0_GAIN_MASK,
@@ -123,13 +131,30 @@ static const struct rpr0521_gain_info {
.gain = rpr0521_als_gain,
.size = ARRAY_SIZE(rpr0521_als_gain),
},
- [RPR0521_CHAN_PXS] = {
- .reg = RPR0521_REG_PXS_CTRL,
- .mask = RPR0521_PXS_GAIN_MASK,
- .shift = RPR0521_PXS_GAIN_SHIFT,
- .gain = rpr0521_pxs_gain,
- .size = ARRAY_SIZE(rpr0521_pxs_gain),
- },
+};
+
+struct rpr0521_samp_freq {
+ int als_hz;
+ int als_uhz;
+ int pxs_hz;
+ int pxs_uhz;
+};
+
+static const struct rpr0521_samp_freq rpr0521_samp_freq_i[13] = {
+/* {ALS, PXS}, W==currently writable option */
+ {0, 0, 0, 0}, /* W0000, 0=standby */
+ {0, 0, 100, 0}, /* 0001 */
+ {0, 0, 25, 0}, /* 0010 */
+ {0, 0, 10, 0}, /* 0011 */
+ {0, 0, 2, 500000}, /* 0100 */
+ {10, 0, 20, 0}, /* 0101 */
+ {10, 0, 10, 0}, /* W0110 */
+ {10, 0, 2, 500000}, /* 0111 */
+ {2, 500000, 20, 0}, /* 1000, measurement 100ms, sleep 300ms */
+ {2, 500000, 10, 0}, /* 1001, measurement 100ms, sleep 300ms */
+ {2, 500000, 0, 0}, /* 1010, high sensitivity mode */
+ {2, 500000, 2, 500000}, /* W1011, high sensitivity mode */
+ {20, 0, 20, 0} /* 1100, ALS_data x 0.5, see specification P.18 */
};
struct rpr0521_data {
@@ -142,9 +167,11 @@ struct rpr0521_data {
bool als_dev_en;
bool pxs_dev_en;
- /* optimize runtime pm ops - enable device only if needed */
+ /* optimize runtime pm ops - enable/disable device only if needed */
bool als_ps_need_en;
bool pxs_ps_need_en;
+ bool als_need_dis;
+ bool pxs_need_dis;
struct regmap *regmap;
};
@@ -152,9 +179,16 @@ struct rpr0521_data {
static IIO_CONST_ATTR(in_intensity_scale_available, RPR0521_ALS_SCALE_AVAIL);
static IIO_CONST_ATTR(in_proximity_scale_available, RPR0521_PXS_SCALE_AVAIL);
+/*
+ * Start with easy freq first, whole table of freq combinations is more
+ * complicated.
+ */
+static IIO_CONST_ATTR_SAMP_FREQ_AVAIL("2.5 10");
+
static struct attribute *rpr0521_attributes[] = {
&iio_const_attr_in_intensity_scale_available.dev_attr.attr,
&iio_const_attr_in_proximity_scale_available.dev_attr.attr,
+ &iio_const_attr_sampling_frequency_available.dev_attr.attr,
NULL,
};
@@ -164,12 +198,21 @@ static const struct attribute_group rpr0521_attribute_group = {
static const struct iio_chan_spec rpr0521_channels[] = {
{
+ .type = IIO_PROXIMITY,
+ .address = RPR0521_CHAN_PXS,
+ .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
+ BIT(IIO_CHAN_INFO_OFFSET) |
+ BIT(IIO_CHAN_INFO_SCALE),
+ .info_mask_shared_by_all = BIT(IIO_CHAN_INFO_SAMP_FREQ),
+ },
+ {
.type = IIO_INTENSITY,
.modified = 1,
.address = RPR0521_CHAN_ALS_DATA0,
.channel2 = IIO_MOD_LIGHT_BOTH,
.info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
BIT(IIO_CHAN_INFO_SCALE),
+ .info_mask_shared_by_all = BIT(IIO_CHAN_INFO_SAMP_FREQ),
},
{
.type = IIO_INTENSITY,
@@ -178,13 +221,8 @@ static const struct iio_chan_spec rpr0521_channels[] = {
.channel2 = IIO_MOD_LIGHT_IR,
.info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
BIT(IIO_CHAN_INFO_SCALE),
+ .info_mask_shared_by_all = BIT(IIO_CHAN_INFO_SAMP_FREQ),
},
- {
- .type = IIO_PROXIMITY,
- .address = RPR0521_CHAN_PXS,
- .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
- BIT(IIO_CHAN_INFO_SCALE),
- }
};
static int rpr0521_als_enable(struct rpr0521_data *data, u8 status)
@@ -197,7 +235,10 @@ static int rpr0521_als_enable(struct rpr0521_data *data, u8 status)
if (ret < 0)
return ret;
- data->als_dev_en = true;
+ if (status & RPR0521_MODE_ALS_MASK)
+ data->als_dev_en = true;
+ else
+ data->als_dev_en = false;
return 0;
}
@@ -212,7 +253,10 @@ static int rpr0521_pxs_enable(struct rpr0521_data *data, u8 status)
if (ret < 0)
return ret;
- data->pxs_dev_en = true;
+ if (status & RPR0521_MODE_PXS_MASK)
+ data->pxs_dev_en = true;
+ else
+ data->pxs_dev_en = false;
return 0;
}
@@ -224,40 +268,32 @@ static int rpr0521_pxs_enable(struct rpr0521_data *data, u8 status)
* @on: state to be set for devices in @device_mask
* @device_mask: bitmask specifying for which device we need to update @on state
*
- * We rely on rpr0521_runtime_resume to enable our @device_mask devices, but
- * if (for example) PXS was enabled (pxs_dev_en = true) by a previous call to
- * rpr0521_runtime_resume and we want to enable ALS we MUST set ALS enable
- * bit of RPR0521_REG_MODE_CTRL here because rpr0521_runtime_resume will not
- * be called twice.
+ * Calls for this function must be balanced so that each ON should have matching
+ * OFF. Otherwise pm usage_count gets out of sync.
*/
static int rpr0521_set_power_state(struct rpr0521_data *data, bool on,
u8 device_mask)
{
#ifdef CONFIG_PM
int ret;
- u8 update_mask = 0;
if (device_mask & RPR0521_MODE_ALS_MASK) {
- if (on && !data->als_ps_need_en && data->pxs_dev_en)
- update_mask |= RPR0521_MODE_ALS_MASK;
- else
- data->als_ps_need_en = on;
+ data->als_ps_need_en = on;
+ data->als_need_dis = !on;
}
if (device_mask & RPR0521_MODE_PXS_MASK) {
- if (on && !data->pxs_ps_need_en && data->als_dev_en)
- update_mask |= RPR0521_MODE_PXS_MASK;
- else
- data->pxs_ps_need_en = on;
- }
-
- if (update_mask) {
- ret = regmap_update_bits(data->regmap, RPR0521_REG_MODE_CTRL,
- update_mask, update_mask);
- if (ret < 0)
- return ret;
+ data->pxs_ps_need_en = on;
+ data->pxs_need_dis = !on;
}
+ /*
+ * On: _resume() is called only when we are suspended
+ * Off: _suspend() is called after delay if _resume() is not
+ * called before that.
+ * Note: If either measurement is re-enabled before _suspend(),
+ * both stay enabled until _suspend().
+ */
if (on) {
ret = pm_runtime_get_sync(&data->client->dev);
} else {
@@ -273,6 +309,23 @@ static int rpr0521_set_power_state(struct rpr0521_data *data, bool on,
return ret;
}
+
+ if (on) {
+ /* If _resume() was not called, enable measurement now. */
+ if (data->als_ps_need_en) {
+ ret = rpr0521_als_enable(data, RPR0521_MODE_ALS_ENABLE);
+ if (ret)
+ return ret;
+ data->als_ps_need_en = false;
+ }
+
+ if (data->pxs_ps_need_en) {
+ ret = rpr0521_pxs_enable(data, RPR0521_MODE_PXS_ENABLE);
+ if (ret)
+ return ret;
+ data->pxs_ps_need_en = false;
+ }
+ }
#endif
return 0;
}
@@ -314,6 +367,106 @@ static int rpr0521_set_gain(struct rpr0521_data *data, int chan,
idx << rpr0521_gain[chan].shift);
}
+static int rpr0521_read_samp_freq(struct rpr0521_data *data,
+ enum iio_chan_type chan_type,
+ int *val, int *val2)
+{
+ int reg, ret;
+
+ ret = regmap_read(data->regmap, RPR0521_REG_MODE_CTRL, &reg);
+ if (ret < 0)
+ return ret;
+
+ reg &= RPR0521_MODE_MEAS_TIME_MASK;
+ if (reg >= ARRAY_SIZE(rpr0521_samp_freq_i))
+ return -EINVAL;
+
+ switch (chan_type) {
+ case IIO_INTENSITY:
+ *val = rpr0521_samp_freq_i[reg].als_hz;
+ *val2 = rpr0521_samp_freq_i[reg].als_uhz;
+ return 0;
+
+ case IIO_PROXIMITY:
+ *val = rpr0521_samp_freq_i[reg].pxs_hz;
+ *val2 = rpr0521_samp_freq_i[reg].pxs_uhz;
+ return 0;
+
+ default:
+ return -EINVAL;
+ }
+}
+
+static int rpr0521_write_samp_freq_common(struct rpr0521_data *data,
+ enum iio_chan_type chan_type,
+ int val, int val2)
+{
+ int i;
+
+ /*
+ * Ignore channel
+ * both pxs and als are setup only to same freq because of simplicity
+ */
+ switch (val) {
+ case 0:
+ i = 0;
+ break;
+
+ case 2:
+ if (val2 != 500000)
+ return -EINVAL;
+
+ i = 11;
+ break;
+
+ case 10:
+ i = 6;
+ break;
+
+ default:
+ return -EINVAL;
+ }
+
+ return regmap_update_bits(data->regmap,
+ RPR0521_REG_MODE_CTRL,
+ RPR0521_MODE_MEAS_TIME_MASK,
+ i);
+}
+
+static int rpr0521_read_ps_offset(struct rpr0521_data *data, int *offset)
+{
+ int ret;
+ __le16 buffer;
+
+ ret = regmap_bulk_read(data->regmap,
+ RPR0521_REG_PS_OFFSET_LSB, &buffer, sizeof(buffer));
+
+ if (ret < 0) {
+ dev_err(&data->client->dev, "Failed to read PS OFFSET register\n");
+ return ret;
+ }
+ *offset = le16_to_cpu(buffer);
+
+ return ret;
+}
+
+static int rpr0521_write_ps_offset(struct rpr0521_data *data, int offset)
+{
+ int ret;
+ __le16 buffer;
+
+ buffer = cpu_to_le16(offset & 0x3ff);
+ ret = regmap_raw_write(data->regmap,
+ RPR0521_REG_PS_OFFSET_LSB, &buffer, sizeof(buffer));
+
+ if (ret < 0) {
+ dev_err(&data->client->dev, "Failed to write PS OFFSET register\n");
+ return ret;
+ }
+
+ return ret;
+}
+
static int rpr0521_read_raw(struct iio_dev *indio_dev,
struct iio_chan_spec const *chan, int *val,
int *val2, long mask)
@@ -339,7 +492,7 @@ static int rpr0521_read_raw(struct iio_dev *indio_dev,
ret = regmap_bulk_read(data->regmap,
rpr0521_data_reg[chan->address].address,
- &raw_data, 2);
+ &raw_data, sizeof(raw_data));
if (ret < 0) {
rpr0521_set_power_state(data, false, device_mask);
mutex_unlock(&data->lock);
@@ -354,6 +507,7 @@ static int rpr0521_read_raw(struct iio_dev *indio_dev,
*val = le16_to_cpu(raw_data);
return IIO_VAL_INT;
+
case IIO_CHAN_INFO_SCALE:
mutex_lock(&data->lock);
ret = rpr0521_get_gain(data, chan->address, val, val2);
@@ -362,6 +516,25 @@ static int rpr0521_read_raw(struct iio_dev *indio_dev,
return ret;
return IIO_VAL_INT_PLUS_MICRO;
+
+ case IIO_CHAN_INFO_SAMP_FREQ:
+ mutex_lock(&data->lock);
+ ret = rpr0521_read_samp_freq(data, chan->type, val, val2);
+ mutex_unlock(&data->lock);
+ if (ret < 0)
+ return ret;
+
+ return IIO_VAL_INT_PLUS_MICRO;
+
+ case IIO_CHAN_INFO_OFFSET:
+ mutex_lock(&data->lock);
+ ret = rpr0521_read_ps_offset(data, val);
+ mutex_unlock(&data->lock);
+ if (ret < 0)
+ return ret;
+
+ return IIO_VAL_INT;
+
default:
return -EINVAL;
}
@@ -381,6 +554,22 @@ static int rpr0521_write_raw(struct iio_dev *indio_dev,
mutex_unlock(&data->lock);
return ret;
+
+ case IIO_CHAN_INFO_SAMP_FREQ:
+ mutex_lock(&data->lock);
+ ret = rpr0521_write_samp_freq_common(data, chan->type,
+ val, val2);
+ mutex_unlock(&data->lock);
+
+ return ret;
+
+ case IIO_CHAN_INFO_OFFSET:
+ mutex_lock(&data->lock);
+ ret = rpr0521_write_ps_offset(data, val);
+ mutex_unlock(&data->lock);
+
+ return ret;
+
default:
return -EINVAL;
}
@@ -419,12 +608,14 @@ static int rpr0521_init(struct rpr0521_data *data)
return ret;
}
+#ifndef CONFIG_PM
ret = rpr0521_als_enable(data, RPR0521_MODE_ALS_ENABLE);
if (ret < 0)
return ret;
ret = rpr0521_pxs_enable(data, RPR0521_MODE_PXS_ENABLE);
if (ret < 0)
return ret;
+#endif
return 0;
}
@@ -510,13 +701,26 @@ static int rpr0521_probe(struct i2c_client *client,
ret = pm_runtime_set_active(&client->dev);
if (ret < 0)
- return ret;
+ goto err_poweroff;
pm_runtime_enable(&client->dev);
pm_runtime_set_autosuspend_delay(&client->dev, RPR0521_SLEEP_DELAY_MS);
pm_runtime_use_autosuspend(&client->dev);
- return iio_device_register(indio_dev);
+ ret = iio_device_register(indio_dev);
+ if (ret)
+ goto err_pm_disable;
+
+ return 0;
+
+err_pm_disable:
+ pm_runtime_disable(&client->dev);
+ pm_runtime_set_suspended(&client->dev);
+ pm_runtime_put_noidle(&client->dev);
+err_poweroff:
+ rpr0521_poweroff(data);
+
+ return ret;
}
static int rpr0521_remove(struct i2c_client *client)
@@ -541,9 +745,16 @@ static int rpr0521_runtime_suspend(struct device *dev)
struct rpr0521_data *data = iio_priv(indio_dev);
int ret;
- /* disable channels and sets {als,pxs}_dev_en to false */
mutex_lock(&data->lock);
+ /* If measurements are enabled, enable them on resume */
+ if (!data->als_need_dis)
+ data->als_ps_need_en = data->als_dev_en;
+ if (!data->pxs_need_dis)
+ data->pxs_ps_need_en = data->pxs_dev_en;
+
+ /* disable channels and sets {als,pxs}_dev_en to false */
ret = rpr0521_poweroff(data);
+ regcache_mark_dirty(data->regmap);
mutex_unlock(&data->lock);
return ret;
@@ -555,6 +766,7 @@ static int rpr0521_runtime_resume(struct device *dev)
struct rpr0521_data *data = iio_priv(indio_dev);
int ret;
+ regcache_sync(data->regmap);
if (data->als_ps_need_en) {
ret = rpr0521_als_enable(data, RPR0521_MODE_ALS_ENABLE);
if (ret < 0)
@@ -568,6 +780,7 @@ static int rpr0521_runtime_resume(struct device *dev)
return ret;
data->pxs_ps_need_en = false;
}
+ msleep(100); //wait for first measurement result
return 0;
}
diff --git a/drivers/iio/light/tsl2583.c b/drivers/iio/light/tsl2583.c
index a78b6025c465..1679181d2bdd 100644
--- a/drivers/iio/light/tsl2583.c
+++ b/drivers/iio/light/tsl2583.c
@@ -3,7 +3,7 @@
* within the TAOS tsl258x family of devices (tsl2580, tsl2581, tsl2583).
*
* Copyright (c) 2011, TAOS Corporation.
- * Copyright (c) 2016 Brian Masney <masneyb@onstation.org>
+ * Copyright (c) 2016-2017 Brian Masney <masneyb@onstation.org>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -27,6 +27,7 @@
#include <linux/module.h>
#include <linux/iio/iio.h>
#include <linux/iio/sysfs.h>
+#include <linux/pm_runtime.h>
/* Device Registers and Masks */
#define TSL2583_CNTRL 0x00
@@ -64,6 +65,8 @@
#define TSL2583_CHIP_ID 0x90
#define TSL2583_CHIP_ID_MASK 0xf0
+#define TSL2583_POWER_OFF_DELAY_MS 2000
+
/* Per-device data */
struct tsl2583_als_info {
u16 als_ch0;
@@ -108,7 +111,6 @@ struct tsl2583_chip {
struct tsl2583_settings als_settings;
int als_time_scale;
int als_saturation;
- bool suspended;
};
struct gainadj {
@@ -460,8 +462,6 @@ static int tsl2583_chip_init_and_power_on(struct iio_dev *indio_dev)
if (ret < 0)
return ret;
- chip->suspended = false;
-
return ret;
}
@@ -513,11 +513,6 @@ static ssize_t in_illuminance_calibrate_store(struct device *dev,
mutex_lock(&chip->als_mutex);
- if (chip->suspended) {
- ret = -EBUSY;
- goto done;
- }
-
ret = tsl2583_als_calibrate(indio_dev);
if (ret < 0)
goto done;
@@ -645,20 +640,36 @@ static const struct iio_chan_spec tsl2583_channels[] = {
},
};
+static int tsl2583_set_pm_runtime_busy(struct tsl2583_chip *chip, bool on)
+{
+ int ret;
+
+ if (on) {
+ ret = pm_runtime_get_sync(&chip->client->dev);
+ if (ret < 0)
+ pm_runtime_put_noidle(&chip->client->dev);
+ } else {
+ pm_runtime_mark_last_busy(&chip->client->dev);
+ ret = pm_runtime_put_autosuspend(&chip->client->dev);
+ }
+
+ return ret;
+}
+
static int tsl2583_read_raw(struct iio_dev *indio_dev,
struct iio_chan_spec const *chan,
int *val, int *val2, long mask)
{
struct tsl2583_chip *chip = iio_priv(indio_dev);
- int ret = -EINVAL;
+ int ret, pm_ret;
- mutex_lock(&chip->als_mutex);
+ ret = tsl2583_set_pm_runtime_busy(chip, true);
+ if (ret < 0)
+ return ret;
- if (chip->suspended) {
- ret = -EBUSY;
- goto read_done;
- }
+ mutex_lock(&chip->als_mutex);
+ ret = -EINVAL;
switch (mask) {
case IIO_CHAN_INFO_RAW:
if (chan->type == IIO_LIGHT) {
@@ -719,6 +730,18 @@ static int tsl2583_read_raw(struct iio_dev *indio_dev,
read_done:
mutex_unlock(&chip->als_mutex);
+ if (ret < 0)
+ return ret;
+
+ /*
+ * Preserve the ret variable if the call to
+ * tsl2583_set_pm_runtime_busy() is successful so the reading
+ * (if applicable) is returned to user space.
+ */
+ pm_ret = tsl2583_set_pm_runtime_busy(chip, false);
+ if (pm_ret < 0)
+ return pm_ret;
+
return ret;
}
@@ -727,15 +750,15 @@ static int tsl2583_write_raw(struct iio_dev *indio_dev,
int val, int val2, long mask)
{
struct tsl2583_chip *chip = iio_priv(indio_dev);
- int ret = -EINVAL;
+ int ret;
- mutex_lock(&chip->als_mutex);
+ ret = tsl2583_set_pm_runtime_busy(chip, true);
+ if (ret < 0)
+ return ret;
- if (chip->suspended) {
- ret = -EBUSY;
- goto write_done;
- }
+ mutex_lock(&chip->als_mutex);
+ ret = -EINVAL;
switch (mask) {
case IIO_CHAN_INFO_CALIBBIAS:
if (chan->type == IIO_LIGHT) {
@@ -767,9 +790,15 @@ static int tsl2583_write_raw(struct iio_dev *indio_dev,
break;
}
-write_done:
mutex_unlock(&chip->als_mutex);
+ if (ret < 0)
+ return ret;
+
+ ret = tsl2583_set_pm_runtime_busy(chip, false);
+ if (ret < 0)
+ return ret;
+
return ret;
}
@@ -803,7 +832,6 @@ static int tsl2583_probe(struct i2c_client *clientp,
i2c_set_clientdata(clientp, indio_dev);
mutex_init(&chip->als_mutex);
- chip->suspended = true;
ret = i2c_smbus_read_byte_data(clientp,
TSL2583_CMD_REG | TSL2583_CHIPID);
@@ -826,6 +854,11 @@ static int tsl2583_probe(struct i2c_client *clientp,
indio_dev->modes = INDIO_DIRECT_MODE;
indio_dev->name = chip->client->name;
+ pm_runtime_enable(&clientp->dev);
+ pm_runtime_set_autosuspend_delay(&clientp->dev,
+ TSL2583_POWER_OFF_DELAY_MS);
+ pm_runtime_use_autosuspend(&clientp->dev);
+
ret = devm_iio_device_register(indio_dev->dev.parent, indio_dev);
if (ret) {
dev_err(&clientp->dev, "%s: iio registration failed\n",
@@ -836,16 +869,25 @@ static int tsl2583_probe(struct i2c_client *clientp,
/* Load up the V2 defaults (these are hard coded defaults for now) */
tsl2583_defaults(chip);
- /* Make sure the chip is on */
- ret = tsl2583_chip_init_and_power_on(indio_dev);
- if (ret < 0)
- return ret;
-
dev_info(&clientp->dev, "Light sensor found.\n");
return 0;
}
+static int tsl2583_remove(struct i2c_client *client)
+{
+ struct iio_dev *indio_dev = i2c_get_clientdata(client);
+ struct tsl2583_chip *chip = iio_priv(indio_dev);
+
+ iio_device_unregister(indio_dev);
+
+ pm_runtime_disable(&client->dev);
+ pm_runtime_set_suspended(&client->dev);
+ pm_runtime_put_noidle(&client->dev);
+
+ return tsl2583_set_power_state(chip, TSL2583_CNTL_PWR_OFF);
+}
+
static int __maybe_unused tsl2583_suspend(struct device *dev)
{
struct iio_dev *indio_dev = i2c_get_clientdata(to_i2c_client(dev));
@@ -855,7 +897,6 @@ static int __maybe_unused tsl2583_suspend(struct device *dev)
mutex_lock(&chip->als_mutex);
ret = tsl2583_set_power_state(chip, TSL2583_CNTL_PWR_OFF);
- chip->suspended = true;
mutex_unlock(&chip->als_mutex);
@@ -877,7 +918,11 @@ static int __maybe_unused tsl2583_resume(struct device *dev)
return ret;
}
-static SIMPLE_DEV_PM_OPS(tsl2583_pm_ops, tsl2583_suspend, tsl2583_resume);
+static const struct dev_pm_ops tsl2583_pm_ops = {
+ SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend,
+ pm_runtime_force_resume)
+ SET_RUNTIME_PM_OPS(tsl2583_suspend, tsl2583_resume, NULL)
+};
static struct i2c_device_id tsl2583_idtable[] = {
{ "tsl2580", 0 },
@@ -904,6 +949,7 @@ static struct i2c_driver tsl2583_driver = {
},
.id_table = tsl2583_idtable,
.probe = tsl2583_probe,
+ .remove = tsl2583_remove,
};
module_i2c_driver(tsl2583_driver);
diff --git a/drivers/iio/magnetometer/st_magn_spi.c b/drivers/iio/magnetometer/st_magn_spi.c
index 6325e7dc8e03..f3cb4dc05391 100644
--- a/drivers/iio/magnetometer/st_magn_spi.c
+++ b/drivers/iio/magnetometer/st_magn_spi.c
@@ -48,8 +48,6 @@ static int st_magn_spi_remove(struct spi_device *spi)
}
static const struct spi_device_id st_magn_id_table[] = {
- { LSM303DLHC_MAGN_DEV_NAME },
- { LSM303DLM_MAGN_DEV_NAME },
{ LIS3MDL_MAGN_DEV_NAME },
{ LSM303AGR_MAGN_DEV_NAME },
{},
diff --git a/drivers/iio/orientation/hid-sensor-rotation.c b/drivers/iio/orientation/hid-sensor-rotation.c
index a97e802ca523..e9fa86c87db5 100644
--- a/drivers/iio/orientation/hid-sensor-rotation.c
+++ b/drivers/iio/orientation/hid-sensor-rotation.c
@@ -31,6 +31,10 @@ struct dev_rot_state {
struct hid_sensor_common common_attributes;
struct hid_sensor_hub_attribute_info quaternion;
u32 sampled_vals[4];
+ int scale_pre_decml;
+ int scale_post_decml;
+ int scale_precision;
+ int value_offset;
};
/* Channel definitions */
@@ -41,6 +45,8 @@ static const struct iio_chan_spec dev_rot_channels[] = {
.channel2 = IIO_MOD_QUATERNION,
.info_mask_separate = BIT(IIO_CHAN_INFO_RAW),
.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SAMP_FREQ) |
+ BIT(IIO_CHAN_INFO_OFFSET) |
+ BIT(IIO_CHAN_INFO_SCALE) |
BIT(IIO_CHAN_INFO_HYSTERESIS)
}
};
@@ -80,6 +86,15 @@ static int dev_rot_read_raw(struct iio_dev *indio_dev,
} else
ret_type = -EINVAL;
break;
+ case IIO_CHAN_INFO_SCALE:
+ vals[0] = rot_state->scale_pre_decml;
+ vals[1] = rot_state->scale_post_decml;
+ return rot_state->scale_precision;
+
+ case IIO_CHAN_INFO_OFFSET:
+ *vals = rot_state->value_offset;
+ return IIO_VAL_INT;
+
case IIO_CHAN_INFO_SAMP_FREQ:
ret_type = hid_sensor_read_samp_freq_value(
&rot_state->common_attributes, &vals[0], &vals[1]);
@@ -199,6 +214,11 @@ static int dev_rot_parse_report(struct platform_device *pdev,
dev_dbg(&pdev->dev, "dev_rot: attrib size %d\n",
st->quaternion.size);
+ st->scale_precision = hid_sensor_format_scale(
+ hsdev->usage,
+ &st->quaternion,
+ &st->scale_pre_decml, &st->scale_post_decml);
+
/* Set Sensitivity field ids, when there is no individual modifier */
if (st->common_attributes.sensitivity.index < 0) {
sensor_hub_input_get_attribute_info(hsdev,
@@ -218,7 +238,7 @@ static int dev_rot_parse_report(struct platform_device *pdev,
static int hid_dev_rot_probe(struct platform_device *pdev)
{
int ret;
- static char *name = "dev_rotation";
+ static char *name;
struct iio_dev *indio_dev;
struct dev_rot_state *rot_state;
struct hid_sensor_hub_device *hsdev = pdev->dev.platform_data;
@@ -234,8 +254,21 @@ static int hid_dev_rot_probe(struct platform_device *pdev)
rot_state->common_attributes.hsdev = hsdev;
rot_state->common_attributes.pdev = pdev;
- ret = hid_sensor_parse_common_attributes(hsdev,
- HID_USAGE_SENSOR_DEVICE_ORIENTATION,
+ switch (hsdev->usage) {
+ case HID_USAGE_SENSOR_DEVICE_ORIENTATION:
+ name = "dev_rotation";
+ break;
+ case HID_USAGE_SENSOR_RELATIVE_ORIENTATION:
+ name = "relative_orientation";
+ break;
+ case HID_USAGE_SENSOR_GEOMAGNETIC_ORIENTATION:
+ name = "geomagnetic_orientation";
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ ret = hid_sensor_parse_common_attributes(hsdev, hsdev->usage,
&rot_state->common_attributes);
if (ret) {
dev_err(&pdev->dev, "failed to setup common attributes\n");
@@ -252,8 +285,7 @@ static int hid_dev_rot_probe(struct platform_device *pdev)
ret = dev_rot_parse_report(pdev, hsdev,
(struct iio_chan_spec *)indio_dev->channels,
- HID_USAGE_SENSOR_DEVICE_ORIENTATION,
- rot_state);
+ hsdev->usage, rot_state);
if (ret) {
dev_err(&pdev->dev, "failed to setup attributes\n");
return ret;
@@ -288,8 +320,7 @@ static int hid_dev_rot_probe(struct platform_device *pdev)
rot_state->callbacks.send_event = dev_rot_proc_event;
rot_state->callbacks.capture_sample = dev_rot_capture_sample;
rot_state->callbacks.pdev = pdev;
- ret = sensor_hub_register_callback(hsdev,
- HID_USAGE_SENSOR_DEVICE_ORIENTATION,
+ ret = sensor_hub_register_callback(hsdev, hsdev->usage,
&rot_state->callbacks);
if (ret) {
dev_err(&pdev->dev, "callback reg failed\n");
@@ -314,7 +345,7 @@ static int hid_dev_rot_remove(struct platform_device *pdev)
struct iio_dev *indio_dev = platform_get_drvdata(pdev);
struct dev_rot_state *rot_state = iio_priv(indio_dev);
- sensor_hub_remove_callback(hsdev, HID_USAGE_SENSOR_DEVICE_ORIENTATION);
+ sensor_hub_remove_callback(hsdev, hsdev->usage);
iio_device_unregister(indio_dev);
hid_sensor_remove_trigger(&rot_state->common_attributes);
iio_triggered_buffer_cleanup(indio_dev);
@@ -327,6 +358,14 @@ static const struct platform_device_id hid_dev_rot_ids[] = {
/* Format: HID-SENSOR-usage_id_in_hex_lowercase */
.name = "HID-SENSOR-20008a",
},
+ {
+ /* Relative orientation(AG) sensor */
+ .name = "HID-SENSOR-20008e",
+ },
+ {
+ /* Geomagnetic orientation(AM) sensor */
+ .name = "HID-SENSOR-2000c1",
+ },
{ /* sentinel */ }
};
MODULE_DEVICE_TABLE(platform, hid_dev_rot_ids);
diff --git a/drivers/iio/pressure/Kconfig b/drivers/iio/pressure/Kconfig
index 5d16b252ab6b..eaa7cfcb4c2a 100644
--- a/drivers/iio/pressure/Kconfig
+++ b/drivers/iio/pressure/Kconfig
@@ -23,7 +23,7 @@ config BMP280
select BMP280_SPI if (SPI_MASTER)
help
Say yes here to build support for Bosch Sensortec BMP180 and BMP280
- pressure and temperature sensors. Also supports the BE280 with
+ pressure and temperature sensors. Also supports the BME280 with
an additional humidity sensor channel.
To compile this driver as a module, choose M here: the core module
diff --git a/drivers/iio/pressure/st_pressure_core.c b/drivers/iio/pressure/st_pressure_core.c
index fd0edca0e656..aa61ec15c139 100644
--- a/drivers/iio/pressure/st_pressure_core.c
+++ b/drivers/iio/pressure/st_pressure_core.c
@@ -568,6 +568,8 @@ static const struct iio_trigger_ops st_press_trigger_ops = {
int st_press_common_probe(struct iio_dev *indio_dev)
{
struct st_sensor_data *press_data = iio_priv(indio_dev);
+ struct st_sensors_platform_data *pdata =
+ (struct st_sensors_platform_data *)press_data->dev->platform_data;
int irq = press_data->get_irq_data_ready(indio_dev);
int err;
@@ -603,10 +605,8 @@ int st_press_common_probe(struct iio_dev *indio_dev)
press_data->odr = press_data->sensor_settings->odr.odr_avl[0].hz;
/* Some devices don't support a data ready pin. */
- if (!press_data->dev->platform_data &&
- press_data->sensor_settings->drdy_irq.addr)
- press_data->dev->platform_data =
- (struct st_sensors_platform_data *)&default_press_pdata;
+ if (!pdata && press_data->sensor_settings->drdy_irq.addr)
+ pdata = (struct st_sensors_platform_data *)&default_press_pdata;
err = st_sensors_init_sensor(indio_dev, press_data->dev->platform_data);
if (err < 0)
diff --git a/drivers/iio/pressure/zpa2326.c b/drivers/iio/pressure/zpa2326.c
index e58a0ad07477..c92a95f9f52c 100644
--- a/drivers/iio/pressure/zpa2326.c
+++ b/drivers/iio/pressure/zpa2326.c
@@ -867,12 +867,13 @@ static int zpa2326_wait_oneshot_completion(const struct iio_dev *indio_dev,
{
int ret;
unsigned int val;
+ long timeout;
zpa2326_dbg(indio_dev, "waiting for one shot completion interrupt");
- ret = wait_for_completion_interruptible_timeout(
+ timeout = wait_for_completion_interruptible_timeout(
&private->data_ready, ZPA2326_CONVERSION_JIFFIES);
- if (ret > 0)
+ if (timeout > 0)
/*
* Interrupt handler completed before timeout: return operation
* status.
@@ -882,13 +883,16 @@ static int zpa2326_wait_oneshot_completion(const struct iio_dev *indio_dev,
/* Clear all interrupts just to be sure. */
regmap_read(private->regmap, ZPA2326_INT_SOURCE_REG, &val);
- if (!ret)
+ if (!timeout) {
/* Timed out. */
+ zpa2326_warn(indio_dev, "no one shot interrupt occurred (%ld)",
+ timeout);
ret = -ETIME;
-
- if (ret != -ERESTARTSYS)
- zpa2326_warn(indio_dev, "no one shot interrupt occurred (%d)",
- ret);
+ } else if (timeout < 0) {
+ zpa2326_warn(indio_dev,
+ "wait for one shot interrupt cancelled");
+ ret = -ERESTARTSYS;
+ }
return ret;
}
diff --git a/drivers/iio/proximity/as3935.c b/drivers/iio/proximity/as3935.c
index ddf9bee89f77..0eeff29b61be 100644
--- a/drivers/iio/proximity/as3935.c
+++ b/drivers/iio/proximity/as3935.c
@@ -40,9 +40,9 @@
#define AS3935_AFE_PWR_BIT BIT(0)
#define AS3935_INT 0x03
-#define AS3935_INT_MASK 0x07
+#define AS3935_INT_MASK 0x0f
#define AS3935_EVENT_INT BIT(3)
-#define AS3935_NOISE_INT BIT(1)
+#define AS3935_NOISE_INT BIT(0)
#define AS3935_DATA 0x07
#define AS3935_DATA_MASK 0x3F
@@ -176,13 +176,13 @@ static int as3935_read_raw(struct iio_dev *indio_dev,
if (ret)
return ret;
- if (m == IIO_CHAN_INFO_RAW)
- return IIO_VAL_INT;
-
/* storm out of range */
if (*val == AS3935_DATA_MASK)
return -EINVAL;
+ if (m == IIO_CHAN_INFO_RAW)
+ return IIO_VAL_INT;
+
if (m == IIO_CHAN_INFO_PROCESSED)
*val *= 1000;
break;
@@ -215,7 +215,7 @@ static irqreturn_t as3935_trigger_handler(int irq, void *private)
st->buffer[0] = val & AS3935_DATA_MASK;
iio_push_to_buffers_with_timestamp(indio_dev, &st->buffer,
- pf->timestamp);
+ iio_get_time_ns(indio_dev));
err_read:
iio_trigger_notify_done(indio_dev->trig);
@@ -244,7 +244,7 @@ static void as3935_event_work(struct work_struct *work)
switch (val) {
case AS3935_EVENT_INT:
- iio_trigger_poll(st->trig);
+ iio_trigger_poll_chained(st->trig);
break;
case AS3935_NOISE_INT:
dev_warn(&st->spi->dev, "noise level is too high\n");
@@ -269,8 +269,6 @@ static irqreturn_t as3935_interrupt_handler(int irq, void *private)
static void calibrate_as3935(struct as3935_state *st)
{
- mutex_lock(&st->lock);
-
/* mask disturber interrupt bit */
as3935_write(st, AS3935_INT, BIT(5));
@@ -280,8 +278,6 @@ static void calibrate_as3935(struct as3935_state *st)
mdelay(2);
as3935_write(st, AS3935_TUNE_CAP, (st->tune_cap / TUNE_CAP_DIV));
-
- mutex_unlock(&st->lock);
}
#ifdef CONFIG_PM_SLEEP
@@ -318,6 +314,8 @@ static int as3935_resume(struct device *dev)
val &= ~AS3935_AFE_PWR_BIT;
ret = as3935_write(st, AS3935_AFE_GAIN, val);
+ calibrate_as3935(st);
+
err_resume:
mutex_unlock(&st->lock);
diff --git a/drivers/iio/proximity/sx9500.c b/drivers/iio/proximity/sx9500.c
index 9ea147f1a50d..f42b3a1c75ff 100644
--- a/drivers/iio/proximity/sx9500.c
+++ b/drivers/iio/proximity/sx9500.c
@@ -878,8 +878,7 @@ static void sx9500_gpio_probe(struct i2c_client *client,
dev = &client->dev;
- data->gpiod_rst = devm_gpiod_get_index(dev, SX9500_GPIO_RESET,
- 0, GPIOD_OUT_HIGH);
+ data->gpiod_rst = devm_gpiod_get(dev, SX9500_GPIO_RESET, GPIOD_OUT_HIGH);
if (IS_ERR(data->gpiod_rst)) {
dev_warn(dev, "gpio get reset pin failed\n");
data->gpiod_rst = NULL;
diff --git a/drivers/iio/temperature/maxim_thermocouple.c b/drivers/iio/temperature/maxim_thermocouple.c
index 557214202eff..d70e2e53d6a7 100644
--- a/drivers/iio/temperature/maxim_thermocouple.c
+++ b/drivers/iio/temperature/maxim_thermocouple.c
@@ -267,6 +267,7 @@ static int maxim_thermocouple_remove(struct spi_device *spi)
static const struct spi_device_id maxim_thermocouple_id[] = {
{"max6675", MAX6675},
{"max31855", MAX31855},
+ {"max31856", MAX31855},
{},
};
MODULE_DEVICE_TABLE(spi, maxim_thermocouple_id);
diff --git a/drivers/iio/trigger/stm32-timer-trigger.c b/drivers/iio/trigger/stm32-timer-trigger.c
index 25248d644e7c..d22bc56dd9fc 100644
--- a/drivers/iio/trigger/stm32-timer-trigger.c
+++ b/drivers/iio/trigger/stm32-timer-trigger.c
@@ -14,19 +14,19 @@
#include <linux/module.h>
#include <linux/platform_device.h>
-#define MAX_TRIGGERS 6
+#define MAX_TRIGGERS 7
#define MAX_VALIDS 5
/* List the triggers created by each timer */
static const void *triggers_table[][MAX_TRIGGERS] = {
- { TIM1_TRGO, TIM1_CH1, TIM1_CH2, TIM1_CH3, TIM1_CH4,},
+ { TIM1_TRGO, TIM1_TRGO2, TIM1_CH1, TIM1_CH2, TIM1_CH3, TIM1_CH4,},
{ TIM2_TRGO, TIM2_CH1, TIM2_CH2, TIM2_CH3, TIM2_CH4,},
{ TIM3_TRGO, TIM3_CH1, TIM3_CH2, TIM3_CH3, TIM3_CH4,},
{ TIM4_TRGO, TIM4_CH1, TIM4_CH2, TIM4_CH3, TIM4_CH4,},
{ TIM5_TRGO, TIM5_CH1, TIM5_CH2, TIM5_CH3, TIM5_CH4,},
{ TIM6_TRGO,},
{ TIM7_TRGO,},
- { TIM8_TRGO, TIM8_CH1, TIM8_CH2, TIM8_CH3, TIM8_CH4,},
+ { TIM8_TRGO, TIM8_TRGO2, TIM8_CH1, TIM8_CH2, TIM8_CH3, TIM8_CH4,},
{ TIM9_TRGO, TIM9_CH1, TIM9_CH2,},
{ }, /* timer 10 */
{ }, /* timer 11 */
@@ -56,9 +56,16 @@ struct stm32_timer_trigger {
u32 max_arr;
const void *triggers;
const void *valids;
+ bool has_trgo2;
};
+static bool stm32_timer_is_trgo2_name(const char *name)
+{
+ return !!strstr(name, "trgo2");
+}
+
static int stm32_timer_start(struct stm32_timer_trigger *priv,
+ struct iio_trigger *trig,
unsigned int frequency)
{
unsigned long long prd, div;
@@ -102,7 +109,12 @@ static int stm32_timer_start(struct stm32_timer_trigger *priv,
regmap_update_bits(priv->regmap, TIM_CR1, TIM_CR1_ARPE, TIM_CR1_ARPE);
/* Force master mode to update mode */
- regmap_update_bits(priv->regmap, TIM_CR2, TIM_CR2_MMS, 0x20);
+ if (stm32_timer_is_trgo2_name(trig->name))
+ regmap_update_bits(priv->regmap, TIM_CR2, TIM_CR2_MMS2,
+ 0x2 << TIM_CR2_MMS2_SHIFT);
+ else
+ regmap_update_bits(priv->regmap, TIM_CR2, TIM_CR2_MMS,
+ 0x2 << TIM_CR2_MMS_SHIFT);
/* Make sure that registers are updated */
regmap_update_bits(priv->regmap, TIM_EGR, TIM_EGR_UG, TIM_EGR_UG);
@@ -150,7 +162,7 @@ static ssize_t stm32_tt_store_frequency(struct device *dev,
if (freq == 0) {
stm32_timer_stop(priv);
} else {
- ret = stm32_timer_start(priv, freq);
+ ret = stm32_timer_start(priv, trig, freq);
if (ret)
return ret;
}
@@ -183,6 +195,9 @@ static IIO_DEV_ATTR_SAMP_FREQ(0660,
stm32_tt_read_frequency,
stm32_tt_store_frequency);
+#define MASTER_MODE_MAX 7
+#define MASTER_MODE2_MAX 15
+
static char *master_mode_table[] = {
"reset",
"enable",
@@ -191,7 +206,16 @@ static char *master_mode_table[] = {
"OC1REF",
"OC2REF",
"OC3REF",
- "OC4REF"
+ "OC4REF",
+ /* Master mode selection 2 only */
+ "OC5REF",
+ "OC6REF",
+ "compare_pulse_OC4REF",
+ "compare_pulse_OC6REF",
+ "compare_pulse_OC4REF_r_or_OC6REF_r",
+ "compare_pulse_OC4REF_r_or_OC6REF_f",
+ "compare_pulse_OC5REF_r_or_OC6REF_r",
+ "compare_pulse_OC5REF_r_or_OC6REF_f",
};
static ssize_t stm32_tt_show_master_mode(struct device *dev,
@@ -199,10 +223,15 @@ static ssize_t stm32_tt_show_master_mode(struct device *dev,
char *buf)
{
struct stm32_timer_trigger *priv = dev_get_drvdata(dev);
+ struct iio_trigger *trig = to_iio_trigger(dev);
u32 cr2;
regmap_read(priv->regmap, TIM_CR2, &cr2);
- cr2 = (cr2 & TIM_CR2_MMS) >> TIM_CR2_MMS_SHIFT;
+
+ if (stm32_timer_is_trgo2_name(trig->name))
+ cr2 = (cr2 & TIM_CR2_MMS2) >> TIM_CR2_MMS2_SHIFT;
+ else
+ cr2 = (cr2 & TIM_CR2_MMS) >> TIM_CR2_MMS_SHIFT;
return snprintf(buf, PAGE_SIZE, "%s\n", master_mode_table[cr2]);
}
@@ -212,13 +241,25 @@ static ssize_t stm32_tt_store_master_mode(struct device *dev,
const char *buf, size_t len)
{
struct stm32_timer_trigger *priv = dev_get_drvdata(dev);
+ struct iio_trigger *trig = to_iio_trigger(dev);
+ u32 mask, shift, master_mode_max;
int i;
- for (i = 0; i < ARRAY_SIZE(master_mode_table); i++) {
+ if (stm32_timer_is_trgo2_name(trig->name)) {
+ mask = TIM_CR2_MMS2;
+ shift = TIM_CR2_MMS2_SHIFT;
+ master_mode_max = MASTER_MODE2_MAX;
+ } else {
+ mask = TIM_CR2_MMS;
+ shift = TIM_CR2_MMS_SHIFT;
+ master_mode_max = MASTER_MODE_MAX;
+ }
+
+ for (i = 0; i <= master_mode_max; i++) {
if (!strncmp(master_mode_table[i], buf,
strlen(master_mode_table[i]))) {
- regmap_update_bits(priv->regmap, TIM_CR2,
- TIM_CR2_MMS, i << TIM_CR2_MMS_SHIFT);
+ regmap_update_bits(priv->regmap, TIM_CR2, mask,
+ i << shift);
/* Make sure that registers are updated */
regmap_update_bits(priv->regmap, TIM_EGR,
TIM_EGR_UG, TIM_EGR_UG);
@@ -229,8 +270,31 @@ static ssize_t stm32_tt_store_master_mode(struct device *dev,
return -EINVAL;
}
-static IIO_CONST_ATTR(master_mode_available,
- "reset enable update compare_pulse OC1REF OC2REF OC3REF OC4REF");
+static ssize_t stm32_tt_show_master_mode_avail(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ struct iio_trigger *trig = to_iio_trigger(dev);
+ unsigned int i, master_mode_max;
+ size_t len = 0;
+
+ if (stm32_timer_is_trgo2_name(trig->name))
+ master_mode_max = MASTER_MODE2_MAX;
+ else
+ master_mode_max = MASTER_MODE_MAX;
+
+ for (i = 0; i <= master_mode_max; i++)
+ len += scnprintf(buf + len, PAGE_SIZE - len,
+ "%s ", master_mode_table[i]);
+
+ /* replace trailing space by newline */
+ buf[len - 1] = '\n';
+
+ return len;
+}
+
+static IIO_DEVICE_ATTR(master_mode_available, 0444,
+ stm32_tt_show_master_mode_avail, NULL, 0);
static IIO_DEVICE_ATTR(master_mode, 0660,
stm32_tt_show_master_mode,
@@ -240,7 +304,7 @@ static IIO_DEVICE_ATTR(master_mode, 0660,
static struct attribute *stm32_trigger_attrs[] = {
&iio_dev_attr_sampling_frequency.dev_attr.attr,
&iio_dev_attr_master_mode.dev_attr.attr,
- &iio_const_attr_master_mode_available.dev_attr.attr,
+ &iio_dev_attr_master_mode_available.dev_attr.attr,
NULL,
};
@@ -264,6 +328,12 @@ static int stm32_setup_iio_triggers(struct stm32_timer_trigger *priv)
while (cur && *cur) {
struct iio_trigger *trig;
+ bool cur_is_trgo2 = stm32_timer_is_trgo2_name(*cur);
+
+ if (cur_is_trgo2 && !priv->has_trgo2) {
+ cur++;
+ continue;
+ }
trig = devm_iio_trigger_alloc(priv->dev, "%s", *cur);
if (!trig)
@@ -277,7 +347,7 @@ static int stm32_setup_iio_triggers(struct stm32_timer_trigger *priv)
* should only be available on trgo trigger which
* is always the first in the list.
*/
- if (cur == priv->triggers)
+ if (cur == priv->triggers || cur_is_trgo2)
trig->dev.groups = stm32_trigger_attr_groups;
iio_trigger_set_drvdata(trig, priv);
@@ -347,12 +417,70 @@ static int stm32_counter_write_raw(struct iio_dev *indio_dev,
return -EINVAL;
}
+static int stm32_counter_validate_trigger(struct iio_dev *indio_dev,
+ struct iio_trigger *trig)
+{
+ struct stm32_timer_trigger *priv = iio_priv(indio_dev);
+ const char * const *cur = priv->valids;
+ unsigned int i = 0;
+
+ if (!is_stm32_timer_trigger(trig))
+ return -EINVAL;
+
+ while (cur && *cur) {
+ if (!strncmp(trig->name, *cur, strlen(trig->name))) {
+ regmap_update_bits(priv->regmap,
+ TIM_SMCR, TIM_SMCR_TS,
+ i << TIM_SMCR_TS_SHIFT);
+ return 0;
+ }
+ cur++;
+ i++;
+ }
+
+ return -EINVAL;
+}
+
static const struct iio_info stm32_trigger_info = {
.driver_module = THIS_MODULE,
+ .validate_trigger = stm32_counter_validate_trigger,
.read_raw = stm32_counter_read_raw,
.write_raw = stm32_counter_write_raw
};
+static const char *const stm32_trigger_modes[] = {
+ "trigger",
+};
+
+static int stm32_set_trigger_mode(struct iio_dev *indio_dev,
+ const struct iio_chan_spec *chan,
+ unsigned int mode)
+{
+ struct stm32_timer_trigger *priv = iio_priv(indio_dev);
+
+ regmap_update_bits(priv->regmap, TIM_SMCR, TIM_SMCR_SMS, TIM_SMCR_SMS);
+
+ return 0;
+}
+
+static int stm32_get_trigger_mode(struct iio_dev *indio_dev,
+ const struct iio_chan_spec *chan)
+{
+ struct stm32_timer_trigger *priv = iio_priv(indio_dev);
+ u32 smcr;
+
+ regmap_read(priv->regmap, TIM_SMCR, &smcr);
+
+ return smcr == TIM_SMCR_SMS ? 0 : -EINVAL;
+}
+
+static const struct iio_enum stm32_trigger_mode_enum = {
+ .items = stm32_trigger_modes,
+ .num_items = ARRAY_SIZE(stm32_trigger_modes),
+ .set = stm32_set_trigger_mode,
+ .get = stm32_get_trigger_mode
+};
+
static const char *const stm32_enable_modes[] = {
"always",
"gated",
@@ -536,6 +664,8 @@ static const struct iio_chan_spec_ext_info stm32_trigger_count_info[] = {
IIO_ENUM_AVAILABLE("quadrature_mode", &stm32_quadrature_mode_enum),
IIO_ENUM("enable_mode", IIO_SEPARATE, &stm32_enable_mode_enum),
IIO_ENUM_AVAILABLE("enable_mode", &stm32_enable_mode_enum),
+ IIO_ENUM("trigger_mode", IIO_SEPARATE, &stm32_trigger_mode_enum),
+ IIO_ENUM_AVAILABLE("trigger_mode", &stm32_trigger_mode_enum),
{}
};
@@ -560,6 +690,7 @@ static struct stm32_timer_trigger *stm32_setup_counter_device(struct device *dev
indio_dev->name = dev_name(dev);
indio_dev->dev.parent = dev;
indio_dev->info = &stm32_trigger_info;
+ indio_dev->modes = INDIO_HARDWARE_TRIGGERED;
indio_dev->num_channels = 1;
indio_dev->channels = &stm32_trigger_channel;
indio_dev->dev.of_node = dev->of_node;
@@ -584,6 +715,20 @@ bool is_stm32_timer_trigger(struct iio_trigger *trig)
}
EXPORT_SYMBOL(is_stm32_timer_trigger);
+static void stm32_timer_detect_trgo2(struct stm32_timer_trigger *priv)
+{
+ u32 val;
+
+ /*
+ * Master mode selection 2 bits can only be written and read back when
+ * timer supports it.
+ */
+ regmap_update_bits(priv->regmap, TIM_CR2, TIM_CR2_MMS2, TIM_CR2_MMS2);
+ regmap_read(priv->regmap, TIM_CR2, &val);
+ regmap_update_bits(priv->regmap, TIM_CR2, TIM_CR2_MMS2, 0);
+ priv->has_trgo2 = !!val;
+}
+
static int stm32_timer_trigger_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
@@ -614,6 +759,7 @@ static int stm32_timer_trigger_probe(struct platform_device *pdev)
priv->max_arr = ddata->max_arr;
priv->triggers = triggers_table[index];
priv->valids = valids_table[index];
+ stm32_timer_detect_trgo2(priv);
ret = stm32_setup_iio_triggers(priv);
if (ret)
diff --git a/drivers/infiniband/core/addr.c b/drivers/infiniband/core/addr.c
index 02971e239a18..ece6926fa2e6 100644
--- a/drivers/infiniband/core/addr.c
+++ b/drivers/infiniband/core/addr.c
@@ -449,12 +449,7 @@ static int addr6_resolve(struct sockaddr_in6 *src_in,
return ret;
rt = (struct rt6_info *)dst;
- if (ipv6_addr_any(&fl6.saddr)) {
- ret = ipv6_dev_get_saddr(addr->net, ip6_dst_idev(dst)->dev,
- &fl6.daddr, 0, &fl6.saddr);
- if (ret)
- goto put;
-
+ if (ipv6_addr_any(&src_in->sin6_addr)) {
src_in->sin6_family = AF_INET6;
src_in->sin6_addr = fl6.saddr;
}
@@ -471,9 +466,6 @@ static int addr6_resolve(struct sockaddr_in6 *src_in,
*pdst = dst;
return 0;
-put:
- dst_release(dst);
- return ret;
}
#else
static int addr6_resolve(struct sockaddr_in6 *src_in,
diff --git a/drivers/infiniband/core/cm.c b/drivers/infiniband/core/cm.c
index 1844770f3ae8..2b4d613a3474 100644
--- a/drivers/infiniband/core/cm.c
+++ b/drivers/infiniband/core/cm.c
@@ -1429,7 +1429,7 @@ static void cm_format_paths_from_req(struct cm_req_msg *req_msg,
primary_path->packet_life_time =
cm_req_get_primary_local_ack_timeout(req_msg);
primary_path->packet_life_time -= (primary_path->packet_life_time > 0);
- sa_path_set_service_id(primary_path, req_msg->service_id);
+ primary_path->service_id = req_msg->service_id;
if (req_msg->alt_local_lid) {
alt_path->dgid = req_msg->alt_local_gid;
@@ -1452,7 +1452,7 @@ static void cm_format_paths_from_req(struct cm_req_msg *req_msg,
alt_path->packet_life_time =
cm_req_get_alt_local_ack_timeout(req_msg);
alt_path->packet_life_time -= (alt_path->packet_life_time > 0);
- sa_path_set_service_id(alt_path, req_msg->service_id);
+ alt_path->service_id = req_msg->service_id;
}
}
diff --git a/drivers/infiniband/core/cma.c b/drivers/infiniband/core/cma.c
index 91b7a2fe5a55..31bb82d8ecd7 100644
--- a/drivers/infiniband/core/cma.c
+++ b/drivers/infiniband/core/cma.c
@@ -1140,7 +1140,7 @@ static void cma_save_ib_info(struct sockaddr *src_addr,
ib->sib_pkey = path->pkey;
ib->sib_flowinfo = path->flow_label;
memcpy(&ib->sib_addr, &path->sgid, 16);
- ib->sib_sid = sa_path_get_service_id(path);
+ ib->sib_sid = path->service_id;
ib->sib_scope_id = 0;
} else {
ib->sib_pkey = listen_ib->sib_pkey;
@@ -1274,8 +1274,7 @@ static int cma_save_req_info(const struct ib_cm_event *ib_event,
memcpy(&req->local_gid, &req_param->primary_path->sgid,
sizeof(req->local_gid));
req->has_gid = true;
- req->service_id =
- sa_path_get_service_id(req_param->primary_path);
+ req->service_id = req_param->primary_path->service_id;
req->pkey = be16_to_cpu(req_param->primary_path->pkey);
if (req->pkey != req_param->bth_pkey)
pr_warn_ratelimited("RDMA CMA: got different BTH P_Key (0x%x) and primary path P_Key (0x%x)\n"
@@ -1827,7 +1826,8 @@ static struct rdma_id_private *cma_new_conn_id(struct rdma_cm_id *listen_id,
struct rdma_route *rt;
const sa_family_t ss_family = listen_id->route.addr.src_addr.ss_family;
struct sa_path_rec *path = ib_event->param.req_rcvd.primary_path;
- const __be64 service_id = sa_path_get_service_id(path);
+ const __be64 service_id =
+ ib_event->param.req_rcvd.primary_path->service_id;
int ret;
id = rdma_create_id(listen_id->route.addr.dev_addr.net,
@@ -2345,9 +2345,8 @@ static int cma_query_ib_route(struct rdma_id_private *id_priv, int timeout_ms,
path_rec.pkey = cpu_to_be16(ib_addr_get_pkey(dev_addr));
path_rec.numb_path = 1;
path_rec.reversible = 1;
- sa_path_set_service_id(&path_rec,
- rdma_get_service_id(&id_priv->id,
- cma_dst_addr(id_priv)));
+ path_rec.service_id = rdma_get_service_id(&id_priv->id,
+ cma_dst_addr(id_priv));
comp_mask = IB_SA_PATH_REC_DGID | IB_SA_PATH_REC_SGID |
IB_SA_PATH_REC_PKEY | IB_SA_PATH_REC_NUMB_PATH |
diff --git a/drivers/infiniband/core/core_priv.h b/drivers/infiniband/core/core_priv.h
index cb7d372e4bdf..d92ab4eaa8f3 100644
--- a/drivers/infiniband/core/core_priv.h
+++ b/drivers/infiniband/core/core_priv.h
@@ -169,6 +169,16 @@ void ib_mad_cleanup(void);
int ib_sa_init(void);
void ib_sa_cleanup(void);
+int ibnl_init(void);
+void ibnl_cleanup(void);
+
+/**
+ * Check if there are any listeners to the netlink group
+ * @group: the netlink group ID
+ * Returns 0 on success or a negative for no listeners.
+ */
+int ibnl_chk_listeners(unsigned int group);
+
int ib_nl_handle_resolve_resp(struct sk_buff *skb,
struct netlink_callback *cb);
int ib_nl_handle_set_timeout(struct sk_buff *skb,
diff --git a/drivers/infiniband/core/netlink.c b/drivers/infiniband/core/netlink.c
index b784055423c8..94931c474d41 100644
--- a/drivers/infiniband/core/netlink.c
+++ b/drivers/infiniband/core/netlink.c
@@ -37,6 +37,7 @@
#include <net/net_namespace.h>
#include <net/sock.h>
#include <rdma/rdma_netlink.h>
+#include "core_priv.h"
struct ibnl_client {
struct list_head list;
@@ -55,7 +56,6 @@ int ibnl_chk_listeners(unsigned int group)
return -1;
return 0;
}
-EXPORT_SYMBOL(ibnl_chk_listeners);
int ibnl_add_client(int index, int nops,
const struct ibnl_client_cbs cb_table[])
diff --git a/drivers/infiniband/core/sa_query.c b/drivers/infiniband/core/sa_query.c
index e335b09c022e..fb7aec4047c8 100644
--- a/drivers/infiniband/core/sa_query.c
+++ b/drivers/infiniband/core/sa_query.c
@@ -194,7 +194,7 @@ static u32 tid;
.field_name = "sa_path_rec:" #field
static const struct ib_field path_rec_table[] = {
- { PATH_REC_FIELD(ib.service_id),
+ { PATH_REC_FIELD(service_id),
.offset_words = 0,
.offset_bits = 0,
.size_bits = 64 },
@@ -296,7 +296,7 @@ static const struct ib_field path_rec_table[] = {
.field_name = "sa_path_rec:" #field
static const struct ib_field opa_path_rec_table[] = {
- { OPA_PATH_REC_FIELD(opa.service_id),
+ { OPA_PATH_REC_FIELD(service_id),
.offset_words = 0,
.offset_bits = 0,
.size_bits = 64 },
@@ -774,7 +774,7 @@ static void ib_nl_set_path_rec_attrs(struct sk_buff *skb,
/* Now build the attributes */
if (comp_mask & IB_SA_PATH_REC_SERVICE_ID) {
- val64 = be64_to_cpu(sa_path_get_service_id(sa_rec));
+ val64 = be64_to_cpu(sa_rec->service_id);
nla_put(skb, RDMA_NLA_F_MANDATORY | LS_NLA_TYPE_SERVICE_ID,
sizeof(val64), &val64);
}
diff --git a/drivers/infiniband/core/umem.c b/drivers/infiniband/core/umem.c
index 3dbf811d3c51..21e60b1e2ff4 100644
--- a/drivers/infiniband/core/umem.c
+++ b/drivers/infiniband/core/umem.c
@@ -58,7 +58,7 @@ static void __ib_umem_release(struct ib_device *dev, struct ib_umem *umem, int d
for_each_sg(umem->sg_head.sgl, sg, umem->npages, i) {
page = sg_page(sg);
- if (umem->writable && dirty)
+ if (!PageDirty(page) && umem->writable && dirty)
set_page_dirty_lock(page);
put_page(page);
}
diff --git a/drivers/infiniband/core/umem_odp.c b/drivers/infiniband/core/umem_odp.c
index 0780b1afefa9..8c4ec564e495 100644
--- a/drivers/infiniband/core/umem_odp.c
+++ b/drivers/infiniband/core/umem_odp.c
@@ -321,11 +321,15 @@ int ib_umem_odp_get(struct ib_ucontext *context, struct ib_umem *umem,
struct vm_area_struct *vma;
struct hstate *h;
+ down_read(&mm->mmap_sem);
vma = find_vma(mm, ib_umem_start(umem));
- if (!vma || !is_vm_hugetlb_page(vma))
+ if (!vma || !is_vm_hugetlb_page(vma)) {
+ up_read(&mm->mmap_sem);
return -EINVAL;
+ }
h = hstate_vma(vma);
umem->page_shift = huge_page_shift(h);
+ up_read(&mm->mmap_sem);
umem->hugetlb = 1;
} else {
umem->hugetlb = 0;
diff --git a/drivers/infiniband/core/uverbs_marshall.c b/drivers/infiniband/core/uverbs_marshall.c
index 8b9587fe2303..94fd989c9060 100644
--- a/drivers/infiniband/core/uverbs_marshall.c
+++ b/drivers/infiniband/core/uverbs_marshall.c
@@ -96,11 +96,11 @@ void ib_copy_qp_attr_to_user(struct ib_uverbs_qp_attr *dst,
}
EXPORT_SYMBOL(ib_copy_qp_attr_to_user);
-void __ib_copy_path_rec_to_user(struct ib_user_path_rec *dst,
- struct sa_path_rec *src)
+static void __ib_copy_path_rec_to_user(struct ib_user_path_rec *dst,
+ struct sa_path_rec *src)
{
- memcpy(dst->dgid, src->dgid.raw, sizeof src->dgid);
- memcpy(dst->sgid, src->sgid.raw, sizeof src->sgid);
+ memcpy(dst->dgid, src->dgid.raw, sizeof(src->dgid));
+ memcpy(dst->sgid, src->sgid.raw, sizeof(src->sgid));
dst->dlid = htons(ntohl(sa_path_get_dlid(src)));
dst->slid = htons(ntohl(sa_path_get_slid(src)));
diff --git a/drivers/infiniband/hw/bnxt_re/bnxt_re.h b/drivers/infiniband/hw/bnxt_re/bnxt_re.h
index ebf7be8d4139..08772836fded 100644
--- a/drivers/infiniband/hw/bnxt_re/bnxt_re.h
+++ b/drivers/infiniband/hw/bnxt_re/bnxt_re.h
@@ -56,6 +56,10 @@
#define BNXT_RE_MAX_SRQC_COUNT (64 * 1024)
#define BNXT_RE_MAX_CQ_COUNT (64 * 1024)
+#define BNXT_RE_UD_QP_HW_STALL 0x400000
+
+#define BNXT_RE_RQ_WQE_THRESHOLD 32
+
struct bnxt_re_work {
struct work_struct work;
unsigned long event;
diff --git a/drivers/infiniband/hw/bnxt_re/ib_verbs.c b/drivers/infiniband/hw/bnxt_re/ib_verbs.c
index 7ba9e699d7ab..c7bd68311d0c 100644
--- a/drivers/infiniband/hw/bnxt_re/ib_verbs.c
+++ b/drivers/infiniband/hw/bnxt_re/ib_verbs.c
@@ -61,6 +61,48 @@
#include "ib_verbs.h"
#include <rdma/bnxt_re-abi.h>
+static int __from_ib_access_flags(int iflags)
+{
+ int qflags = 0;
+
+ if (iflags & IB_ACCESS_LOCAL_WRITE)
+ qflags |= BNXT_QPLIB_ACCESS_LOCAL_WRITE;
+ if (iflags & IB_ACCESS_REMOTE_READ)
+ qflags |= BNXT_QPLIB_ACCESS_REMOTE_READ;
+ if (iflags & IB_ACCESS_REMOTE_WRITE)
+ qflags |= BNXT_QPLIB_ACCESS_REMOTE_WRITE;
+ if (iflags & IB_ACCESS_REMOTE_ATOMIC)
+ qflags |= BNXT_QPLIB_ACCESS_REMOTE_ATOMIC;
+ if (iflags & IB_ACCESS_MW_BIND)
+ qflags |= BNXT_QPLIB_ACCESS_MW_BIND;
+ if (iflags & IB_ZERO_BASED)
+ qflags |= BNXT_QPLIB_ACCESS_ZERO_BASED;
+ if (iflags & IB_ACCESS_ON_DEMAND)
+ qflags |= BNXT_QPLIB_ACCESS_ON_DEMAND;
+ return qflags;
+};
+
+static enum ib_access_flags __to_ib_access_flags(int qflags)
+{
+ enum ib_access_flags iflags = 0;
+
+ if (qflags & BNXT_QPLIB_ACCESS_LOCAL_WRITE)
+ iflags |= IB_ACCESS_LOCAL_WRITE;
+ if (qflags & BNXT_QPLIB_ACCESS_REMOTE_WRITE)
+ iflags |= IB_ACCESS_REMOTE_WRITE;
+ if (qflags & BNXT_QPLIB_ACCESS_REMOTE_READ)
+ iflags |= IB_ACCESS_REMOTE_READ;
+ if (qflags & BNXT_QPLIB_ACCESS_REMOTE_ATOMIC)
+ iflags |= IB_ACCESS_REMOTE_ATOMIC;
+ if (qflags & BNXT_QPLIB_ACCESS_MW_BIND)
+ iflags |= IB_ACCESS_MW_BIND;
+ if (qflags & BNXT_QPLIB_ACCESS_ZERO_BASED)
+ iflags |= IB_ZERO_BASED;
+ if (qflags & BNXT_QPLIB_ACCESS_ON_DEMAND)
+ iflags |= IB_ACCESS_ON_DEMAND;
+ return iflags;
+};
+
static int bnxt_re_build_sgl(struct ib_sge *ib_sg_list,
struct bnxt_qplib_sge *sg_list, int num)
{
@@ -149,8 +191,8 @@ int bnxt_re_query_device(struct ib_device *ibdev,
ib_attr->max_total_mcast_qp_attach = 0;
ib_attr->max_ah = dev_attr->max_ah;
- ib_attr->max_fmr = dev_attr->max_fmr;
- ib_attr->max_map_per_fmr = 1; /* ? */
+ ib_attr->max_fmr = 0;
+ ib_attr->max_map_per_fmr = 0;
ib_attr->max_srq = dev_attr->max_srq;
ib_attr->max_srq_wr = dev_attr->max_srq_wqes;
@@ -410,6 +452,158 @@ enum rdma_link_layer bnxt_re_get_link_layer(struct ib_device *ibdev,
return IB_LINK_LAYER_ETHERNET;
}
+#define BNXT_RE_FENCE_PBL_SIZE DIV_ROUND_UP(BNXT_RE_FENCE_BYTES, PAGE_SIZE)
+
+static void bnxt_re_create_fence_wqe(struct bnxt_re_pd *pd)
+{
+ struct bnxt_re_fence_data *fence = &pd->fence;
+ struct ib_mr *ib_mr = &fence->mr->ib_mr;
+ struct bnxt_qplib_swqe *wqe = &fence->bind_wqe;
+
+ memset(wqe, 0, sizeof(*wqe));
+ wqe->type = BNXT_QPLIB_SWQE_TYPE_BIND_MW;
+ wqe->wr_id = BNXT_QPLIB_FENCE_WRID;
+ wqe->flags |= BNXT_QPLIB_SWQE_FLAGS_SIGNAL_COMP;
+ wqe->flags |= BNXT_QPLIB_SWQE_FLAGS_UC_FENCE;
+ wqe->bind.zero_based = false;
+ wqe->bind.parent_l_key = ib_mr->lkey;
+ wqe->bind.va = (u64)(unsigned long)fence->va;
+ wqe->bind.length = fence->size;
+ wqe->bind.access_cntl = __from_ib_access_flags(IB_ACCESS_REMOTE_READ);
+ wqe->bind.mw_type = SQ_BIND_MW_TYPE_TYPE1;
+
+ /* Save the initial rkey in fence structure for now;
+ * wqe->bind.r_key will be set at (re)bind time.
+ */
+ fence->bind_rkey = ib_inc_rkey(fence->mw->rkey);
+}
+
+static int bnxt_re_bind_fence_mw(struct bnxt_qplib_qp *qplib_qp)
+{
+ struct bnxt_re_qp *qp = container_of(qplib_qp, struct bnxt_re_qp,
+ qplib_qp);
+ struct ib_pd *ib_pd = qp->ib_qp.pd;
+ struct bnxt_re_pd *pd = container_of(ib_pd, struct bnxt_re_pd, ib_pd);
+ struct bnxt_re_fence_data *fence = &pd->fence;
+ struct bnxt_qplib_swqe *fence_wqe = &fence->bind_wqe;
+ struct bnxt_qplib_swqe wqe;
+ int rc;
+
+ memcpy(&wqe, fence_wqe, sizeof(wqe));
+ wqe.bind.r_key = fence->bind_rkey;
+ fence->bind_rkey = ib_inc_rkey(fence->bind_rkey);
+
+ dev_dbg(rdev_to_dev(qp->rdev),
+ "Posting bind fence-WQE: rkey: %#x QP: %d PD: %p\n",
+ wqe.bind.r_key, qp->qplib_qp.id, pd);
+ rc = bnxt_qplib_post_send(&qp->qplib_qp, &wqe);
+ if (rc) {
+ dev_err(rdev_to_dev(qp->rdev), "Failed to bind fence-WQE\n");
+ return rc;
+ }
+ bnxt_qplib_post_send_db(&qp->qplib_qp);
+
+ return rc;
+}
+
+static void bnxt_re_destroy_fence_mr(struct bnxt_re_pd *pd)
+{
+ struct bnxt_re_fence_data *fence = &pd->fence;
+ struct bnxt_re_dev *rdev = pd->rdev;
+ struct device *dev = &rdev->en_dev->pdev->dev;
+ struct bnxt_re_mr *mr = fence->mr;
+
+ if (fence->mw) {
+ bnxt_re_dealloc_mw(fence->mw);
+ fence->mw = NULL;
+ }
+ if (mr) {
+ if (mr->ib_mr.rkey)
+ bnxt_qplib_dereg_mrw(&rdev->qplib_res, &mr->qplib_mr,
+ true);
+ if (mr->ib_mr.lkey)
+ bnxt_qplib_free_mrw(&rdev->qplib_res, &mr->qplib_mr);
+ kfree(mr);
+ fence->mr = NULL;
+ }
+ if (fence->dma_addr) {
+ dma_unmap_single(dev, fence->dma_addr, BNXT_RE_FENCE_BYTES,
+ DMA_BIDIRECTIONAL);
+ fence->dma_addr = 0;
+ }
+}
+
+static int bnxt_re_create_fence_mr(struct bnxt_re_pd *pd)
+{
+ int mr_access_flags = IB_ACCESS_LOCAL_WRITE | IB_ACCESS_MW_BIND;
+ struct bnxt_re_fence_data *fence = &pd->fence;
+ struct bnxt_re_dev *rdev = pd->rdev;
+ struct device *dev = &rdev->en_dev->pdev->dev;
+ struct bnxt_re_mr *mr = NULL;
+ dma_addr_t dma_addr = 0;
+ struct ib_mw *mw;
+ u64 pbl_tbl;
+ int rc;
+
+ dma_addr = dma_map_single(dev, fence->va, BNXT_RE_FENCE_BYTES,
+ DMA_BIDIRECTIONAL);
+ rc = dma_mapping_error(dev, dma_addr);
+ if (rc) {
+ dev_err(rdev_to_dev(rdev), "Failed to dma-map fence-MR-mem\n");
+ rc = -EIO;
+ fence->dma_addr = 0;
+ goto fail;
+ }
+ fence->dma_addr = dma_addr;
+
+ /* Allocate a MR */
+ mr = kzalloc(sizeof(*mr), GFP_KERNEL);
+ if (!mr) {
+ rc = -ENOMEM;
+ goto fail;
+ }
+ fence->mr = mr;
+ mr->rdev = rdev;
+ mr->qplib_mr.pd = &pd->qplib_pd;
+ mr->qplib_mr.type = CMDQ_ALLOCATE_MRW_MRW_FLAGS_PMR;
+ mr->qplib_mr.flags = __from_ib_access_flags(mr_access_flags);
+ rc = bnxt_qplib_alloc_mrw(&rdev->qplib_res, &mr->qplib_mr);
+ if (rc) {
+ dev_err(rdev_to_dev(rdev), "Failed to alloc fence-HW-MR\n");
+ goto fail;
+ }
+
+ /* Register MR */
+ mr->ib_mr.lkey = mr->qplib_mr.lkey;
+ mr->qplib_mr.va = (u64)(unsigned long)fence->va;
+ mr->qplib_mr.total_size = BNXT_RE_FENCE_BYTES;
+ pbl_tbl = dma_addr;
+ rc = bnxt_qplib_reg_mr(&rdev->qplib_res, &mr->qplib_mr, &pbl_tbl,
+ BNXT_RE_FENCE_PBL_SIZE, false);
+ if (rc) {
+ dev_err(rdev_to_dev(rdev), "Failed to register fence-MR\n");
+ goto fail;
+ }
+ mr->ib_mr.rkey = mr->qplib_mr.rkey;
+
+ /* Create a fence MW only for kernel consumers */
+ mw = bnxt_re_alloc_mw(&pd->ib_pd, IB_MW_TYPE_1, NULL);
+ if (!mw) {
+ dev_err(rdev_to_dev(rdev),
+ "Failed to create fence-MW for PD: %p\n", pd);
+ rc = -EINVAL;
+ goto fail;
+ }
+ fence->mw = mw;
+
+ bnxt_re_create_fence_wqe(pd);
+ return 0;
+
+fail:
+ bnxt_re_destroy_fence_mr(pd);
+ return rc;
+}
+
/* Protection Domains */
int bnxt_re_dealloc_pd(struct ib_pd *ib_pd)
{
@@ -417,6 +611,7 @@ int bnxt_re_dealloc_pd(struct ib_pd *ib_pd)
struct bnxt_re_dev *rdev = pd->rdev;
int rc;
+ bnxt_re_destroy_fence_mr(pd);
if (ib_pd->uobject && pd->dpi.dbr) {
struct ib_ucontext *ib_uctx = ib_pd->uobject->context;
struct bnxt_re_ucontext *ucntx;
@@ -498,6 +693,10 @@ struct ib_pd *bnxt_re_alloc_pd(struct ib_device *ibdev,
}
}
+ if (!udata)
+ if (bnxt_re_create_fence_mr(pd))
+ dev_warn(rdev_to_dev(rdev),
+ "Failed to create Fence-MR\n");
return &pd->ib_pd;
dbfail:
(void)bnxt_qplib_dealloc_pd(&rdev->qplib_res, &rdev->qplib_res.pd_tbl,
@@ -849,12 +1048,16 @@ static struct bnxt_re_qp *bnxt_re_create_shadow_qp
/* Shadow QP SQ depth should be same as QP1 RQ depth */
qp->qplib_qp.sq.max_wqe = qp1_qp->rq.max_wqe;
qp->qplib_qp.sq.max_sge = 2;
+ /* Q full delta can be 1 since it is internal QP */
+ qp->qplib_qp.sq.q_full_delta = 1;
qp->qplib_qp.scq = qp1_qp->scq;
qp->qplib_qp.rcq = qp1_qp->rcq;
qp->qplib_qp.rq.max_wqe = qp1_qp->rq.max_wqe;
qp->qplib_qp.rq.max_sge = qp1_qp->rq.max_sge;
+ /* Q full delta can be 1 since it is internal QP */
+ qp->qplib_qp.rq.q_full_delta = 1;
qp->qplib_qp.mtu = qp1_qp->mtu;
@@ -917,10 +1120,6 @@ struct ib_qp *bnxt_re_create_qp(struct ib_pd *ib_pd,
qp->qplib_qp.sig_type = ((qp_init_attr->sq_sig_type ==
IB_SIGNAL_ALL_WR) ? true : false);
- entries = roundup_pow_of_two(qp_init_attr->cap.max_send_wr + 1);
- qp->qplib_qp.sq.max_wqe = min_t(u32, entries,
- dev_attr->max_qp_wqes + 1);
-
qp->qplib_qp.sq.max_sge = qp_init_attr->cap.max_send_sge;
if (qp->qplib_qp.sq.max_sge > dev_attr->max_qp_sges)
qp->qplib_qp.sq.max_sge = dev_attr->max_qp_sges;
@@ -959,6 +1158,9 @@ struct ib_qp *bnxt_re_create_qp(struct ib_pd *ib_pd,
qp->qplib_qp.rq.max_wqe = min_t(u32, entries,
dev_attr->max_qp_wqes + 1);
+ qp->qplib_qp.rq.q_full_delta = qp->qplib_qp.rq.max_wqe -
+ qp_init_attr->cap.max_recv_wr;
+
qp->qplib_qp.rq.max_sge = qp_init_attr->cap.max_recv_sge;
if (qp->qplib_qp.rq.max_sge > dev_attr->max_qp_sges)
qp->qplib_qp.rq.max_sge = dev_attr->max_qp_sges;
@@ -967,6 +1169,12 @@ struct ib_qp *bnxt_re_create_qp(struct ib_pd *ib_pd,
qp->qplib_qp.mtu = ib_mtu_enum_to_int(iboe_get_mtu(rdev->netdev->mtu));
if (qp_init_attr->qp_type == IB_QPT_GSI) {
+ /* Allocate 1 more than what's provided */
+ entries = roundup_pow_of_two(qp_init_attr->cap.max_send_wr + 1);
+ qp->qplib_qp.sq.max_wqe = min_t(u32, entries,
+ dev_attr->max_qp_wqes + 1);
+ qp->qplib_qp.sq.q_full_delta = qp->qplib_qp.sq.max_wqe -
+ qp_init_attr->cap.max_send_wr;
qp->qplib_qp.rq.max_sge = dev_attr->max_qp_sges;
if (qp->qplib_qp.rq.max_sge > dev_attr->max_qp_sges)
qp->qplib_qp.rq.max_sge = dev_attr->max_qp_sges;
@@ -1006,6 +1214,22 @@ struct ib_qp *bnxt_re_create_qp(struct ib_pd *ib_pd,
}
} else {
+ /* Allocate 128 + 1 more than what's provided */
+ entries = roundup_pow_of_two(qp_init_attr->cap.max_send_wr +
+ BNXT_QPLIB_RESERVED_QP_WRS + 1);
+ qp->qplib_qp.sq.max_wqe = min_t(u32, entries,
+ dev_attr->max_qp_wqes +
+ BNXT_QPLIB_RESERVED_QP_WRS + 1);
+ qp->qplib_qp.sq.q_full_delta = BNXT_QPLIB_RESERVED_QP_WRS + 1;
+
+ /*
+ * Reserving one slot for Phantom WQE. Application can
+ * post one extra entry in this case. But allowing this to avoid
+ * unexpected Queue full condition
+ */
+
+ qp->qplib_qp.sq.q_full_delta -= 1;
+
qp->qplib_qp.max_rd_atomic = dev_attr->max_qp_rd_atom;
qp->qplib_qp.max_dest_rd_atomic = dev_attr->max_qp_init_rd_atom;
if (udata) {
@@ -1025,6 +1249,7 @@ struct ib_qp *bnxt_re_create_qp(struct ib_pd *ib_pd,
qp->ib_qp.qp_num = qp->qplib_qp.id;
spin_lock_init(&qp->sq_lock);
+ spin_lock_init(&qp->rq_lock);
if (udata) {
struct bnxt_re_qp_resp resp;
@@ -1129,48 +1354,6 @@ static enum ib_mtu __to_ib_mtu(u32 mtu)
}
}
-static int __from_ib_access_flags(int iflags)
-{
- int qflags = 0;
-
- if (iflags & IB_ACCESS_LOCAL_WRITE)
- qflags |= BNXT_QPLIB_ACCESS_LOCAL_WRITE;
- if (iflags & IB_ACCESS_REMOTE_READ)
- qflags |= BNXT_QPLIB_ACCESS_REMOTE_READ;
- if (iflags & IB_ACCESS_REMOTE_WRITE)
- qflags |= BNXT_QPLIB_ACCESS_REMOTE_WRITE;
- if (iflags & IB_ACCESS_REMOTE_ATOMIC)
- qflags |= BNXT_QPLIB_ACCESS_REMOTE_ATOMIC;
- if (iflags & IB_ACCESS_MW_BIND)
- qflags |= BNXT_QPLIB_ACCESS_MW_BIND;
- if (iflags & IB_ZERO_BASED)
- qflags |= BNXT_QPLIB_ACCESS_ZERO_BASED;
- if (iflags & IB_ACCESS_ON_DEMAND)
- qflags |= BNXT_QPLIB_ACCESS_ON_DEMAND;
- return qflags;
-};
-
-static enum ib_access_flags __to_ib_access_flags(int qflags)
-{
- enum ib_access_flags iflags = 0;
-
- if (qflags & BNXT_QPLIB_ACCESS_LOCAL_WRITE)
- iflags |= IB_ACCESS_LOCAL_WRITE;
- if (qflags & BNXT_QPLIB_ACCESS_REMOTE_WRITE)
- iflags |= IB_ACCESS_REMOTE_WRITE;
- if (qflags & BNXT_QPLIB_ACCESS_REMOTE_READ)
- iflags |= IB_ACCESS_REMOTE_READ;
- if (qflags & BNXT_QPLIB_ACCESS_REMOTE_ATOMIC)
- iflags |= IB_ACCESS_REMOTE_ATOMIC;
- if (qflags & BNXT_QPLIB_ACCESS_MW_BIND)
- iflags |= IB_ACCESS_MW_BIND;
- if (qflags & BNXT_QPLIB_ACCESS_ZERO_BASED)
- iflags |= IB_ZERO_BASED;
- if (qflags & BNXT_QPLIB_ACCESS_ON_DEMAND)
- iflags |= IB_ACCESS_ON_DEMAND;
- return iflags;
-};
-
static int bnxt_re_modify_shadow_qp(struct bnxt_re_dev *rdev,
struct bnxt_re_qp *qp1_qp,
int qp_attr_mask)
@@ -1378,11 +1561,21 @@ int bnxt_re_modify_qp(struct ib_qp *ib_qp, struct ib_qp_attr *qp_attr,
entries = roundup_pow_of_two(qp_attr->cap.max_send_wr);
qp->qplib_qp.sq.max_wqe = min_t(u32, entries,
dev_attr->max_qp_wqes + 1);
+ qp->qplib_qp.sq.q_full_delta = qp->qplib_qp.sq.max_wqe -
+ qp_attr->cap.max_send_wr;
+ /*
+ * Reserving one slot for Phantom WQE. Some application can
+ * post one extra entry in this case. Allowing this to avoid
+ * unexpected Queue full condition
+ */
+ qp->qplib_qp.sq.q_full_delta -= 1;
qp->qplib_qp.sq.max_sge = qp_attr->cap.max_send_sge;
if (qp->qplib_qp.rq.max_wqe) {
entries = roundup_pow_of_two(qp_attr->cap.max_recv_wr);
qp->qplib_qp.rq.max_wqe =
min_t(u32, entries, dev_attr->max_qp_wqes + 1);
+ qp->qplib_qp.rq.q_full_delta = qp->qplib_qp.rq.max_wqe -
+ qp_attr->cap.max_recv_wr;
qp->qplib_qp.rq.max_sge = qp_attr->cap.max_recv_sge;
} else {
/* SRQ was used prior, just ignore the RQ caps */
@@ -1883,6 +2076,22 @@ static int bnxt_re_copy_wr_payload(struct bnxt_re_dev *rdev,
return payload_sz;
}
+static void bnxt_ud_qp_hw_stall_workaround(struct bnxt_re_qp *qp)
+{
+ if ((qp->ib_qp.qp_type == IB_QPT_UD ||
+ qp->ib_qp.qp_type == IB_QPT_GSI ||
+ qp->ib_qp.qp_type == IB_QPT_RAW_ETHERTYPE) &&
+ qp->qplib_qp.wqe_cnt == BNXT_RE_UD_QP_HW_STALL) {
+ int qp_attr_mask;
+ struct ib_qp_attr qp_attr;
+
+ qp_attr_mask = IB_QP_STATE;
+ qp_attr.qp_state = IB_QPS_RTS;
+ bnxt_re_modify_qp(&qp->ib_qp, &qp_attr, qp_attr_mask, NULL);
+ qp->qplib_qp.wqe_cnt = 0;
+ }
+}
+
static int bnxt_re_post_send_shadow_qp(struct bnxt_re_dev *rdev,
struct bnxt_re_qp *qp,
struct ib_send_wr *wr)
@@ -1928,6 +2137,7 @@ bad:
wr = wr->next;
}
bnxt_qplib_post_send_db(&qp->qplib_qp);
+ bnxt_ud_qp_hw_stall_workaround(qp);
spin_unlock_irqrestore(&qp->sq_lock, flags);
return rc;
}
@@ -2024,6 +2234,7 @@ bad:
wr = wr->next;
}
bnxt_qplib_post_send_db(&qp->qplib_qp);
+ bnxt_ud_qp_hw_stall_workaround(qp);
spin_unlock_irqrestore(&qp->sq_lock, flags);
return rc;
@@ -2071,7 +2282,10 @@ int bnxt_re_post_recv(struct ib_qp *ib_qp, struct ib_recv_wr *wr,
struct bnxt_re_qp *qp = container_of(ib_qp, struct bnxt_re_qp, ib_qp);
struct bnxt_qplib_swqe wqe;
int rc = 0, payload_sz = 0;
+ unsigned long flags;
+ u32 count = 0;
+ spin_lock_irqsave(&qp->rq_lock, flags);
while (wr) {
/* House keeping */
memset(&wqe, 0, sizeof(wqe));
@@ -2100,9 +2314,21 @@ int bnxt_re_post_recv(struct ib_qp *ib_qp, struct ib_recv_wr *wr,
*bad_wr = wr;
break;
}
+
+ /* Ring DB if the RQEs posted reaches a threshold value */
+ if (++count >= BNXT_RE_RQ_WQE_THRESHOLD) {
+ bnxt_qplib_post_recv_db(&qp->qplib_qp);
+ count = 0;
+ }
+
wr = wr->next;
}
- bnxt_qplib_post_recv_db(&qp->qplib_qp);
+
+ if (count)
+ bnxt_qplib_post_recv_db(&qp->qplib_qp);
+
+ spin_unlock_irqrestore(&qp->rq_lock, flags);
+
return rc;
}
@@ -2643,12 +2869,36 @@ static void bnxt_re_process_res_ud_wc(struct ib_wc *wc,
wc->opcode = IB_WC_RECV_RDMA_WITH_IMM;
}
+static int send_phantom_wqe(struct bnxt_re_qp *qp)
+{
+ struct bnxt_qplib_qp *lib_qp = &qp->qplib_qp;
+ unsigned long flags;
+ int rc = 0;
+
+ spin_lock_irqsave(&qp->sq_lock, flags);
+
+ rc = bnxt_re_bind_fence_mw(lib_qp);
+ if (!rc) {
+ lib_qp->sq.phantom_wqe_cnt++;
+ dev_dbg(&lib_qp->sq.hwq.pdev->dev,
+ "qp %#x sq->prod %#x sw_prod %#x phantom_wqe_cnt %d\n",
+ lib_qp->id, lib_qp->sq.hwq.prod,
+ HWQ_CMP(lib_qp->sq.hwq.prod, &lib_qp->sq.hwq),
+ lib_qp->sq.phantom_wqe_cnt);
+ }
+
+ spin_unlock_irqrestore(&qp->sq_lock, flags);
+ return rc;
+}
+
int bnxt_re_poll_cq(struct ib_cq *ib_cq, int num_entries, struct ib_wc *wc)
{
struct bnxt_re_cq *cq = container_of(ib_cq, struct bnxt_re_cq, ib_cq);
struct bnxt_re_qp *qp;
struct bnxt_qplib_cqe *cqe;
int i, ncqe, budget;
+ struct bnxt_qplib_q *sq;
+ struct bnxt_qplib_qp *lib_qp;
u32 tbl_idx;
struct bnxt_re_sqp_entries *sqp_entry = NULL;
unsigned long flags;
@@ -2661,7 +2911,21 @@ int bnxt_re_poll_cq(struct ib_cq *ib_cq, int num_entries, struct ib_wc *wc)
}
cqe = &cq->cql[0];
while (budget) {
- ncqe = bnxt_qplib_poll_cq(&cq->qplib_cq, cqe, budget);
+ lib_qp = NULL;
+ ncqe = bnxt_qplib_poll_cq(&cq->qplib_cq, cqe, budget, &lib_qp);
+ if (lib_qp) {
+ sq = &lib_qp->sq;
+ if (sq->send_phantom) {
+ qp = container_of(lib_qp,
+ struct bnxt_re_qp, qplib_qp);
+ if (send_phantom_wqe(qp) == -ENOMEM)
+ dev_err(rdev_to_dev(cq->rdev),
+ "Phantom failed! Scheduled to send again\n");
+ else
+ sq->send_phantom = false;
+ }
+ }
+
if (!ncqe)
break;
@@ -2822,6 +3086,12 @@ int bnxt_re_dereg_mr(struct ib_mr *ib_mr)
struct bnxt_re_dev *rdev = mr->rdev;
int rc;
+ rc = bnxt_qplib_free_mrw(&rdev->qplib_res, &mr->qplib_mr);
+ if (rc) {
+ dev_err(rdev_to_dev(rdev), "Dereg MR failed: %#x\n", rc);
+ return rc;
+ }
+
if (mr->npages && mr->pages) {
rc = bnxt_qplib_free_fast_reg_page_list(&rdev->qplib_res,
&mr->qplib_frpl);
@@ -2829,8 +3099,6 @@ int bnxt_re_dereg_mr(struct ib_mr *ib_mr)
mr->npages = 0;
mr->pages = NULL;
}
- rc = bnxt_qplib_free_mrw(&rdev->qplib_res, &mr->qplib_mr);
-
if (!IS_ERR_OR_NULL(mr->ib_umem))
ib_umem_release(mr->ib_umem);
@@ -2914,97 +3182,52 @@ fail:
return ERR_PTR(rc);
}
-/* Fast Memory Regions */
-struct ib_fmr *bnxt_re_alloc_fmr(struct ib_pd *ib_pd, int mr_access_flags,
- struct ib_fmr_attr *fmr_attr)
+struct ib_mw *bnxt_re_alloc_mw(struct ib_pd *ib_pd, enum ib_mw_type type,
+ struct ib_udata *udata)
{
struct bnxt_re_pd *pd = container_of(ib_pd, struct bnxt_re_pd, ib_pd);
struct bnxt_re_dev *rdev = pd->rdev;
- struct bnxt_re_fmr *fmr;
+ struct bnxt_re_mw *mw;
int rc;
- if (fmr_attr->max_pages > MAX_PBL_LVL_2_PGS ||
- fmr_attr->max_maps > rdev->dev_attr.max_map_per_fmr) {
- dev_err(rdev_to_dev(rdev), "Allocate FMR exceeded Max limit");
+ mw = kzalloc(sizeof(*mw), GFP_KERNEL);
+ if (!mw)
return ERR_PTR(-ENOMEM);
- }
- fmr = kzalloc(sizeof(*fmr), GFP_KERNEL);
- if (!fmr)
- return ERR_PTR(-ENOMEM);
-
- fmr->rdev = rdev;
- fmr->qplib_fmr.pd = &pd->qplib_pd;
- fmr->qplib_fmr.type = CMDQ_ALLOCATE_MRW_MRW_FLAGS_PMR;
+ mw->rdev = rdev;
+ mw->qplib_mw.pd = &pd->qplib_pd;
- rc = bnxt_qplib_alloc_mrw(&rdev->qplib_res, &fmr->qplib_fmr);
- if (rc)
+ mw->qplib_mw.type = (type == IB_MW_TYPE_1 ?
+ CMDQ_ALLOCATE_MRW_MRW_FLAGS_MW_TYPE1 :
+ CMDQ_ALLOCATE_MRW_MRW_FLAGS_MW_TYPE2B);
+ rc = bnxt_qplib_alloc_mrw(&rdev->qplib_res, &mw->qplib_mw);
+ if (rc) {
+ dev_err(rdev_to_dev(rdev), "Allocate MW failed!");
goto fail;
+ }
+ mw->ib_mw.rkey = mw->qplib_mw.rkey;
- fmr->qplib_fmr.flags = __from_ib_access_flags(mr_access_flags);
- fmr->ib_fmr.lkey = fmr->qplib_fmr.lkey;
- fmr->ib_fmr.rkey = fmr->ib_fmr.lkey;
+ atomic_inc(&rdev->mw_count);
+ return &mw->ib_mw;
- atomic_inc(&rdev->mr_count);
- return &fmr->ib_fmr;
fail:
- kfree(fmr);
+ kfree(mw);
return ERR_PTR(rc);
}
-int bnxt_re_map_phys_fmr(struct ib_fmr *ib_fmr, u64 *page_list, int list_len,
- u64 iova)
+int bnxt_re_dealloc_mw(struct ib_mw *ib_mw)
{
- struct bnxt_re_fmr *fmr = container_of(ib_fmr, struct bnxt_re_fmr,
- ib_fmr);
- struct bnxt_re_dev *rdev = fmr->rdev;
+ struct bnxt_re_mw *mw = container_of(ib_mw, struct bnxt_re_mw, ib_mw);
+ struct bnxt_re_dev *rdev = mw->rdev;
int rc;
- fmr->qplib_fmr.va = iova;
- fmr->qplib_fmr.total_size = list_len * PAGE_SIZE;
-
- rc = bnxt_qplib_reg_mr(&rdev->qplib_res, &fmr->qplib_fmr, page_list,
- list_len, true);
- if (rc)
- dev_err(rdev_to_dev(rdev), "Failed to map FMR for lkey = 0x%x!",
- fmr->ib_fmr.lkey);
- return rc;
-}
-
-int bnxt_re_unmap_fmr(struct list_head *fmr_list)
-{
- struct bnxt_re_dev *rdev;
- struct bnxt_re_fmr *fmr;
- struct ib_fmr *ib_fmr;
- int rc = 0;
-
- /* Validate each FMRs inside the fmr_list */
- list_for_each_entry(ib_fmr, fmr_list, list) {
- fmr = container_of(ib_fmr, struct bnxt_re_fmr, ib_fmr);
- rdev = fmr->rdev;
-
- if (rdev) {
- rc = bnxt_qplib_dereg_mrw(&rdev->qplib_res,
- &fmr->qplib_fmr, true);
- if (rc)
- break;
- }
+ rc = bnxt_qplib_free_mrw(&rdev->qplib_res, &mw->qplib_mw);
+ if (rc) {
+ dev_err(rdev_to_dev(rdev), "Free MW failed: %#x\n", rc);
+ return rc;
}
- return rc;
-}
-
-int bnxt_re_dealloc_fmr(struct ib_fmr *ib_fmr)
-{
- struct bnxt_re_fmr *fmr = container_of(ib_fmr, struct bnxt_re_fmr,
- ib_fmr);
- struct bnxt_re_dev *rdev = fmr->rdev;
- int rc;
- rc = bnxt_qplib_free_mrw(&rdev->qplib_res, &fmr->qplib_fmr);
- if (rc)
- dev_err(rdev_to_dev(rdev), "Failed to free FMR");
-
- kfree(fmr);
- atomic_dec(&rdev->mr_count);
+ kfree(mw);
+ atomic_dec(&rdev->mw_count);
return rc;
}
diff --git a/drivers/infiniband/hw/bnxt_re/ib_verbs.h b/drivers/infiniband/hw/bnxt_re/ib_verbs.h
index 5c3d71765454..6c160f6a5398 100644
--- a/drivers/infiniband/hw/bnxt_re/ib_verbs.h
+++ b/drivers/infiniband/hw/bnxt_re/ib_verbs.h
@@ -44,11 +44,23 @@ struct bnxt_re_gid_ctx {
u32 refcnt;
};
+#define BNXT_RE_FENCE_BYTES 64
+struct bnxt_re_fence_data {
+ u32 size;
+ u8 va[BNXT_RE_FENCE_BYTES];
+ dma_addr_t dma_addr;
+ struct bnxt_re_mr *mr;
+ struct ib_mw *mw;
+ struct bnxt_qplib_swqe bind_wqe;
+ u32 bind_rkey;
+};
+
struct bnxt_re_pd {
struct bnxt_re_dev *rdev;
struct ib_pd ib_pd;
struct bnxt_qplib_pd qplib_pd;
struct bnxt_qplib_dpi dpi;
+ struct bnxt_re_fence_data fence;
};
struct bnxt_re_ah {
@@ -62,6 +74,7 @@ struct bnxt_re_qp {
struct bnxt_re_dev *rdev;
struct ib_qp ib_qp;
spinlock_t sq_lock; /* protect sq */
+ spinlock_t rq_lock; /* protect rq */
struct bnxt_qplib_qp qplib_qp;
struct ib_umem *sumem;
struct ib_umem *rumem;
@@ -181,12 +194,9 @@ int bnxt_re_map_mr_sg(struct ib_mr *ib_mr, struct scatterlist *sg, int sg_nents,
struct ib_mr *bnxt_re_alloc_mr(struct ib_pd *ib_pd, enum ib_mr_type mr_type,
u32 max_num_sg);
int bnxt_re_dereg_mr(struct ib_mr *mr);
-struct ib_fmr *bnxt_re_alloc_fmr(struct ib_pd *pd, int mr_access_flags,
- struct ib_fmr_attr *fmr_attr);
-int bnxt_re_map_phys_fmr(struct ib_fmr *fmr, u64 *page_list, int list_len,
- u64 iova);
-int bnxt_re_unmap_fmr(struct list_head *fmr_list);
-int bnxt_re_dealloc_fmr(struct ib_fmr *fmr);
+struct ib_mw *bnxt_re_alloc_mw(struct ib_pd *ib_pd, enum ib_mw_type type,
+ struct ib_udata *udata);
+int bnxt_re_dealloc_mw(struct ib_mw *mw);
struct ib_mr *bnxt_re_reg_user_mr(struct ib_pd *pd, u64 start, u64 length,
u64 virt_addr, int mr_access_flags,
struct ib_udata *udata);
diff --git a/drivers/infiniband/hw/bnxt_re/main.c b/drivers/infiniband/hw/bnxt_re/main.c
index 5d355401179b..1fce5e73216b 100644
--- a/drivers/infiniband/hw/bnxt_re/main.c
+++ b/drivers/infiniband/hw/bnxt_re/main.c
@@ -507,10 +507,6 @@ static int bnxt_re_register_ib(struct bnxt_re_dev *rdev)
ibdev->dereg_mr = bnxt_re_dereg_mr;
ibdev->alloc_mr = bnxt_re_alloc_mr;
ibdev->map_mr_sg = bnxt_re_map_mr_sg;
- ibdev->alloc_fmr = bnxt_re_alloc_fmr;
- ibdev->map_phys_fmr = bnxt_re_map_phys_fmr;
- ibdev->unmap_fmr = bnxt_re_unmap_fmr;
- ibdev->dealloc_fmr = bnxt_re_dealloc_fmr;
ibdev->reg_user_mr = bnxt_re_reg_user_mr;
ibdev->alloc_ucontext = bnxt_re_alloc_ucontext;
diff --git a/drivers/infiniband/hw/bnxt_re/qplib_fp.c b/drivers/infiniband/hw/bnxt_re/qplib_fp.c
index 43d08b5e9085..f05500bcdcf1 100644
--- a/drivers/infiniband/hw/bnxt_re/qplib_fp.c
+++ b/drivers/infiniband/hw/bnxt_re/qplib_fp.c
@@ -284,7 +284,7 @@ int bnxt_qplib_create_qp1(struct bnxt_qplib_res *res, struct bnxt_qplib_qp *qp)
{
struct bnxt_qplib_rcfw *rcfw = res->rcfw;
struct cmdq_create_qp1 req;
- struct creq_create_qp1_resp *resp;
+ struct creq_create_qp1_resp resp;
struct bnxt_qplib_pbl *pbl;
struct bnxt_qplib_q *sq = &qp->sq;
struct bnxt_qplib_q *rq = &qp->rq;
@@ -394,31 +394,12 @@ int bnxt_qplib_create_qp1(struct bnxt_qplib_res *res, struct bnxt_qplib_qp *qp)
req.pd_id = cpu_to_le32(qp->pd->id);
- resp = (struct creq_create_qp1_resp *)
- bnxt_qplib_rcfw_send_message(rcfw, (void *)&req,
- NULL, 0);
- if (!resp) {
- dev_err(&res->pdev->dev, "QPLIB: FP: CREATE_QP1 send failed");
- rc = -EINVAL;
- goto fail;
- }
- if (!bnxt_qplib_rcfw_wait_for_resp(rcfw, le16_to_cpu(req.cookie))) {
- /* Cmd timed out */
- dev_err(&rcfw->pdev->dev, "QPLIB: FP: CREATE_QP1 timed out");
- rc = -ETIMEDOUT;
- goto fail;
- }
- if (resp->status ||
- le16_to_cpu(resp->cookie) != le16_to_cpu(req.cookie)) {
- dev_err(&rcfw->pdev->dev, "QPLIB: FP: CREATE_QP1 failed ");
- dev_err(&rcfw->pdev->dev,
- "QPLIB: with status 0x%x cmdq 0x%x resp 0x%x",
- resp->status, le16_to_cpu(req.cookie),
- le16_to_cpu(resp->cookie));
- rc = -EINVAL;
+ rc = bnxt_qplib_rcfw_send_message(rcfw, (void *)&req,
+ (void *)&resp, NULL, 0);
+ if (rc)
goto fail;
- }
- qp->id = le32_to_cpu(resp->xid);
+
+ qp->id = le32_to_cpu(resp.xid);
qp->cur_qp_state = CMDQ_MODIFY_QP_NEW_STATE_RESET;
sq->flush_in_progress = false;
rq->flush_in_progress = false;
@@ -442,7 +423,7 @@ int bnxt_qplib_create_qp(struct bnxt_qplib_res *res, struct bnxt_qplib_qp *qp)
struct bnxt_qplib_rcfw *rcfw = res->rcfw;
struct sq_send *hw_sq_send_hdr, **hw_sq_send_ptr;
struct cmdq_create_qp req;
- struct creq_create_qp_resp *resp;
+ struct creq_create_qp_resp resp;
struct bnxt_qplib_pbl *pbl;
struct sq_psn_search **psn_search_ptr;
unsigned long int psn_search, poff = 0;
@@ -627,31 +608,12 @@ int bnxt_qplib_create_qp(struct bnxt_qplib_res *res, struct bnxt_qplib_qp *qp)
}
req.pd_id = cpu_to_le32(qp->pd->id);
- resp = (struct creq_create_qp_resp *)
- bnxt_qplib_rcfw_send_message(rcfw, (void *)&req,
- NULL, 0);
- if (!resp) {
- dev_err(&rcfw->pdev->dev, "QPLIB: FP: CREATE_QP send failed");
- rc = -EINVAL;
- goto fail;
- }
- if (!bnxt_qplib_rcfw_wait_for_resp(rcfw, le16_to_cpu(req.cookie))) {
- /* Cmd timed out */
- dev_err(&rcfw->pdev->dev, "QPLIB: FP: CREATE_QP timed out");
- rc = -ETIMEDOUT;
- goto fail;
- }
- if (resp->status ||
- le16_to_cpu(resp->cookie) != le16_to_cpu(req.cookie)) {
- dev_err(&rcfw->pdev->dev, "QPLIB: FP: CREATE_QP failed ");
- dev_err(&rcfw->pdev->dev,
- "QPLIB: with status 0x%x cmdq 0x%x resp 0x%x",
- resp->status, le16_to_cpu(req.cookie),
- le16_to_cpu(resp->cookie));
- rc = -EINVAL;
+ rc = bnxt_qplib_rcfw_send_message(rcfw, (void *)&req,
+ (void *)&resp, NULL, 0);
+ if (rc)
goto fail;
- }
- qp->id = le32_to_cpu(resp->xid);
+
+ qp->id = le32_to_cpu(resp.xid);
qp->cur_qp_state = CMDQ_MODIFY_QP_NEW_STATE_RESET;
sq->flush_in_progress = false;
rq->flush_in_progress = false;
@@ -769,10 +731,11 @@ int bnxt_qplib_modify_qp(struct bnxt_qplib_res *res, struct bnxt_qplib_qp *qp)
{
struct bnxt_qplib_rcfw *rcfw = res->rcfw;
struct cmdq_modify_qp req;
- struct creq_modify_qp_resp *resp;
+ struct creq_modify_qp_resp resp;
u16 cmd_flags = 0, pkey;
u32 temp32[4];
u32 bmask;
+ int rc;
RCFW_CMD_PREP(req, MODIFY_QP, cmd_flags);
@@ -862,27 +825,10 @@ int bnxt_qplib_modify_qp(struct bnxt_qplib_res *res, struct bnxt_qplib_qp *qp)
req.vlan_pcp_vlan_dei_vlan_id = cpu_to_le16(qp->vlan_id);
- resp = (struct creq_modify_qp_resp *)
- bnxt_qplib_rcfw_send_message(rcfw, (void *)&req,
- NULL, 0);
- if (!resp) {
- dev_err(&rcfw->pdev->dev, "QPLIB: FP: MODIFY_QP send failed");
- return -EINVAL;
- }
- if (!bnxt_qplib_rcfw_wait_for_resp(rcfw, le16_to_cpu(req.cookie))) {
- /* Cmd timed out */
- dev_err(&rcfw->pdev->dev, "QPLIB: FP: MODIFY_QP timed out");
- return -ETIMEDOUT;
- }
- if (resp->status ||
- le16_to_cpu(resp->cookie) != le16_to_cpu(req.cookie)) {
- dev_err(&rcfw->pdev->dev, "QPLIB: FP: MODIFY_QP failed ");
- dev_err(&rcfw->pdev->dev,
- "QPLIB: with status 0x%x cmdq 0x%x resp 0x%x",
- resp->status, le16_to_cpu(req.cookie),
- le16_to_cpu(resp->cookie));
- return -EINVAL;
- }
+ rc = bnxt_qplib_rcfw_send_message(rcfw, (void *)&req,
+ (void *)&resp, NULL, 0);
+ if (rc)
+ return rc;
qp->cur_qp_state = qp->state;
return 0;
}
@@ -891,37 +837,26 @@ int bnxt_qplib_query_qp(struct bnxt_qplib_res *res, struct bnxt_qplib_qp *qp)
{
struct bnxt_qplib_rcfw *rcfw = res->rcfw;
struct cmdq_query_qp req;
- struct creq_query_qp_resp *resp;
+ struct creq_query_qp_resp resp;
+ struct bnxt_qplib_rcfw_sbuf *sbuf;
struct creq_query_qp_resp_sb *sb;
u16 cmd_flags = 0;
u32 temp32[4];
- int i;
+ int i, rc = 0;
RCFW_CMD_PREP(req, QUERY_QP, cmd_flags);
+ sbuf = bnxt_qplib_rcfw_alloc_sbuf(rcfw, sizeof(*sb));
+ if (!sbuf)
+ return -ENOMEM;
+ sb = sbuf->sb;
+
req.qp_cid = cpu_to_le32(qp->id);
req.resp_size = sizeof(*sb) / BNXT_QPLIB_CMDQE_UNITS;
- resp = (struct creq_query_qp_resp *)
- bnxt_qplib_rcfw_send_message(rcfw, (void *)&req,
- (void **)&sb, 0);
- if (!resp) {
- dev_err(&rcfw->pdev->dev, "QPLIB: FP: QUERY_QP send failed");
- return -EINVAL;
- }
- if (!bnxt_qplib_rcfw_wait_for_resp(rcfw, le16_to_cpu(req.cookie))) {
- /* Cmd timed out */
- dev_err(&rcfw->pdev->dev, "QPLIB: FP: QUERY_QP timed out");
- return -ETIMEDOUT;
- }
- if (resp->status ||
- le16_to_cpu(resp->cookie) != le16_to_cpu(req.cookie)) {
- dev_err(&rcfw->pdev->dev, "QPLIB: FP: QUERY_QP failed ");
- dev_err(&rcfw->pdev->dev,
- "QPLIB: with status 0x%x cmdq 0x%x resp 0x%x",
- resp->status, le16_to_cpu(req.cookie),
- le16_to_cpu(resp->cookie));
- return -EINVAL;
- }
+ rc = bnxt_qplib_rcfw_send_message(rcfw, (void *)&req, (void *)&resp,
+ (void *)sbuf, 0);
+ if (rc)
+ goto bail;
/* Extract the context from the side buffer */
qp->state = sb->en_sqd_async_notify_state &
CREQ_QUERY_QP_RESP_SB_STATE_MASK;
@@ -976,7 +911,9 @@ int bnxt_qplib_query_qp(struct bnxt_qplib_res *res, struct bnxt_qplib_qp *qp)
qp->dest_qpn = le32_to_cpu(sb->dest_qp_id);
memcpy(qp->smac, sb->src_mac, 6);
qp->vlan_id = le16_to_cpu(sb->vlan_pcp_vlan_dei_vlan_id);
- return 0;
+bail:
+ bnxt_qplib_rcfw_free_sbuf(rcfw, sbuf);
+ return rc;
}
static void __clean_cq(struct bnxt_qplib_cq *cq, u64 qp)
@@ -1021,34 +958,18 @@ int bnxt_qplib_destroy_qp(struct bnxt_qplib_res *res,
{
struct bnxt_qplib_rcfw *rcfw = res->rcfw;
struct cmdq_destroy_qp req;
- struct creq_destroy_qp_resp *resp;
+ struct creq_destroy_qp_resp resp;
unsigned long flags;
u16 cmd_flags = 0;
+ int rc;
RCFW_CMD_PREP(req, DESTROY_QP, cmd_flags);
req.qp_cid = cpu_to_le32(qp->id);
- resp = (struct creq_destroy_qp_resp *)
- bnxt_qplib_rcfw_send_message(rcfw, (void *)&req,
- NULL, 0);
- if (!resp) {
- dev_err(&rcfw->pdev->dev, "QPLIB: FP: DESTROY_QP send failed");
- return -EINVAL;
- }
- if (!bnxt_qplib_rcfw_wait_for_resp(rcfw, le16_to_cpu(req.cookie))) {
- /* Cmd timed out */
- dev_err(&rcfw->pdev->dev, "QPLIB: FP: DESTROY_QP timed out");
- return -ETIMEDOUT;
- }
- if (resp->status ||
- le16_to_cpu(resp->cookie) != le16_to_cpu(req.cookie)) {
- dev_err(&rcfw->pdev->dev, "QPLIB: FP: DESTROY_QP failed ");
- dev_err(&rcfw->pdev->dev,
- "QPLIB: with status 0x%x cmdq 0x%x resp 0x%x",
- resp->status, le16_to_cpu(req.cookie),
- le16_to_cpu(resp->cookie));
- return -EINVAL;
- }
+ rc = bnxt_qplib_rcfw_send_message(rcfw, (void *)&req,
+ (void *)&resp, NULL, 0);
+ if (rc)
+ return rc;
/* Must walk the associated CQs to nullified the QP ptr */
spin_lock_irqsave(&qp->scq->hwq.lock, flags);
@@ -1162,8 +1083,12 @@ int bnxt_qplib_post_send(struct bnxt_qplib_qp *qp,
rc = -EINVAL;
goto done;
}
- if (HWQ_CMP((sq->hwq.prod + 1), &sq->hwq) ==
- HWQ_CMP(sq->hwq.cons, &sq->hwq)) {
+
+ if (bnxt_qplib_queue_full(sq)) {
+ dev_err(&sq->hwq.pdev->dev,
+ "QPLIB: prod = %#x cons = %#x qdepth = %#x delta = %#x",
+ sq->hwq.prod, sq->hwq.cons, sq->hwq.max_elements,
+ sq->q_full_delta);
rc = -ENOMEM;
goto done;
}
@@ -1373,6 +1298,9 @@ int bnxt_qplib_post_send(struct bnxt_qplib_qp *qp,
}
sq->hwq.prod++;
+
+ qp->wqe_cnt++;
+
done:
return rc;
}
@@ -1411,8 +1339,7 @@ int bnxt_qplib_post_recv(struct bnxt_qplib_qp *qp,
rc = -EINVAL;
goto done;
}
- if (HWQ_CMP((rq->hwq.prod + 1), &rq->hwq) ==
- HWQ_CMP(rq->hwq.cons, &rq->hwq)) {
+ if (bnxt_qplib_queue_full(rq)) {
dev_err(&rq->hwq.pdev->dev,
"QPLIB: FP: QP (0x%x) RQ is full!", qp->id);
rc = -EINVAL;
@@ -1483,7 +1410,7 @@ int bnxt_qplib_create_cq(struct bnxt_qplib_res *res, struct bnxt_qplib_cq *cq)
{
struct bnxt_qplib_rcfw *rcfw = res->rcfw;
struct cmdq_create_cq req;
- struct creq_create_cq_resp *resp;
+ struct creq_create_cq_resp resp;
struct bnxt_qplib_pbl *pbl;
u16 cmd_flags = 0;
int rc;
@@ -1525,30 +1452,12 @@ int bnxt_qplib_create_cq(struct bnxt_qplib_res *res, struct bnxt_qplib_cq *cq)
(cq->cnq_hw_ring_id & CMDQ_CREATE_CQ_CNQ_ID_MASK) <<
CMDQ_CREATE_CQ_CNQ_ID_SFT);
- resp = (struct creq_create_cq_resp *)
- bnxt_qplib_rcfw_send_message(rcfw, (void *)&req,
- NULL, 0);
- if (!resp) {
- dev_err(&rcfw->pdev->dev, "QPLIB: FP: CREATE_CQ send failed");
- return -EINVAL;
- }
- if (!bnxt_qplib_rcfw_wait_for_resp(rcfw, le16_to_cpu(req.cookie))) {
- /* Cmd timed out */
- dev_err(&rcfw->pdev->dev, "QPLIB: FP: CREATE_CQ timed out");
- rc = -ETIMEDOUT;
- goto fail;
- }
- if (resp->status ||
- le16_to_cpu(resp->cookie) != le16_to_cpu(req.cookie)) {
- dev_err(&rcfw->pdev->dev, "QPLIB: FP: CREATE_CQ failed ");
- dev_err(&rcfw->pdev->dev,
- "QPLIB: with status 0x%x cmdq 0x%x resp 0x%x",
- resp->status, le16_to_cpu(req.cookie),
- le16_to_cpu(resp->cookie));
- rc = -EINVAL;
+ rc = bnxt_qplib_rcfw_send_message(rcfw, (void *)&req,
+ (void *)&resp, NULL, 0);
+ if (rc)
goto fail;
- }
- cq->id = le32_to_cpu(resp->xid);
+
+ cq->id = le32_to_cpu(resp.xid);
cq->dbr_base = res->dpi_tbl.dbr_bar_reg_iomem;
cq->period = BNXT_QPLIB_QUEUE_START_PERIOD;
init_waitqueue_head(&cq->waitq);
@@ -1566,33 +1475,17 @@ int bnxt_qplib_destroy_cq(struct bnxt_qplib_res *res, struct bnxt_qplib_cq *cq)
{
struct bnxt_qplib_rcfw *rcfw = res->rcfw;
struct cmdq_destroy_cq req;
- struct creq_destroy_cq_resp *resp;
+ struct creq_destroy_cq_resp resp;
u16 cmd_flags = 0;
+ int rc;
RCFW_CMD_PREP(req, DESTROY_CQ, cmd_flags);
req.cq_cid = cpu_to_le32(cq->id);
- resp = (struct creq_destroy_cq_resp *)
- bnxt_qplib_rcfw_send_message(rcfw, (void *)&req,
- NULL, 0);
- if (!resp) {
- dev_err(&rcfw->pdev->dev, "QPLIB: FP: DESTROY_CQ send failed");
- return -EINVAL;
- }
- if (!bnxt_qplib_rcfw_wait_for_resp(rcfw, le16_to_cpu(req.cookie))) {
- /* Cmd timed out */
- dev_err(&rcfw->pdev->dev, "QPLIB: FP: DESTROY_CQ timed out");
- return -ETIMEDOUT;
- }
- if (resp->status ||
- le16_to_cpu(resp->cookie) != le16_to_cpu(req.cookie)) {
- dev_err(&rcfw->pdev->dev, "QPLIB: FP: DESTROY_CQ failed ");
- dev_err(&rcfw->pdev->dev,
- "QPLIB: with status 0x%x cmdq 0x%x resp 0x%x",
- resp->status, le16_to_cpu(req.cookie),
- le16_to_cpu(resp->cookie));
- return -EINVAL;
- }
+ rc = bnxt_qplib_rcfw_send_message(rcfw, (void *)&req,
+ (void *)&resp, NULL, 0);
+ if (rc)
+ return rc;
bnxt_qplib_free_hwq(res->pdev, &cq->hwq);
return 0;
}
@@ -1664,14 +1557,113 @@ static int __flush_rq(struct bnxt_qplib_q *rq, struct bnxt_qplib_qp *qp,
return rc;
}
+/* Note: SQE is valid from sw_sq_cons up to cqe_sq_cons (exclusive)
+ * CQE is track from sw_cq_cons to max_element but valid only if VALID=1
+ */
+static int do_wa9060(struct bnxt_qplib_qp *qp, struct bnxt_qplib_cq *cq,
+ u32 cq_cons, u32 sw_sq_cons, u32 cqe_sq_cons)
+{
+ struct bnxt_qplib_q *sq = &qp->sq;
+ struct bnxt_qplib_swq *swq;
+ u32 peek_sw_cq_cons, peek_raw_cq_cons, peek_sq_cons_idx;
+ struct cq_base *peek_hwcqe, **peek_hw_cqe_ptr;
+ struct cq_req *peek_req_hwcqe;
+ struct bnxt_qplib_qp *peek_qp;
+ struct bnxt_qplib_q *peek_sq;
+ int i, rc = 0;
+
+ /* Normal mode */
+ /* Check for the psn_search marking before completing */
+ swq = &sq->swq[sw_sq_cons];
+ if (swq->psn_search &&
+ le32_to_cpu(swq->psn_search->flags_next_psn) & 0x80000000) {
+ /* Unmark */
+ swq->psn_search->flags_next_psn = cpu_to_le32
+ (le32_to_cpu(swq->psn_search->flags_next_psn)
+ & ~0x80000000);
+ dev_dbg(&cq->hwq.pdev->dev,
+ "FP: Process Req cq_cons=0x%x qp=0x%x sq cons sw=0x%x cqe=0x%x marked!\n",
+ cq_cons, qp->id, sw_sq_cons, cqe_sq_cons);
+ sq->condition = true;
+ sq->send_phantom = true;
+
+ /* TODO: Only ARM if the previous SQE is ARMALL */
+ bnxt_qplib_arm_cq(cq, DBR_DBR_TYPE_CQ_ARMALL);
+
+ rc = -EAGAIN;
+ goto out;
+ }
+ if (sq->condition) {
+ /* Peek at the completions */
+ peek_raw_cq_cons = cq->hwq.cons;
+ peek_sw_cq_cons = cq_cons;
+ i = cq->hwq.max_elements;
+ while (i--) {
+ peek_sw_cq_cons = HWQ_CMP((peek_sw_cq_cons), &cq->hwq);
+ peek_hw_cqe_ptr = (struct cq_base **)cq->hwq.pbl_ptr;
+ peek_hwcqe = &peek_hw_cqe_ptr[CQE_PG(peek_sw_cq_cons)]
+ [CQE_IDX(peek_sw_cq_cons)];
+ /* If the next hwcqe is VALID */
+ if (CQE_CMP_VALID(peek_hwcqe, peek_raw_cq_cons,
+ cq->hwq.max_elements)) {
+ /* If the next hwcqe is a REQ */
+ if ((peek_hwcqe->cqe_type_toggle &
+ CQ_BASE_CQE_TYPE_MASK) ==
+ CQ_BASE_CQE_TYPE_REQ) {
+ peek_req_hwcqe = (struct cq_req *)
+ peek_hwcqe;
+ peek_qp = (struct bnxt_qplib_qp *)
+ ((unsigned long)
+ le64_to_cpu
+ (peek_req_hwcqe->qp_handle));
+ peek_sq = &peek_qp->sq;
+ peek_sq_cons_idx = HWQ_CMP(le16_to_cpu(
+ peek_req_hwcqe->sq_cons_idx) - 1
+ , &sq->hwq);
+ /* If the hwcqe's sq's wr_id matches */
+ if (peek_sq == sq &&
+ sq->swq[peek_sq_cons_idx].wr_id ==
+ BNXT_QPLIB_FENCE_WRID) {
+ /*
+ * Unbreak only if the phantom
+ * comes back
+ */
+ dev_dbg(&cq->hwq.pdev->dev,
+ "FP:Got Phantom CQE");
+ sq->condition = false;
+ sq->single = true;
+ rc = 0;
+ goto out;
+ }
+ }
+ /* Valid but not the phantom, so keep looping */
+ } else {
+ /* Not valid yet, just exit and wait */
+ rc = -EINVAL;
+ goto out;
+ }
+ peek_sw_cq_cons++;
+ peek_raw_cq_cons++;
+ }
+ dev_err(&cq->hwq.pdev->dev,
+ "Should not have come here! cq_cons=0x%x qp=0x%x sq cons sw=0x%x hw=0x%x",
+ cq_cons, qp->id, sw_sq_cons, cqe_sq_cons);
+ rc = -EINVAL;
+ }
+out:
+ return rc;
+}
+
static int bnxt_qplib_cq_process_req(struct bnxt_qplib_cq *cq,
struct cq_req *hwcqe,
- struct bnxt_qplib_cqe **pcqe, int *budget)
+ struct bnxt_qplib_cqe **pcqe, int *budget,
+ u32 cq_cons, struct bnxt_qplib_qp **lib_qp)
{
struct bnxt_qplib_qp *qp;
struct bnxt_qplib_q *sq;
struct bnxt_qplib_cqe *cqe;
- u32 sw_cons, cqe_cons;
+ u32 sw_sq_cons, cqe_sq_cons;
+ struct bnxt_qplib_swq *swq;
int rc = 0;
qp = (struct bnxt_qplib_qp *)((unsigned long)
@@ -1683,13 +1675,13 @@ static int bnxt_qplib_cq_process_req(struct bnxt_qplib_cq *cq,
}
sq = &qp->sq;
- cqe_cons = HWQ_CMP(le16_to_cpu(hwcqe->sq_cons_idx), &sq->hwq);
- if (cqe_cons > sq->hwq.max_elements) {
+ cqe_sq_cons = HWQ_CMP(le16_to_cpu(hwcqe->sq_cons_idx), &sq->hwq);
+ if (cqe_sq_cons > sq->hwq.max_elements) {
dev_err(&cq->hwq.pdev->dev,
"QPLIB: FP: CQ Process req reported ");
dev_err(&cq->hwq.pdev->dev,
"QPLIB: sq_cons_idx 0x%x which exceeded max 0x%x",
- cqe_cons, sq->hwq.max_elements);
+ cqe_sq_cons, sq->hwq.max_elements);
return -EINVAL;
}
/* If we were in the middle of flushing the SQ, continue */
@@ -1698,53 +1690,74 @@ static int bnxt_qplib_cq_process_req(struct bnxt_qplib_cq *cq,
/* Require to walk the sq's swq to fabricate CQEs for all previously
* signaled SWQEs due to CQE aggregation from the current sq cons
- * to the cqe_cons
+ * to the cqe_sq_cons
*/
cqe = *pcqe;
while (*budget) {
- sw_cons = HWQ_CMP(sq->hwq.cons, &sq->hwq);
- if (sw_cons == cqe_cons)
+ sw_sq_cons = HWQ_CMP(sq->hwq.cons, &sq->hwq);
+ if (sw_sq_cons == cqe_sq_cons)
+ /* Done */
break;
+
+ swq = &sq->swq[sw_sq_cons];
memset(cqe, 0, sizeof(*cqe));
cqe->opcode = CQ_BASE_CQE_TYPE_REQ;
cqe->qp_handle = (u64)(unsigned long)qp;
cqe->src_qp = qp->id;
- cqe->wr_id = sq->swq[sw_cons].wr_id;
- cqe->type = sq->swq[sw_cons].type;
+ cqe->wr_id = swq->wr_id;
+ if (cqe->wr_id == BNXT_QPLIB_FENCE_WRID)
+ goto skip;
+ cqe->type = swq->type;
/* For the last CQE, check for status. For errors, regardless
* of the request being signaled or not, it must complete with
* the hwcqe error status
*/
- if (HWQ_CMP((sw_cons + 1), &sq->hwq) == cqe_cons &&
+ if (HWQ_CMP((sw_sq_cons + 1), &sq->hwq) == cqe_sq_cons &&
hwcqe->status != CQ_REQ_STATUS_OK) {
cqe->status = hwcqe->status;
dev_err(&cq->hwq.pdev->dev,
"QPLIB: FP: CQ Processed Req ");
dev_err(&cq->hwq.pdev->dev,
"QPLIB: wr_id[%d] = 0x%llx with status 0x%x",
- sw_cons, cqe->wr_id, cqe->status);
+ sw_sq_cons, cqe->wr_id, cqe->status);
cqe++;
(*budget)--;
sq->flush_in_progress = true;
/* Must block new posting of SQ and RQ */
qp->state = CMDQ_MODIFY_QP_NEW_STATE_ERR;
+ sq->condition = false;
+ sq->single = false;
} else {
- if (sq->swq[sw_cons].flags &
- SQ_SEND_FLAGS_SIGNAL_COMP) {
+ if (swq->flags & SQ_SEND_FLAGS_SIGNAL_COMP) {
+ /* Before we complete, do WA 9060 */
+ if (do_wa9060(qp, cq, cq_cons, sw_sq_cons,
+ cqe_sq_cons)) {
+ *lib_qp = qp;
+ goto out;
+ }
cqe->status = CQ_REQ_STATUS_OK;
cqe++;
(*budget)--;
}
}
+skip:
sq->hwq.cons++;
+ if (sq->single)
+ break;
}
+out:
*pcqe = cqe;
- if (!*budget && HWQ_CMP(sq->hwq.cons, &sq->hwq) != cqe_cons) {
+ if (HWQ_CMP(sq->hwq.cons, &sq->hwq) != cqe_sq_cons) {
/* Out of budget */
rc = -EAGAIN;
goto done;
}
+ /*
+ * Back to normal completion mode only after it has completed all of
+ * the WC for this CQE
+ */
+ sq->single = false;
if (!sq->flush_in_progress)
goto done;
flush:
@@ -2074,7 +2087,7 @@ static int bnxt_qplib_cq_process_cutoff(struct bnxt_qplib_cq *cq,
}
int bnxt_qplib_poll_cq(struct bnxt_qplib_cq *cq, struct bnxt_qplib_cqe *cqe,
- int num_cqes)
+ int num_cqes, struct bnxt_qplib_qp **lib_qp)
{
struct cq_base *hw_cqe, **hw_cqe_ptr;
unsigned long flags;
@@ -2099,7 +2112,8 @@ int bnxt_qplib_poll_cq(struct bnxt_qplib_cq *cq, struct bnxt_qplib_cqe *cqe,
case CQ_BASE_CQE_TYPE_REQ:
rc = bnxt_qplib_cq_process_req(cq,
(struct cq_req *)hw_cqe,
- &cqe, &budget);
+ &cqe, &budget,
+ sw_cons, lib_qp);
break;
case CQ_BASE_CQE_TYPE_RES_RC:
rc = bnxt_qplib_cq_process_res_rc(cq,
diff --git a/drivers/infiniband/hw/bnxt_re/qplib_fp.h b/drivers/infiniband/hw/bnxt_re/qplib_fp.h
index f0150f8da1e3..36b7b7db0e3f 100644
--- a/drivers/infiniband/hw/bnxt_re/qplib_fp.h
+++ b/drivers/infiniband/hw/bnxt_re/qplib_fp.h
@@ -88,6 +88,7 @@ struct bnxt_qplib_swq {
struct bnxt_qplib_swqe {
/* General */
+#define BNXT_QPLIB_FENCE_WRID 0x46454E43 /* "FENC" */
u64 wr_id;
u8 reqs_type;
u8 type;
@@ -216,9 +217,16 @@ struct bnxt_qplib_q {
struct scatterlist *sglist;
u32 nmap;
u32 max_wqe;
+ u16 q_full_delta;
u16 max_sge;
u32 psn;
bool flush_in_progress;
+ bool condition;
+ bool single;
+ bool send_phantom;
+ u32 phantom_wqe_cnt;
+ u32 phantom_cqe_cnt;
+ u32 next_cq_cons;
};
struct bnxt_qplib_qp {
@@ -242,6 +250,7 @@ struct bnxt_qplib_qp {
u8 timeout;
u8 retry_cnt;
u8 rnr_retry;
+ u64 wqe_cnt;
u32 min_rnr_timer;
u32 max_rd_atomic;
u32 max_dest_rd_atomic;
@@ -301,6 +310,13 @@ struct bnxt_qplib_qp {
(!!((hdr)->cqe_type_toggle & CQ_BASE_TOGGLE) == \
!((raw_cons) & (cp_bit)))
+static inline bool bnxt_qplib_queue_full(struct bnxt_qplib_q *qplib_q)
+{
+ return HWQ_CMP((qplib_q->hwq.prod + qplib_q->q_full_delta),
+ &qplib_q->hwq) == HWQ_CMP(qplib_q->hwq.cons,
+ &qplib_q->hwq);
+}
+
struct bnxt_qplib_cqe {
u8 status;
u8 type;
@@ -432,7 +448,7 @@ int bnxt_qplib_post_recv(struct bnxt_qplib_qp *qp,
int bnxt_qplib_create_cq(struct bnxt_qplib_res *res, struct bnxt_qplib_cq *cq);
int bnxt_qplib_destroy_cq(struct bnxt_qplib_res *res, struct bnxt_qplib_cq *cq);
int bnxt_qplib_poll_cq(struct bnxt_qplib_cq *cq, struct bnxt_qplib_cqe *cqe,
- int num);
+ int num, struct bnxt_qplib_qp **qp);
void bnxt_qplib_req_notify_cq(struct bnxt_qplib_cq *cq, u32 arm_type);
void bnxt_qplib_free_nq(struct bnxt_qplib_nq *nq);
int bnxt_qplib_alloc_nq(struct pci_dev *pdev, struct bnxt_qplib_nq *nq);
diff --git a/drivers/infiniband/hw/bnxt_re/qplib_rcfw.c b/drivers/infiniband/hw/bnxt_re/qplib_rcfw.c
index 23fb7260662b..16e42754dbec 100644
--- a/drivers/infiniband/hw/bnxt_re/qplib_rcfw.c
+++ b/drivers/infiniband/hw/bnxt_re/qplib_rcfw.c
@@ -39,72 +39,55 @@
#include <linux/spinlock.h>
#include <linux/pci.h>
#include <linux/prefetch.h>
+#include <linux/delay.h>
+
#include "roce_hsi.h"
#include "qplib_res.h"
#include "qplib_rcfw.h"
static void bnxt_qplib_service_creq(unsigned long data);
/* Hardware communication channel */
-int bnxt_qplib_rcfw_wait_for_resp(struct bnxt_qplib_rcfw *rcfw, u16 cookie)
+static int __wait_for_resp(struct bnxt_qplib_rcfw *rcfw, u16 cookie)
{
u16 cbit;
int rc;
- cookie &= RCFW_MAX_COOKIE_VALUE;
cbit = cookie % RCFW_MAX_OUTSTANDING_CMD;
- if (!test_bit(cbit, rcfw->cmdq_bitmap))
- dev_warn(&rcfw->pdev->dev,
- "QPLIB: CMD bit %d for cookie 0x%x is not set?",
- cbit, cookie);
-
rc = wait_event_timeout(rcfw->waitq,
!test_bit(cbit, rcfw->cmdq_bitmap),
msecs_to_jiffies(RCFW_CMD_WAIT_TIME_MS));
- if (!rc) {
- dev_warn(&rcfw->pdev->dev,
- "QPLIB: Bono Error: timeout %d msec, msg {0x%x}\n",
- RCFW_CMD_WAIT_TIME_MS, cookie);
- }
-
- return rc;
+ return rc ? 0 : -ETIMEDOUT;
};
-int bnxt_qplib_rcfw_block_for_resp(struct bnxt_qplib_rcfw *rcfw, u16 cookie)
+static int __block_for_resp(struct bnxt_qplib_rcfw *rcfw, u16 cookie)
{
- u32 count = -1;
+ u32 count = RCFW_BLOCKED_CMD_WAIT_COUNT;
u16 cbit;
- cookie &= RCFW_MAX_COOKIE_VALUE;
cbit = cookie % RCFW_MAX_OUTSTANDING_CMD;
if (!test_bit(cbit, rcfw->cmdq_bitmap))
goto done;
do {
+ mdelay(1); /* 1m sec */
bnxt_qplib_service_creq((unsigned long)rcfw);
} while (test_bit(cbit, rcfw->cmdq_bitmap) && --count);
done:
- return count;
+ return count ? 0 : -ETIMEDOUT;
};
-void *bnxt_qplib_rcfw_send_message(struct bnxt_qplib_rcfw *rcfw,
- struct cmdq_base *req, void **crsbe,
- u8 is_block)
+static int __send_message(struct bnxt_qplib_rcfw *rcfw, struct cmdq_base *req,
+ struct creq_base *resp, void *sb, u8 is_block)
{
- struct bnxt_qplib_crsq *crsq = &rcfw->crsq;
struct bnxt_qplib_cmdqe *cmdqe, **cmdq_ptr;
struct bnxt_qplib_hwq *cmdq = &rcfw->cmdq;
- struct bnxt_qplib_hwq *crsb = &rcfw->crsb;
- struct bnxt_qplib_crsqe *crsqe = NULL;
- struct bnxt_qplib_crsbe **crsb_ptr;
+ struct bnxt_qplib_crsq *crsqe;
u32 sw_prod, cmdq_prod;
- u8 retry_cnt = 0xFF;
- dma_addr_t dma_addr;
unsigned long flags;
u32 size, opcode;
u16 cookie, cbit;
int pg, idx;
u8 *preq;
-retry:
opcode = req->opcode;
if (!test_bit(FIRMWARE_INITIALIZED_FLAG, &rcfw->flags) &&
(opcode != CMDQ_BASE_OPCODE_QUERY_FUNC &&
@@ -112,63 +95,50 @@ retry:
dev_err(&rcfw->pdev->dev,
"QPLIB: RCFW not initialized, reject opcode 0x%x",
opcode);
- return NULL;
+ return -EINVAL;
}
if (test_bit(FIRMWARE_INITIALIZED_FLAG, &rcfw->flags) &&
opcode == CMDQ_BASE_OPCODE_INITIALIZE_FW) {
dev_err(&rcfw->pdev->dev, "QPLIB: RCFW already initialized!");
- return NULL;
+ return -EINVAL;
}
/* Cmdq are in 16-byte units, each request can consume 1 or more
* cmdqe
*/
spin_lock_irqsave(&cmdq->lock, flags);
- if (req->cmd_size > cmdq->max_elements -
- ((HWQ_CMP(cmdq->prod, cmdq) - HWQ_CMP(cmdq->cons, cmdq)) &
- (cmdq->max_elements - 1))) {
+ if (req->cmd_size >= HWQ_FREE_SLOTS(cmdq)) {
dev_err(&rcfw->pdev->dev, "QPLIB: RCFW: CMDQ is full!");
spin_unlock_irqrestore(&cmdq->lock, flags);
-
- if (!retry_cnt--)
- return NULL;
- goto retry;
+ return -EAGAIN;
}
- retry_cnt = 0xFF;
- cookie = atomic_inc_return(&rcfw->seq_num) & RCFW_MAX_COOKIE_VALUE;
+ cookie = rcfw->seq_num & RCFW_MAX_COOKIE_VALUE;
cbit = cookie % RCFW_MAX_OUTSTANDING_CMD;
if (is_block)
cookie |= RCFW_CMD_IS_BLOCKING;
+
+ set_bit(cbit, rcfw->cmdq_bitmap);
req->cookie = cpu_to_le16(cookie);
- if (test_and_set_bit(cbit, rcfw->cmdq_bitmap)) {
- dev_err(&rcfw->pdev->dev,
- "QPLIB: RCFW MAX outstanding cmd reached!");
- atomic_dec(&rcfw->seq_num);
+ crsqe = &rcfw->crsqe_tbl[cbit];
+ if (crsqe->resp) {
spin_unlock_irqrestore(&cmdq->lock, flags);
-
- if (!retry_cnt--)
- return NULL;
- goto retry;
+ return -EBUSY;
}
- /* Reserve a resp buffer slot if requested */
- if (req->resp_size && crsbe) {
- spin_lock(&crsb->lock);
- sw_prod = HWQ_CMP(crsb->prod, crsb);
- crsb_ptr = (struct bnxt_qplib_crsbe **)crsb->pbl_ptr;
- *crsbe = (void *)&crsb_ptr[get_crsb_pg(sw_prod)]
- [get_crsb_idx(sw_prod)];
- bnxt_qplib_crsb_dma_next(crsb->pbl_dma_ptr, sw_prod, &dma_addr);
- req->resp_addr = cpu_to_le64(dma_addr);
- crsb->prod++;
- spin_unlock(&crsb->lock);
-
- req->resp_size = (sizeof(struct bnxt_qplib_crsbe) +
- BNXT_QPLIB_CMDQE_UNITS - 1) /
- BNXT_QPLIB_CMDQE_UNITS;
+ memset(resp, 0, sizeof(*resp));
+ crsqe->resp = (struct creq_qp_event *)resp;
+ crsqe->resp->cookie = req->cookie;
+ crsqe->req_size = req->cmd_size;
+ if (req->resp_size && sb) {
+ struct bnxt_qplib_rcfw_sbuf *sbuf = sb;
+
+ req->resp_addr = cpu_to_le64(sbuf->dma_addr);
+ req->resp_size = (sbuf->size + BNXT_QPLIB_CMDQE_UNITS - 1) /
+ BNXT_QPLIB_CMDQE_UNITS;
}
+
cmdq_ptr = (struct bnxt_qplib_cmdqe **)cmdq->pbl_ptr;
preq = (u8 *)req;
size = req->cmd_size * BNXT_QPLIB_CMDQE_UNITS;
@@ -190,23 +160,24 @@ retry:
preq += min_t(u32, size, sizeof(*cmdqe));
size -= min_t(u32, size, sizeof(*cmdqe));
cmdq->prod++;
+ rcfw->seq_num++;
} while (size > 0);
+ rcfw->seq_num++;
+
cmdq_prod = cmdq->prod;
if (rcfw->flags & FIRMWARE_FIRST_FLAG) {
- /* The very first doorbell write is required to set this flag
- * which prompts the FW to reset its internal pointers
+ /* The very first doorbell write
+ * is required to set this flag
+ * which prompts the FW to reset
+ * its internal pointers
*/
cmdq_prod |= FIRMWARE_FIRST_FLAG;
rcfw->flags &= ~FIRMWARE_FIRST_FLAG;
}
- sw_prod = HWQ_CMP(crsq->prod, crsq);
- crsqe = &crsq->crsq[sw_prod];
- memset(crsqe, 0, sizeof(*crsqe));
- crsq->prod++;
- crsqe->req_size = req->cmd_size;
/* ring CMDQ DB */
+ wmb();
writel(cmdq_prod, rcfw->cmdq_bar_reg_iomem +
rcfw->cmdq_bar_reg_prod_off);
writel(RCFW_CMDQ_TRIG_VAL, rcfw->cmdq_bar_reg_iomem +
@@ -214,9 +185,56 @@ retry:
done:
spin_unlock_irqrestore(&cmdq->lock, flags);
/* Return the CREQ response pointer */
- return crsqe ? &crsqe->qp_event : NULL;
+ return 0;
}
+int bnxt_qplib_rcfw_send_message(struct bnxt_qplib_rcfw *rcfw,
+ struct cmdq_base *req,
+ struct creq_base *resp,
+ void *sb, u8 is_block)
+{
+ struct creq_qp_event *evnt = (struct creq_qp_event *)resp;
+ u16 cookie;
+ u8 opcode, retry_cnt = 0xFF;
+ int rc = 0;
+
+ do {
+ opcode = req->opcode;
+ rc = __send_message(rcfw, req, resp, sb, is_block);
+ cookie = le16_to_cpu(req->cookie) & RCFW_MAX_COOKIE_VALUE;
+ if (!rc)
+ break;
+
+ if (!retry_cnt || (rc != -EAGAIN && rc != -EBUSY)) {
+ /* send failed */
+ dev_err(&rcfw->pdev->dev, "QPLIB: cmdq[%#x]=%#x send failed",
+ cookie, opcode);
+ return rc;
+ }
+ is_block ? mdelay(1) : usleep_range(500, 1000);
+
+ } while (retry_cnt--);
+
+ if (is_block)
+ rc = __block_for_resp(rcfw, cookie);
+ else
+ rc = __wait_for_resp(rcfw, cookie);
+ if (rc) {
+ /* timed out */
+ dev_err(&rcfw->pdev->dev, "QPLIB: cmdq[%#x]=%#x timedout (%d)msec",
+ cookie, opcode, RCFW_CMD_WAIT_TIME_MS);
+ return rc;
+ }
+
+ if (evnt->status) {
+ /* failed with status */
+ dev_err(&rcfw->pdev->dev, "QPLIB: cmdq[%#x]=%#x status %#x",
+ cookie, opcode, evnt->status);
+ rc = -EFAULT;
+ }
+
+ return rc;
+}
/* Completions */
static int bnxt_qplib_process_func_event(struct bnxt_qplib_rcfw *rcfw,
struct creq_func_event *func_event)
@@ -260,12 +278,12 @@ static int bnxt_qplib_process_func_event(struct bnxt_qplib_rcfw *rcfw,
static int bnxt_qplib_process_qp_event(struct bnxt_qplib_rcfw *rcfw,
struct creq_qp_event *qp_event)
{
- struct bnxt_qplib_crsq *crsq = &rcfw->crsq;
struct bnxt_qplib_hwq *cmdq = &rcfw->cmdq;
- struct bnxt_qplib_crsqe *crsqe;
- u16 cbit, cookie, blocked = 0;
+ struct bnxt_qplib_crsq *crsqe;
unsigned long flags;
- u32 sw_cons;
+ u16 cbit, blocked = 0;
+ u16 cookie;
+ __le16 mcookie;
switch (qp_event->event) {
case CREQ_QP_EVENT_EVENT_QP_ERROR_NOTIFICATION:
@@ -275,24 +293,31 @@ static int bnxt_qplib_process_qp_event(struct bnxt_qplib_rcfw *rcfw,
default:
/* Command Response */
spin_lock_irqsave(&cmdq->lock, flags);
- sw_cons = HWQ_CMP(crsq->cons, crsq);
- crsqe = &crsq->crsq[sw_cons];
- crsq->cons++;
- memcpy(&crsqe->qp_event, qp_event, sizeof(crsqe->qp_event));
-
- cookie = le16_to_cpu(crsqe->qp_event.cookie);
+ cookie = le16_to_cpu(qp_event->cookie);
+ mcookie = qp_event->cookie;
blocked = cookie & RCFW_CMD_IS_BLOCKING;
cookie &= RCFW_MAX_COOKIE_VALUE;
cbit = cookie % RCFW_MAX_OUTSTANDING_CMD;
+ crsqe = &rcfw->crsqe_tbl[cbit];
+ if (crsqe->resp &&
+ crsqe->resp->cookie == mcookie) {
+ memcpy(crsqe->resp, qp_event, sizeof(*qp_event));
+ crsqe->resp = NULL;
+ } else {
+ dev_err(&rcfw->pdev->dev,
+ "QPLIB: CMD %s resp->cookie = %#x, evnt->cookie = %#x",
+ crsqe->resp ? "mismatch" : "collision",
+ crsqe->resp ? crsqe->resp->cookie : 0, mcookie);
+ }
if (!test_and_clear_bit(cbit, rcfw->cmdq_bitmap))
dev_warn(&rcfw->pdev->dev,
"QPLIB: CMD bit %d was not requested", cbit);
-
cmdq->cons += crsqe->req_size;
- spin_unlock_irqrestore(&cmdq->lock, flags);
+ crsqe->req_size = 0;
+
if (!blocked)
wake_up(&rcfw->waitq);
- break;
+ spin_unlock_irqrestore(&cmdq->lock, flags);
}
return 0;
}
@@ -305,12 +330,12 @@ static void bnxt_qplib_service_creq(unsigned long data)
struct creq_base *creqe, **creq_ptr;
u32 sw_cons, raw_cons;
unsigned long flags;
- u32 type;
+ u32 type, budget = CREQ_ENTRY_POLL_BUDGET;
- /* Service the CREQ until empty */
+ /* Service the CREQ until budget is over */
spin_lock_irqsave(&creq->lock, flags);
raw_cons = creq->cons;
- while (1) {
+ while (budget > 0) {
sw_cons = HWQ_CMP(raw_cons, creq);
creq_ptr = (struct creq_base **)creq->pbl_ptr;
creqe = &creq_ptr[get_creq_pg(sw_cons)][get_creq_idx(sw_cons)];
@@ -320,15 +345,9 @@ static void bnxt_qplib_service_creq(unsigned long data)
type = creqe->type & CREQ_BASE_TYPE_MASK;
switch (type) {
case CREQ_BASE_TYPE_QP_EVENT:
- if (!bnxt_qplib_process_qp_event
- (rcfw, (struct creq_qp_event *)creqe))
- rcfw->creq_qp_event_processed++;
- else {
- dev_warn(&rcfw->pdev->dev, "QPLIB: crsqe with");
- dev_warn(&rcfw->pdev->dev,
- "QPLIB: type = 0x%x not handled",
- type);
- }
+ bnxt_qplib_process_qp_event
+ (rcfw, (struct creq_qp_event *)creqe);
+ rcfw->creq_qp_event_processed++;
break;
case CREQ_BASE_TYPE_FUNC_EVENT:
if (!bnxt_qplib_process_func_event
@@ -346,7 +365,9 @@ static void bnxt_qplib_service_creq(unsigned long data)
break;
}
raw_cons++;
+ budget--;
}
+
if (creq->cons != raw_cons) {
creq->cons = raw_cons;
CREQ_DB_REARM(rcfw->creq_bar_reg_iomem, raw_cons,
@@ -375,23 +396,16 @@ static irqreturn_t bnxt_qplib_creq_irq(int irq, void *dev_instance)
/* RCFW */
int bnxt_qplib_deinit_rcfw(struct bnxt_qplib_rcfw *rcfw)
{
- struct creq_deinitialize_fw_resp *resp;
struct cmdq_deinitialize_fw req;
+ struct creq_deinitialize_fw_resp resp;
u16 cmd_flags = 0;
+ int rc;
RCFW_CMD_PREP(req, DEINITIALIZE_FW, cmd_flags);
- resp = (struct creq_deinitialize_fw_resp *)
- bnxt_qplib_rcfw_send_message(rcfw, (void *)&req,
- NULL, 0);
- if (!resp)
- return -EINVAL;
-
- if (!bnxt_qplib_rcfw_wait_for_resp(rcfw, le16_to_cpu(req.cookie)))
- return -ETIMEDOUT;
-
- if (resp->status ||
- le16_to_cpu(resp->cookie) != le16_to_cpu(req.cookie))
- return -EFAULT;
+ rc = bnxt_qplib_rcfw_send_message(rcfw, (void *)&req, (void *)&resp,
+ NULL, 0);
+ if (rc)
+ return rc;
clear_bit(FIRMWARE_INITIALIZED_FLAG, &rcfw->flags);
return 0;
@@ -417,9 +431,10 @@ static int __get_pbl_pg_idx(struct bnxt_qplib_pbl *pbl)
int bnxt_qplib_init_rcfw(struct bnxt_qplib_rcfw *rcfw,
struct bnxt_qplib_ctx *ctx, int is_virtfn)
{
- struct creq_initialize_fw_resp *resp;
struct cmdq_initialize_fw req;
+ struct creq_initialize_fw_resp resp;
u16 cmd_flags = 0, level;
+ int rc;
RCFW_CMD_PREP(req, INITIALIZE_FW, cmd_flags);
@@ -482,37 +497,19 @@ int bnxt_qplib_init_rcfw(struct bnxt_qplib_rcfw *rcfw,
skip_ctx_setup:
req.stat_ctx_id = cpu_to_le32(ctx->stats.fw_id);
- resp = (struct creq_initialize_fw_resp *)
- bnxt_qplib_rcfw_send_message(rcfw, (void *)&req,
- NULL, 0);
- if (!resp) {
- dev_err(&rcfw->pdev->dev,
- "QPLIB: RCFW: INITIALIZE_FW send failed");
- return -EINVAL;
- }
- if (!bnxt_qplib_rcfw_wait_for_resp(rcfw, le16_to_cpu(req.cookie))) {
- /* Cmd timed out */
- dev_err(&rcfw->pdev->dev,
- "QPLIB: RCFW: INITIALIZE_FW timed out");
- return -ETIMEDOUT;
- }
- if (resp->status ||
- le16_to_cpu(resp->cookie) != le16_to_cpu(req.cookie)) {
- dev_err(&rcfw->pdev->dev,
- "QPLIB: RCFW: INITIALIZE_FW failed");
- return -EINVAL;
- }
+ rc = bnxt_qplib_rcfw_send_message(rcfw, (void *)&req, (void *)&resp,
+ NULL, 0);
+ if (rc)
+ return rc;
set_bit(FIRMWARE_INITIALIZED_FLAG, &rcfw->flags);
return 0;
}
void bnxt_qplib_free_rcfw_channel(struct bnxt_qplib_rcfw *rcfw)
{
- bnxt_qplib_free_hwq(rcfw->pdev, &rcfw->crsb);
- kfree(rcfw->crsq.crsq);
+ kfree(rcfw->crsqe_tbl);
bnxt_qplib_free_hwq(rcfw->pdev, &rcfw->cmdq);
bnxt_qplib_free_hwq(rcfw->pdev, &rcfw->creq);
-
rcfw->pdev = NULL;
}
@@ -539,21 +536,11 @@ int bnxt_qplib_alloc_rcfw_channel(struct pci_dev *pdev,
goto fail;
}
- rcfw->crsq.max_elements = rcfw->cmdq.max_elements;
- rcfw->crsq.crsq = kcalloc(rcfw->crsq.max_elements,
- sizeof(*rcfw->crsq.crsq), GFP_KERNEL);
- if (!rcfw->crsq.crsq)
+ rcfw->crsqe_tbl = kcalloc(rcfw->cmdq.max_elements,
+ sizeof(*rcfw->crsqe_tbl), GFP_KERNEL);
+ if (!rcfw->crsqe_tbl)
goto fail;
- rcfw->crsb.max_elements = BNXT_QPLIB_CRSBE_MAX_CNT;
- if (bnxt_qplib_alloc_init_hwq(rcfw->pdev, &rcfw->crsb, NULL, 0,
- &rcfw->crsb.max_elements,
- BNXT_QPLIB_CRSBE_UNITS, 0, PAGE_SIZE,
- HWQ_TYPE_CTX)) {
- dev_err(&rcfw->pdev->dev,
- "QPLIB: HW channel CRSB allocation failed");
- goto fail;
- }
return 0;
fail:
@@ -606,7 +593,7 @@ int bnxt_qplib_enable_rcfw_channel(struct pci_dev *pdev,
int rc;
/* General */
- atomic_set(&rcfw->seq_num, 0);
+ rcfw->seq_num = 0;
rcfw->flags = FIRMWARE_FIRST_FLAG;
bmap_size = BITS_TO_LONGS(RCFW_MAX_OUTSTANDING_CMD *
sizeof(unsigned long));
@@ -636,10 +623,6 @@ int bnxt_qplib_enable_rcfw_channel(struct pci_dev *pdev,
rcfw->cmdq_bar_reg_trig_off = RCFW_COMM_TRIG_OFFSET;
- /* CRSQ */
- rcfw->crsq.prod = 0;
- rcfw->crsq.cons = 0;
-
/* CREQ */
rcfw->creq_bar_reg = RCFW_COMM_CONS_PCI_BAR_REGION;
res_base = pci_resource_start(pdev, rcfw->creq_bar_reg);
@@ -692,3 +675,34 @@ int bnxt_qplib_enable_rcfw_channel(struct pci_dev *pdev,
__iowrite32_copy(rcfw->cmdq_bar_reg_iomem, &init, sizeof(init) / 4);
return 0;
}
+
+struct bnxt_qplib_rcfw_sbuf *bnxt_qplib_rcfw_alloc_sbuf(
+ struct bnxt_qplib_rcfw *rcfw,
+ u32 size)
+{
+ struct bnxt_qplib_rcfw_sbuf *sbuf;
+
+ sbuf = kzalloc(sizeof(*sbuf), GFP_ATOMIC);
+ if (!sbuf)
+ return NULL;
+
+ sbuf->size = size;
+ sbuf->sb = dma_zalloc_coherent(&rcfw->pdev->dev, sbuf->size,
+ &sbuf->dma_addr, GFP_ATOMIC);
+ if (!sbuf->sb)
+ goto bail;
+
+ return sbuf;
+bail:
+ kfree(sbuf);
+ return NULL;
+}
+
+void bnxt_qplib_rcfw_free_sbuf(struct bnxt_qplib_rcfw *rcfw,
+ struct bnxt_qplib_rcfw_sbuf *sbuf)
+{
+ if (sbuf->sb)
+ dma_free_coherent(&rcfw->pdev->dev, sbuf->size,
+ sbuf->sb, sbuf->dma_addr);
+ kfree(sbuf);
+}
diff --git a/drivers/infiniband/hw/bnxt_re/qplib_rcfw.h b/drivers/infiniband/hw/bnxt_re/qplib_rcfw.h
index d3567d75bf58..09ce121770cd 100644
--- a/drivers/infiniband/hw/bnxt_re/qplib_rcfw.h
+++ b/drivers/infiniband/hw/bnxt_re/qplib_rcfw.h
@@ -73,6 +73,7 @@
#define RCFW_MAX_OUTSTANDING_CMD BNXT_QPLIB_CMDQE_MAX_CNT
#define RCFW_MAX_COOKIE_VALUE 0x7FFF
#define RCFW_CMD_IS_BLOCKING 0x8000
+#define RCFW_BLOCKED_CMD_WAIT_COUNT 0x4E20
/* Cmdq contains a fix number of a 16-Byte slots */
struct bnxt_qplib_cmdqe {
@@ -94,32 +95,6 @@ struct bnxt_qplib_crsbe {
u8 data[1024];
};
-/* CRSQ SB */
-#define BNXT_QPLIB_CRSBE_MAX_CNT 4
-#define BNXT_QPLIB_CRSBE_UNITS sizeof(struct bnxt_qplib_crsbe)
-#define BNXT_QPLIB_CRSBE_CNT_PER_PG (PAGE_SIZE / BNXT_QPLIB_CRSBE_UNITS)
-
-#define MAX_CRSB_IDX (BNXT_QPLIB_CRSBE_MAX_CNT - 1)
-#define MAX_CRSB_IDX_PER_PG (BNXT_QPLIB_CRSBE_CNT_PER_PG - 1)
-
-static inline u32 get_crsb_pg(u32 val)
-{
- return (val & ~MAX_CRSB_IDX_PER_PG) / BNXT_QPLIB_CRSBE_CNT_PER_PG;
-}
-
-static inline u32 get_crsb_idx(u32 val)
-{
- return val & MAX_CRSB_IDX_PER_PG;
-}
-
-static inline void bnxt_qplib_crsb_dma_next(dma_addr_t *pg_map_arr,
- u32 prod, dma_addr_t *dma_addr)
-{
- *dma_addr = pg_map_arr[(prod) / BNXT_QPLIB_CRSBE_CNT_PER_PG];
- *dma_addr += ((prod) % BNXT_QPLIB_CRSBE_CNT_PER_PG) *
- BNXT_QPLIB_CRSBE_UNITS;
-}
-
/* CREQ */
/* Allocate 1 per QP for async error notification for now */
#define BNXT_QPLIB_CREQE_MAX_CNT (64 * 1024)
@@ -158,17 +133,19 @@ static inline u32 get_creq_idx(u32 val)
#define CREQ_DB(db, raw_cons, cp_bit) \
writel(CREQ_DB_CP_FLAGS | ((raw_cons) & ((cp_bit) - 1)), db)
+#define CREQ_ENTRY_POLL_BUDGET 0x100
+
/* HWQ */
-struct bnxt_qplib_crsqe {
- struct creq_qp_event qp_event;
+
+struct bnxt_qplib_crsq {
+ struct creq_qp_event *resp;
u32 req_size;
};
-struct bnxt_qplib_crsq {
- struct bnxt_qplib_crsqe *crsq;
- u32 prod;
- u32 cons;
- u32 max_elements;
+struct bnxt_qplib_rcfw_sbuf {
+ void *sb;
+ dma_addr_t dma_addr;
+ u32 size;
};
/* RCFW Communication Channels */
@@ -185,7 +162,7 @@ struct bnxt_qplib_rcfw {
wait_queue_head_t waitq;
int (*aeq_handler)(struct bnxt_qplib_rcfw *,
struct creq_func_event *);
- atomic_t seq_num;
+ u32 seq_num;
/* Bar region info */
void __iomem *cmdq_bar_reg_iomem;
@@ -203,8 +180,7 @@ struct bnxt_qplib_rcfw {
/* Actual Cmd and Resp Queues */
struct bnxt_qplib_hwq cmdq;
- struct bnxt_qplib_crsq crsq;
- struct bnxt_qplib_hwq crsb;
+ struct bnxt_qplib_crsq *crsqe_tbl;
};
void bnxt_qplib_free_rcfw_channel(struct bnxt_qplib_rcfw *rcfw);
@@ -219,11 +195,14 @@ int bnxt_qplib_enable_rcfw_channel(struct pci_dev *pdev,
(struct bnxt_qplib_rcfw *,
struct creq_func_event *));
-int bnxt_qplib_rcfw_block_for_resp(struct bnxt_qplib_rcfw *rcfw, u16 cookie);
-int bnxt_qplib_rcfw_wait_for_resp(struct bnxt_qplib_rcfw *rcfw, u16 cookie);
-void *bnxt_qplib_rcfw_send_message(struct bnxt_qplib_rcfw *rcfw,
- struct cmdq_base *req, void **crsbe,
- u8 is_block);
+struct bnxt_qplib_rcfw_sbuf *bnxt_qplib_rcfw_alloc_sbuf(
+ struct bnxt_qplib_rcfw *rcfw,
+ u32 size);
+void bnxt_qplib_rcfw_free_sbuf(struct bnxt_qplib_rcfw *rcfw,
+ struct bnxt_qplib_rcfw_sbuf *sbuf);
+int bnxt_qplib_rcfw_send_message(struct bnxt_qplib_rcfw *rcfw,
+ struct cmdq_base *req, struct creq_base *resp,
+ void *sbuf, u8 is_block);
int bnxt_qplib_deinit_rcfw(struct bnxt_qplib_rcfw *rcfw);
int bnxt_qplib_init_rcfw(struct bnxt_qplib_rcfw *rcfw,
diff --git a/drivers/infiniband/hw/bnxt_re/qplib_res.h b/drivers/infiniband/hw/bnxt_re/qplib_res.h
index 6277d802ca4b..2e4855509719 100644
--- a/drivers/infiniband/hw/bnxt_re/qplib_res.h
+++ b/drivers/infiniband/hw/bnxt_re/qplib_res.h
@@ -48,6 +48,10 @@ extern const struct bnxt_qplib_gid bnxt_qplib_gid_zero;
#define HWQ_CMP(idx, hwq) ((idx) & ((hwq)->max_elements - 1))
+#define HWQ_FREE_SLOTS(hwq) (hwq->max_elements - \
+ ((HWQ_CMP(hwq->prod, hwq)\
+ - HWQ_CMP(hwq->cons, hwq))\
+ & (hwq->max_elements - 1)))
enum bnxt_qplib_hwq_type {
HWQ_TYPE_CTX,
HWQ_TYPE_QUEUE,
diff --git a/drivers/infiniband/hw/bnxt_re/qplib_sp.c b/drivers/infiniband/hw/bnxt_re/qplib_sp.c
index 7b31eccedf11..fde18cf0e406 100644
--- a/drivers/infiniband/hw/bnxt_re/qplib_sp.c
+++ b/drivers/infiniband/hw/bnxt_re/qplib_sp.c
@@ -55,37 +55,30 @@ int bnxt_qplib_get_dev_attr(struct bnxt_qplib_rcfw *rcfw,
struct bnxt_qplib_dev_attr *attr)
{
struct cmdq_query_func req;
- struct creq_query_func_resp *resp;
+ struct creq_query_func_resp resp;
+ struct bnxt_qplib_rcfw_sbuf *sbuf;
struct creq_query_func_resp_sb *sb;
u16 cmd_flags = 0;
u32 temp;
u8 *tqm_alloc;
- int i;
+ int i, rc = 0;
RCFW_CMD_PREP(req, QUERY_FUNC, cmd_flags);
- req.resp_size = sizeof(*sb) / BNXT_QPLIB_CMDQE_UNITS;
- resp = (struct creq_query_func_resp *)
- bnxt_qplib_rcfw_send_message(rcfw, (void *)&req, (void **)&sb,
- 0);
- if (!resp) {
- dev_err(&rcfw->pdev->dev, "QPLIB: SP: QUERY_FUNC send failed");
- return -EINVAL;
- }
- if (!bnxt_qplib_rcfw_wait_for_resp(rcfw, le16_to_cpu(req.cookie))) {
- /* Cmd timed out */
- dev_err(&rcfw->pdev->dev, "QPLIB: SP: QUERY_FUNC timed out");
- return -ETIMEDOUT;
- }
- if (resp->status ||
- le16_to_cpu(resp->cookie) != le16_to_cpu(req.cookie)) {
- dev_err(&rcfw->pdev->dev, "QPLIB: SP: QUERY_FUNC failed ");
+ sbuf = bnxt_qplib_rcfw_alloc_sbuf(rcfw, sizeof(*sb));
+ if (!sbuf) {
dev_err(&rcfw->pdev->dev,
- "QPLIB: with status 0x%x cmdq 0x%x resp 0x%x",
- resp->status, le16_to_cpu(req.cookie),
- le16_to_cpu(resp->cookie));
- return -EINVAL;
+ "QPLIB: SP: QUERY_FUNC alloc side buffer failed");
+ return -ENOMEM;
}
+
+ sb = sbuf->sb;
+ req.resp_size = sizeof(*sb) / BNXT_QPLIB_CMDQE_UNITS;
+ rc = bnxt_qplib_rcfw_send_message(rcfw, (void *)&req, (void *)&resp,
+ (void *)sbuf, 0);
+ if (rc)
+ goto bail;
+
/* Extract the context from the side buffer */
attr->max_qp = le32_to_cpu(sb->max_qp);
attr->max_qp_rd_atom =
@@ -95,6 +88,11 @@ int bnxt_qplib_get_dev_attr(struct bnxt_qplib_rcfw *rcfw,
sb->max_qp_init_rd_atom > BNXT_QPLIB_MAX_OUT_RD_ATOM ?
BNXT_QPLIB_MAX_OUT_RD_ATOM : sb->max_qp_init_rd_atom;
attr->max_qp_wqes = le16_to_cpu(sb->max_qp_wr);
+ /*
+ * 128 WQEs needs to be reserved for the HW (8916). Prevent
+ * reporting the max number
+ */
+ attr->max_qp_wqes -= BNXT_QPLIB_RESERVED_QP_WRS;
attr->max_qp_sges = sb->max_sge;
attr->max_cq = le32_to_cpu(sb->max_cq);
attr->max_cq_wqes = le32_to_cpu(sb->max_cqe);
@@ -130,7 +128,10 @@ int bnxt_qplib_get_dev_attr(struct bnxt_qplib_rcfw *rcfw,
attr->tqm_alloc_reqs[i * 4 + 2] = *(++tqm_alloc);
attr->tqm_alloc_reqs[i * 4 + 3] = *(++tqm_alloc);
}
- return 0;
+
+bail:
+ bnxt_qplib_rcfw_free_sbuf(rcfw, sbuf);
+ return rc;
}
/* SGID */
@@ -178,8 +179,9 @@ int bnxt_qplib_del_sgid(struct bnxt_qplib_sgid_tbl *sgid_tbl,
/* Remove GID from the SGID table */
if (update) {
struct cmdq_delete_gid req;
- struct creq_delete_gid_resp *resp;
+ struct creq_delete_gid_resp resp;
u16 cmd_flags = 0;
+ int rc;
RCFW_CMD_PREP(req, DELETE_GID, cmd_flags);
if (sgid_tbl->hw_id[index] == 0xFFFF) {
@@ -188,31 +190,10 @@ int bnxt_qplib_del_sgid(struct bnxt_qplib_sgid_tbl *sgid_tbl,
return -EINVAL;
}
req.gid_index = cpu_to_le16(sgid_tbl->hw_id[index]);
- resp = (struct creq_delete_gid_resp *)
- bnxt_qplib_rcfw_send_message(rcfw, (void *)&req, NULL,
- 0);
- if (!resp) {
- dev_err(&res->pdev->dev,
- "QPLIB: SP: DELETE_GID send failed");
- return -EINVAL;
- }
- if (!bnxt_qplib_rcfw_wait_for_resp(rcfw,
- le16_to_cpu(req.cookie))) {
- /* Cmd timed out */
- dev_err(&res->pdev->dev,
- "QPLIB: SP: DELETE_GID timed out");
- return -ETIMEDOUT;
- }
- if (resp->status ||
- le16_to_cpu(resp->cookie) != le16_to_cpu(req.cookie)) {
- dev_err(&res->pdev->dev,
- "QPLIB: SP: DELETE_GID failed ");
- dev_err(&res->pdev->dev,
- "QPLIB: with status 0x%x cmdq 0x%x resp 0x%x",
- resp->status, le16_to_cpu(req.cookie),
- le16_to_cpu(resp->cookie));
- return -EINVAL;
- }
+ rc = bnxt_qplib_rcfw_send_message(rcfw, (void *)&req,
+ (void *)&resp, NULL, 0);
+ if (rc)
+ return rc;
}
memcpy(&sgid_tbl->tbl[index], &bnxt_qplib_gid_zero,
sizeof(bnxt_qplib_gid_zero));
@@ -234,7 +215,7 @@ int bnxt_qplib_add_sgid(struct bnxt_qplib_sgid_tbl *sgid_tbl,
struct bnxt_qplib_res,
sgid_tbl);
struct bnxt_qplib_rcfw *rcfw = res->rcfw;
- int i, free_idx, rc = 0;
+ int i, free_idx;
if (!sgid_tbl) {
dev_err(&res->pdev->dev, "QPLIB: SGID table not allocated");
@@ -266,10 +247,11 @@ int bnxt_qplib_add_sgid(struct bnxt_qplib_sgid_tbl *sgid_tbl,
}
if (update) {
struct cmdq_add_gid req;
- struct creq_add_gid_resp *resp;
+ struct creq_add_gid_resp resp;
u16 cmd_flags = 0;
u32 temp32[4];
u16 temp16[3];
+ int rc;
RCFW_CMD_PREP(req, ADD_GID, cmd_flags);
@@ -290,31 +272,11 @@ int bnxt_qplib_add_sgid(struct bnxt_qplib_sgid_tbl *sgid_tbl,
req.src_mac[1] = cpu_to_be16(temp16[1]);
req.src_mac[2] = cpu_to_be16(temp16[2]);
- resp = (struct creq_add_gid_resp *)
- bnxt_qplib_rcfw_send_message(rcfw, (void *)&req,
- NULL, 0);
- if (!resp) {
- dev_err(&res->pdev->dev,
- "QPLIB: SP: ADD_GID send failed");
- return -EINVAL;
- }
- if (!bnxt_qplib_rcfw_wait_for_resp(rcfw,
- le16_to_cpu(req.cookie))) {
- /* Cmd timed out */
- dev_err(&res->pdev->dev,
- "QPIB: SP: ADD_GID timed out");
- return -ETIMEDOUT;
- }
- if (resp->status ||
- le16_to_cpu(resp->cookie) != le16_to_cpu(req.cookie)) {
- dev_err(&res->pdev->dev, "QPLIB: SP: ADD_GID failed ");
- dev_err(&res->pdev->dev,
- "QPLIB: with status 0x%x cmdq 0x%x resp 0x%x",
- resp->status, le16_to_cpu(req.cookie),
- le16_to_cpu(resp->cookie));
- return -EINVAL;
- }
- sgid_tbl->hw_id[free_idx] = le32_to_cpu(resp->xid);
+ rc = bnxt_qplib_rcfw_send_message(rcfw, (void *)&req,
+ (void *)&resp, NULL, 0);
+ if (rc)
+ return rc;
+ sgid_tbl->hw_id[free_idx] = le32_to_cpu(resp.xid);
}
/* Add GID to the sgid_tbl */
memcpy(&sgid_tbl->tbl[free_idx], gid, sizeof(*gid));
@@ -325,7 +287,7 @@ int bnxt_qplib_add_sgid(struct bnxt_qplib_sgid_tbl *sgid_tbl,
*index = free_idx;
/* unlock */
- return rc;
+ return 0;
}
/* pkeys */
@@ -422,10 +384,11 @@ int bnxt_qplib_create_ah(struct bnxt_qplib_res *res, struct bnxt_qplib_ah *ah)
{
struct bnxt_qplib_rcfw *rcfw = res->rcfw;
struct cmdq_create_ah req;
- struct creq_create_ah_resp *resp;
+ struct creq_create_ah_resp resp;
u16 cmd_flags = 0;
u32 temp32[4];
u16 temp16[3];
+ int rc;
RCFW_CMD_PREP(req, CREATE_AH, cmd_flags);
@@ -450,28 +413,12 @@ int bnxt_qplib_create_ah(struct bnxt_qplib_res *res, struct bnxt_qplib_ah *ah)
req.dest_mac[1] = cpu_to_le16(temp16[1]);
req.dest_mac[2] = cpu_to_le16(temp16[2]);
- resp = (struct creq_create_ah_resp *)
- bnxt_qplib_rcfw_send_message(rcfw, (void *)&req,
- NULL, 1);
- if (!resp) {
- dev_err(&rcfw->pdev->dev, "QPLIB: SP: CREATE_AH send failed");
- return -EINVAL;
- }
- if (!bnxt_qplib_rcfw_block_for_resp(rcfw, le16_to_cpu(req.cookie))) {
- /* Cmd timed out */
- dev_err(&rcfw->pdev->dev, "QPLIB: SP: CREATE_AH timed out");
- return -ETIMEDOUT;
- }
- if (resp->status ||
- le16_to_cpu(resp->cookie) != le16_to_cpu(req.cookie)) {
- dev_err(&rcfw->pdev->dev, "QPLIB: SP: CREATE_AH failed ");
- dev_err(&rcfw->pdev->dev,
- "QPLIB: with status 0x%x cmdq 0x%x resp 0x%x",
- resp->status, le16_to_cpu(req.cookie),
- le16_to_cpu(resp->cookie));
- return -EINVAL;
- }
- ah->id = le32_to_cpu(resp->xid);
+ rc = bnxt_qplib_rcfw_send_message(rcfw, (void *)&req, (void *)&resp,
+ NULL, 1);
+ if (rc)
+ return rc;
+
+ ah->id = le32_to_cpu(resp.xid);
return 0;
}
@@ -479,35 +426,19 @@ int bnxt_qplib_destroy_ah(struct bnxt_qplib_res *res, struct bnxt_qplib_ah *ah)
{
struct bnxt_qplib_rcfw *rcfw = res->rcfw;
struct cmdq_destroy_ah req;
- struct creq_destroy_ah_resp *resp;
+ struct creq_destroy_ah_resp resp;
u16 cmd_flags = 0;
+ int rc;
/* Clean up the AH table in the device */
RCFW_CMD_PREP(req, DESTROY_AH, cmd_flags);
req.ah_cid = cpu_to_le32(ah->id);
- resp = (struct creq_destroy_ah_resp *)
- bnxt_qplib_rcfw_send_message(rcfw, (void *)&req,
- NULL, 1);
- if (!resp) {
- dev_err(&rcfw->pdev->dev, "QPLIB: SP: DESTROY_AH send failed");
- return -EINVAL;
- }
- if (!bnxt_qplib_rcfw_block_for_resp(rcfw, le16_to_cpu(req.cookie))) {
- /* Cmd timed out */
- dev_err(&rcfw->pdev->dev, "QPLIB: SP: DESTROY_AH timed out");
- return -ETIMEDOUT;
- }
- if (resp->status ||
- le16_to_cpu(resp->cookie) != le16_to_cpu(req.cookie)) {
- dev_err(&rcfw->pdev->dev, "QPLIB: SP: DESTROY_AH failed ");
- dev_err(&rcfw->pdev->dev,
- "QPLIB: with status 0x%x cmdq 0x%x resp 0x%x",
- resp->status, le16_to_cpu(req.cookie),
- le16_to_cpu(resp->cookie));
- return -EINVAL;
- }
+ rc = bnxt_qplib_rcfw_send_message(rcfw, (void *)&req, (void *)&resp,
+ NULL, 1);
+ if (rc)
+ return rc;
return 0;
}
@@ -516,8 +447,9 @@ int bnxt_qplib_free_mrw(struct bnxt_qplib_res *res, struct bnxt_qplib_mrw *mrw)
{
struct bnxt_qplib_rcfw *rcfw = res->rcfw;
struct cmdq_deallocate_key req;
- struct creq_deallocate_key_resp *resp;
+ struct creq_deallocate_key_resp resp;
u16 cmd_flags = 0;
+ int rc;
if (mrw->lkey == 0xFFFFFFFF) {
dev_info(&res->pdev->dev,
@@ -536,27 +468,11 @@ int bnxt_qplib_free_mrw(struct bnxt_qplib_res *res, struct bnxt_qplib_mrw *mrw)
else
req.key = cpu_to_le32(mrw->lkey);
- resp = (struct creq_deallocate_key_resp *)
- bnxt_qplib_rcfw_send_message(rcfw, (void *)&req,
- NULL, 0);
- if (!resp) {
- dev_err(&res->pdev->dev, "QPLIB: SP: FREE_MR send failed");
- return -EINVAL;
- }
- if (!bnxt_qplib_rcfw_wait_for_resp(rcfw, le16_to_cpu(req.cookie))) {
- /* Cmd timed out */
- dev_err(&res->pdev->dev, "QPLIB: SP: FREE_MR timed out");
- return -ETIMEDOUT;
- }
- if (resp->status ||
- le16_to_cpu(resp->cookie) != le16_to_cpu(req.cookie)) {
- dev_err(&res->pdev->dev, "QPLIB: SP: FREE_MR failed ");
- dev_err(&res->pdev->dev,
- "QPLIB: with status 0x%x cmdq 0x%x resp 0x%x",
- resp->status, le16_to_cpu(req.cookie),
- le16_to_cpu(resp->cookie));
- return -EINVAL;
- }
+ rc = bnxt_qplib_rcfw_send_message(rcfw, (void *)&req, (void *)&resp,
+ NULL, 0);
+ if (rc)
+ return rc;
+
/* Free the qplib's MRW memory */
if (mrw->hwq.max_elements)
bnxt_qplib_free_hwq(res->pdev, &mrw->hwq);
@@ -568,9 +484,10 @@ int bnxt_qplib_alloc_mrw(struct bnxt_qplib_res *res, struct bnxt_qplib_mrw *mrw)
{
struct bnxt_qplib_rcfw *rcfw = res->rcfw;
struct cmdq_allocate_mrw req;
- struct creq_allocate_mrw_resp *resp;
+ struct creq_allocate_mrw_resp resp;
u16 cmd_flags = 0;
unsigned long tmp;
+ int rc;
RCFW_CMD_PREP(req, ALLOCATE_MRW, cmd_flags);
@@ -584,33 +501,17 @@ int bnxt_qplib_alloc_mrw(struct bnxt_qplib_res *res, struct bnxt_qplib_mrw *mrw)
tmp = (unsigned long)mrw;
req.mrw_handle = cpu_to_le64(tmp);
- resp = (struct creq_allocate_mrw_resp *)
- bnxt_qplib_rcfw_send_message(rcfw, (void *)&req,
- NULL, 0);
- if (!resp) {
- dev_err(&rcfw->pdev->dev, "QPLIB: SP: ALLOC_MRW send failed");
- return -EINVAL;
- }
- if (!bnxt_qplib_rcfw_wait_for_resp(rcfw, le16_to_cpu(req.cookie))) {
- /* Cmd timed out */
- dev_err(&rcfw->pdev->dev, "QPLIB: SP: ALLOC_MRW timed out");
- return -ETIMEDOUT;
- }
- if (resp->status ||
- le16_to_cpu(resp->cookie) != le16_to_cpu(req.cookie)) {
- dev_err(&rcfw->pdev->dev, "QPLIB: SP: ALLOC_MRW failed ");
- dev_err(&rcfw->pdev->dev,
- "QPLIB: with status 0x%x cmdq 0x%x resp 0x%x",
- resp->status, le16_to_cpu(req.cookie),
- le16_to_cpu(resp->cookie));
- return -EINVAL;
- }
+ rc = bnxt_qplib_rcfw_send_message(rcfw, (void *)&req,
+ (void *)&resp, NULL, 0);
+ if (rc)
+ return rc;
+
if ((mrw->type == CMDQ_ALLOCATE_MRW_MRW_FLAGS_MW_TYPE1) ||
(mrw->type == CMDQ_ALLOCATE_MRW_MRW_FLAGS_MW_TYPE2A) ||
(mrw->type == CMDQ_ALLOCATE_MRW_MRW_FLAGS_MW_TYPE2B))
- mrw->rkey = le32_to_cpu(resp->xid);
+ mrw->rkey = le32_to_cpu(resp.xid);
else
- mrw->lkey = le32_to_cpu(resp->xid);
+ mrw->lkey = le32_to_cpu(resp.xid);
return 0;
}
@@ -619,40 +520,17 @@ int bnxt_qplib_dereg_mrw(struct bnxt_qplib_res *res, struct bnxt_qplib_mrw *mrw,
{
struct bnxt_qplib_rcfw *rcfw = res->rcfw;
struct cmdq_deregister_mr req;
- struct creq_deregister_mr_resp *resp;
+ struct creq_deregister_mr_resp resp;
u16 cmd_flags = 0;
int rc;
RCFW_CMD_PREP(req, DEREGISTER_MR, cmd_flags);
req.lkey = cpu_to_le32(mrw->lkey);
- resp = (struct creq_deregister_mr_resp *)
- bnxt_qplib_rcfw_send_message(rcfw, (void *)&req,
- NULL, block);
- if (!resp) {
- dev_err(&rcfw->pdev->dev, "QPLIB: SP: DEREG_MR send failed");
- return -EINVAL;
- }
- if (block)
- rc = bnxt_qplib_rcfw_block_for_resp(rcfw,
- le16_to_cpu(req.cookie));
- else
- rc = bnxt_qplib_rcfw_wait_for_resp(rcfw,
- le16_to_cpu(req.cookie));
- if (!rc) {
- /* Cmd timed out */
- dev_err(&res->pdev->dev, "QPLIB: SP: DEREG_MR timed out");
- return -ETIMEDOUT;
- }
- if (resp->status ||
- le16_to_cpu(resp->cookie) != le16_to_cpu(req.cookie)) {
- dev_err(&rcfw->pdev->dev, "QPLIB: SP: DEREG_MR failed ");
- dev_err(&rcfw->pdev->dev,
- "QPLIB: with status 0x%x cmdq 0x%x resp 0x%x",
- resp->status, le16_to_cpu(req.cookie),
- le16_to_cpu(resp->cookie));
- return -EINVAL;
- }
+ rc = bnxt_qplib_rcfw_send_message(rcfw, (void *)&req,
+ (void *)&resp, NULL, block);
+ if (rc)
+ return rc;
/* Free the qplib's MR memory */
if (mrw->hwq.max_elements) {
@@ -669,7 +547,7 @@ int bnxt_qplib_reg_mr(struct bnxt_qplib_res *res, struct bnxt_qplib_mrw *mr,
{
struct bnxt_qplib_rcfw *rcfw = res->rcfw;
struct cmdq_register_mr req;
- struct creq_register_mr_resp *resp;
+ struct creq_register_mr_resp resp;
u16 cmd_flags = 0, level;
int pg_ptrs, pages, i, rc;
dma_addr_t **pbl_ptr;
@@ -730,36 +608,11 @@ int bnxt_qplib_reg_mr(struct bnxt_qplib_res *res, struct bnxt_qplib_mrw *mr,
req.key = cpu_to_le32(mr->lkey);
req.mr_size = cpu_to_le64(mr->total_size);
- resp = (struct creq_register_mr_resp *)
- bnxt_qplib_rcfw_send_message(rcfw, (void *)&req,
- NULL, block);
- if (!resp) {
- dev_err(&res->pdev->dev, "SP: REG_MR send failed");
- rc = -EINVAL;
- goto fail;
- }
- if (block)
- rc = bnxt_qplib_rcfw_block_for_resp(rcfw,
- le16_to_cpu(req.cookie));
- else
- rc = bnxt_qplib_rcfw_wait_for_resp(rcfw,
- le16_to_cpu(req.cookie));
- if (!rc) {
- /* Cmd timed out */
- dev_err(&res->pdev->dev, "SP: REG_MR timed out");
- rc = -ETIMEDOUT;
- goto fail;
- }
- if (resp->status ||
- le16_to_cpu(resp->cookie) != le16_to_cpu(req.cookie)) {
- dev_err(&res->pdev->dev, "QPLIB: SP: REG_MR failed ");
- dev_err(&res->pdev->dev,
- "QPLIB: SP: with status 0x%x cmdq 0x%x resp 0x%x",
- resp->status, le16_to_cpu(req.cookie),
- le16_to_cpu(resp->cookie));
- rc = -EINVAL;
+ rc = bnxt_qplib_rcfw_send_message(rcfw, (void *)&req,
+ (void *)&resp, NULL, block);
+ if (rc)
goto fail;
- }
+
return 0;
fail:
@@ -804,35 +657,15 @@ int bnxt_qplib_map_tc2cos(struct bnxt_qplib_res *res, u16 *cids)
{
struct bnxt_qplib_rcfw *rcfw = res->rcfw;
struct cmdq_map_tc_to_cos req;
- struct creq_map_tc_to_cos_resp *resp;
+ struct creq_map_tc_to_cos_resp resp;
u16 cmd_flags = 0;
- int tleft;
+ int rc = 0;
RCFW_CMD_PREP(req, MAP_TC_TO_COS, cmd_flags);
req.cos0 = cpu_to_le16(cids[0]);
req.cos1 = cpu_to_le16(cids[1]);
- resp = bnxt_qplib_rcfw_send_message(rcfw, (void *)&req, NULL, 0);
- if (!resp) {
- dev_err(&res->pdev->dev, "QPLIB: SP: MAP_TC2COS send failed");
- return -EINVAL;
- }
-
- tleft = bnxt_qplib_rcfw_block_for_resp(rcfw, le16_to_cpu(req.cookie));
- if (!tleft) {
- dev_err(&res->pdev->dev, "QPLIB: SP: MAP_TC2COS timed out");
- return -ETIMEDOUT;
- }
-
- if (resp->status ||
- le16_to_cpu(resp->cookie) != le16_to_cpu(req.cookie)) {
- dev_err(&res->pdev->dev, "QPLIB: SP: MAP_TC2COS failed ");
- dev_err(&res->pdev->dev,
- "QPLIB: with status 0x%x cmdq 0x%x resp 0x%x",
- resp->status, le16_to_cpu(req.cookie),
- le16_to_cpu(resp->cookie));
- return -EINVAL;
- }
-
+ rc = bnxt_qplib_rcfw_send_message(rcfw, (void *)&req,
+ (void *)&resp, NULL, 0);
return 0;
}
diff --git a/drivers/infiniband/hw/bnxt_re/qplib_sp.h b/drivers/infiniband/hw/bnxt_re/qplib_sp.h
index 1442a617e968..a543f959098b 100644
--- a/drivers/infiniband/hw/bnxt_re/qplib_sp.h
+++ b/drivers/infiniband/hw/bnxt_re/qplib_sp.h
@@ -40,6 +40,8 @@
#ifndef __BNXT_QPLIB_SP_H__
#define __BNXT_QPLIB_SP_H__
+#define BNXT_QPLIB_RESERVED_QP_WRS 128
+
struct bnxt_qplib_dev_attr {
char fw_ver[32];
u16 max_sgid;
diff --git a/drivers/infiniband/hw/cxgb4/cm.c b/drivers/infiniband/hw/cxgb4/cm.c
index b6fe45924c6e..0910faf3587b 100644
--- a/drivers/infiniband/hw/cxgb4/cm.c
+++ b/drivers/infiniband/hw/cxgb4/cm.c
@@ -488,6 +488,7 @@ static int _put_ep_safe(struct c4iw_dev *dev, struct sk_buff *skb)
ep = *((struct c4iw_ep **)(skb->cb + 2 * sizeof(void *)));
release_ep_resources(ep);
+ kfree_skb(skb);
return 0;
}
@@ -498,6 +499,7 @@ static int _put_pass_ep_safe(struct c4iw_dev *dev, struct sk_buff *skb)
ep = *((struct c4iw_ep **)(skb->cb + 2 * sizeof(void *)));
c4iw_put_ep(&ep->parent_ep->com);
release_ep_resources(ep);
+ kfree_skb(skb);
return 0;
}
@@ -569,11 +571,13 @@ static void abort_arp_failure(void *handle, struct sk_buff *skb)
pr_debug("%s rdev %p\n", __func__, rdev);
req->cmd = CPL_ABORT_NO_RST;
+ skb_get(skb);
ret = c4iw_ofld_send(rdev, skb);
if (ret) {
__state_set(&ep->com, DEAD);
queue_arp_failure_cpl(ep, skb, FAKE_CPL_PUT_EP_SAFE);
- }
+ } else
+ kfree_skb(skb);
}
static int send_flowc(struct c4iw_ep *ep)
@@ -2517,7 +2521,8 @@ static int pass_accept_req(struct c4iw_dev *dev, struct sk_buff *skb)
goto reject;
}
- hdrs = sizeof(struct iphdr) + sizeof(struct tcphdr) +
+ hdrs = ((iptype == 4) ? sizeof(struct iphdr) : sizeof(struct ipv6hdr)) +
+ sizeof(struct tcphdr) +
((enable_tcp_timestamps && req->tcpopt.tstamp) ? 12 : 0);
if (peer_mss && child_ep->mtu > (peer_mss + hdrs))
child_ep->mtu = peer_mss + hdrs;
diff --git a/drivers/infiniband/hw/cxgb4/device.c b/drivers/infiniband/hw/cxgb4/device.c
index 329fb65e8fb0..ae0b79aeea2e 100644
--- a/drivers/infiniband/hw/cxgb4/device.c
+++ b/drivers/infiniband/hw/cxgb4/device.c
@@ -767,7 +767,7 @@ void c4iw_release_dev_ucontext(struct c4iw_rdev *rdev,
kfree(entry);
}
- list_for_each_safe(pos, nxt, &uctx->qpids) {
+ list_for_each_safe(pos, nxt, &uctx->cqids) {
entry = list_entry(pos, struct c4iw_qid_list, entry);
list_del_init(&entry->entry);
kfree(entry);
@@ -880,13 +880,15 @@ static int c4iw_rdev_open(struct c4iw_rdev *rdev)
rdev->free_workq = create_singlethread_workqueue("iw_cxgb4_free");
if (!rdev->free_workq) {
err = -ENOMEM;
- goto err_free_status_page;
+ goto err_free_status_page_and_wr_log;
}
rdev->status_page->db_off = 0;
return 0;
-err_free_status_page:
+err_free_status_page_and_wr_log:
+ if (c4iw_wr_log && rdev->wr_log)
+ kfree(rdev->wr_log);
free_page((unsigned long)rdev->status_page);
destroy_ocqp_pool:
c4iw_ocqp_pool_destroy(rdev);
@@ -903,9 +905,11 @@ static void c4iw_rdev_close(struct c4iw_rdev *rdev)
{
destroy_workqueue(rdev->free_workq);
kfree(rdev->wr_log);
+ c4iw_release_dev_ucontext(rdev, &rdev->uctx);
free_page((unsigned long)rdev->status_page);
c4iw_pblpool_destroy(rdev);
c4iw_rqtpool_destroy(rdev);
+ c4iw_ocqp_pool_destroy(rdev);
c4iw_destroy_resource(&rdev->resource);
}
@@ -971,7 +975,7 @@ static struct c4iw_dev *c4iw_alloc(const struct cxgb4_lld_info *infop)
devp->rdev.lldi.sge_egrstatuspagesize);
devp->rdev.hw_queue.t4_eq_status_entries =
- devp->rdev.lldi.sge_ingpadboundary > 64 ? 2 : 1;
+ devp->rdev.lldi.sge_egrstatuspagesize / 64;
devp->rdev.hw_queue.t4_max_eq_size = 65520;
devp->rdev.hw_queue.t4_max_iq_size = 65520;
devp->rdev.hw_queue.t4_max_rq_size = 8192 -
diff --git a/drivers/infiniband/hw/hfi1/chip.c b/drivers/infiniband/hw/hfi1/chip.c
index 5d6b1eeaa9a0..2ba00b89df6a 100644
--- a/drivers/infiniband/hw/hfi1/chip.c
+++ b/drivers/infiniband/hw/hfi1/chip.c
@@ -6312,25 +6312,38 @@ static void handle_8051_request(struct hfi1_pportdata *ppd)
}
}
-static void write_global_credit(struct hfi1_devdata *dd,
- u8 vau, u16 total, u16 shared)
+/*
+ * Set up allocation unit vaulue.
+ */
+void set_up_vau(struct hfi1_devdata *dd, u8 vau)
{
- write_csr(dd, SEND_CM_GLOBAL_CREDIT,
- ((u64)total <<
- SEND_CM_GLOBAL_CREDIT_TOTAL_CREDIT_LIMIT_SHIFT) |
- ((u64)shared <<
- SEND_CM_GLOBAL_CREDIT_SHARED_LIMIT_SHIFT) |
- ((u64)vau << SEND_CM_GLOBAL_CREDIT_AU_SHIFT));
+ u64 reg = read_csr(dd, SEND_CM_GLOBAL_CREDIT);
+
+ /* do not modify other values in the register */
+ reg &= ~SEND_CM_GLOBAL_CREDIT_AU_SMASK;
+ reg |= (u64)vau << SEND_CM_GLOBAL_CREDIT_AU_SHIFT;
+ write_csr(dd, SEND_CM_GLOBAL_CREDIT, reg);
}
/*
* Set up initial VL15 credits of the remote. Assumes the rest of
- * the CM credit registers are zero from a previous global or credit reset .
+ * the CM credit registers are zero from a previous global or credit reset.
+ * Shared limit for VL15 will always be 0.
*/
-void set_up_vl15(struct hfi1_devdata *dd, u8 vau, u16 vl15buf)
+void set_up_vl15(struct hfi1_devdata *dd, u16 vl15buf)
{
- /* leave shared count at zero for both global and VL15 */
- write_global_credit(dd, vau, vl15buf, 0);
+ u64 reg = read_csr(dd, SEND_CM_GLOBAL_CREDIT);
+
+ /* set initial values for total and shared credit limit */
+ reg &= ~(SEND_CM_GLOBAL_CREDIT_TOTAL_CREDIT_LIMIT_SMASK |
+ SEND_CM_GLOBAL_CREDIT_SHARED_LIMIT_SMASK);
+
+ /*
+ * Set total limit to be equal to VL15 credits.
+ * Leave shared limit at 0.
+ */
+ reg |= (u64)vl15buf << SEND_CM_GLOBAL_CREDIT_TOTAL_CREDIT_LIMIT_SHIFT;
+ write_csr(dd, SEND_CM_GLOBAL_CREDIT, reg);
write_csr(dd, SEND_CM_CREDIT_VL15, (u64)vl15buf
<< SEND_CM_CREDIT_VL15_DEDICATED_LIMIT_VL_SHIFT);
@@ -6348,9 +6361,11 @@ void reset_link_credits(struct hfi1_devdata *dd)
for (i = 0; i < TXE_NUM_DATA_VL; i++)
write_csr(dd, SEND_CM_CREDIT_VL + (8 * i), 0);
write_csr(dd, SEND_CM_CREDIT_VL15, 0);
- write_global_credit(dd, 0, 0, 0);
+ write_csr(dd, SEND_CM_GLOBAL_CREDIT, 0);
/* reset the CM block */
pio_send_control(dd, PSC_CM_RESET);
+ /* reset cached value */
+ dd->vl15buf_cached = 0;
}
/* convert a vCU to a CU */
@@ -6839,24 +6854,35 @@ void handle_link_up(struct work_struct *work)
{
struct hfi1_pportdata *ppd = container_of(work, struct hfi1_pportdata,
link_up_work);
+ struct hfi1_devdata *dd = ppd->dd;
+
set_link_state(ppd, HLS_UP_INIT);
/* cache the read of DC_LCB_STS_ROUND_TRIP_LTP_CNT */
- read_ltp_rtt(ppd->dd);
+ read_ltp_rtt(dd);
/*
* OPA specifies that certain counters are cleared on a transition
* to link up, so do that.
*/
- clear_linkup_counters(ppd->dd);
+ clear_linkup_counters(dd);
/*
* And (re)set link up default values.
*/
set_linkup_defaults(ppd);
+ /*
+ * Set VL15 credits. Use cached value from verify cap interrupt.
+ * In case of quick linkup or simulator, vl15 value will be set by
+ * handle_linkup_change. VerifyCap interrupt handler will not be
+ * called in those scenarios.
+ */
+ if (!(quick_linkup || dd->icode == ICODE_FUNCTIONAL_SIMULATOR))
+ set_up_vl15(dd, dd->vl15buf_cached);
+
/* enforce link speed enabled */
if ((ppd->link_speed_active & ppd->link_speed_enabled) == 0) {
/* oops - current speed is not enabled, bounce */
- dd_dev_err(ppd->dd,
+ dd_dev_err(dd,
"Link speed active 0x%x is outside enabled 0x%x, downing link\n",
ppd->link_speed_active, ppd->link_speed_enabled);
set_link_down_reason(ppd, OPA_LINKDOWN_REASON_SPEED_POLICY, 0,
@@ -7357,7 +7383,14 @@ void handle_verify_cap(struct work_struct *work)
*/
if (vau == 0)
vau = 1;
- set_up_vl15(dd, vau, vl15buf);
+ set_up_vau(dd, vau);
+
+ /*
+ * Set VL15 credits to 0 in global credit register. Cache remote VL15
+ * credits value and wait for link-up interrupt ot set it.
+ */
+ set_up_vl15(dd, 0);
+ dd->vl15buf_cached = vl15buf;
/* set up the LCB CRC mode */
crc_mask = ppd->port_crc_mode_enabled & partner_supported_crc;
diff --git a/drivers/infiniband/hw/hfi1/chip_registers.h b/drivers/infiniband/hw/hfi1/chip_registers.h
index 5bfa839d1c48..793514f1d15f 100644
--- a/drivers/infiniband/hw/hfi1/chip_registers.h
+++ b/drivers/infiniband/hw/hfi1/chip_registers.h
@@ -839,7 +839,9 @@
#define SEND_CM_CTRL_FORCE_CREDIT_MODE_SMASK 0x8ull
#define SEND_CM_CTRL_RESETCSR 0x0000000000000020ull
#define SEND_CM_GLOBAL_CREDIT (TXE + 0x000000000508)
+#define SEND_CM_GLOBAL_CREDIT_AU_MASK 0x7ull
#define SEND_CM_GLOBAL_CREDIT_AU_SHIFT 16
+#define SEND_CM_GLOBAL_CREDIT_AU_SMASK 0x70000ull
#define SEND_CM_GLOBAL_CREDIT_RESETCSR 0x0000094000030000ull
#define SEND_CM_GLOBAL_CREDIT_SHARED_LIMIT_MASK 0xFFFFull
#define SEND_CM_GLOBAL_CREDIT_SHARED_LIMIT_SHIFT 0
diff --git a/drivers/infiniband/hw/hfi1/hfi.h b/drivers/infiniband/hw/hfi1/hfi.h
index da322e6668cc..414a04a481c2 100644
--- a/drivers/infiniband/hw/hfi1/hfi.h
+++ b/drivers/infiniband/hw/hfi1/hfi.h
@@ -1045,6 +1045,14 @@ struct hfi1_devdata {
/* initial vl15 credits to use */
u16 vl15_init;
+ /*
+ * Cached value for vl15buf, read during verify cap interrupt. VL15
+ * credits are to be kept at 0 and set when handling the link-up
+ * interrupt. This removes the possibility of receiving VL15 MAD
+ * packets before this HFI is ready.
+ */
+ u16 vl15buf_cached;
+
/* Misc small ints */
u8 n_krcv_queues;
u8 qos_shift;
@@ -1598,7 +1606,8 @@ int hfi1_rcvbuf_validate(u32 size, u8 type, u16 *encode);
int fm_get_table(struct hfi1_pportdata *ppd, int which, void *t);
int fm_set_table(struct hfi1_pportdata *ppd, int which, void *t);
-void set_up_vl15(struct hfi1_devdata *dd, u8 vau, u16 vl15buf);
+void set_up_vau(struct hfi1_devdata *dd, u8 vau);
+void set_up_vl15(struct hfi1_devdata *dd, u16 vl15buf);
void reset_link_credits(struct hfi1_devdata *dd);
void assign_remote_cm_au_table(struct hfi1_devdata *dd, u8 vcu);
diff --git a/drivers/infiniband/hw/hfi1/intr.c b/drivers/infiniband/hw/hfi1/intr.c
index ba265d0ae93b..04a5082d5ac5 100644
--- a/drivers/infiniband/hw/hfi1/intr.c
+++ b/drivers/infiniband/hw/hfi1/intr.c
@@ -130,7 +130,8 @@ void handle_linkup_change(struct hfi1_devdata *dd, u32 linkup)
* the remote values. Both sides must be using the values.
*/
if (quick_linkup || dd->icode == ICODE_FUNCTIONAL_SIMULATOR) {
- set_up_vl15(dd, dd->vau, dd->vl15_init);
+ set_up_vau(dd, dd->vau);
+ set_up_vl15(dd, dd->vl15_init);
assign_remote_cm_au_table(dd, dd->vcu);
}
diff --git a/drivers/infiniband/hw/hfi1/pcie.c b/drivers/infiniband/hw/hfi1/pcie.c
index 93faf86d54b6..6a9f6f9819e1 100644
--- a/drivers/infiniband/hw/hfi1/pcie.c
+++ b/drivers/infiniband/hw/hfi1/pcie.c
@@ -207,8 +207,8 @@ int hfi1_pcie_ddinit(struct hfi1_devdata *dd, struct pci_dev *pdev)
/*
* Save BARs and command to rewrite after device reset.
*/
- dd->pcibar0 = addr;
- dd->pcibar1 = addr >> 32;
+ pci_read_config_dword(dd->pcidev, PCI_BASE_ADDRESS_0, &dd->pcibar0);
+ pci_read_config_dword(dd->pcidev, PCI_BASE_ADDRESS_1, &dd->pcibar1);
pci_read_config_dword(dd->pcidev, PCI_ROM_ADDRESS, &dd->pci_rom);
pci_read_config_word(dd->pcidev, PCI_COMMAND, &dd->pci_command);
pcie_capability_read_word(dd->pcidev, PCI_EXP_DEVCTL, &dd->pcie_devctl);
diff --git a/drivers/infiniband/hw/hfi1/rc.c b/drivers/infiniband/hw/hfi1/rc.c
index 069bdaf061ab..1080778a1f7c 100644
--- a/drivers/infiniband/hw/hfi1/rc.c
+++ b/drivers/infiniband/hw/hfi1/rc.c
@@ -2159,8 +2159,11 @@ send_last:
ret = hfi1_rvt_get_rwqe(qp, 1);
if (ret < 0)
goto nack_op_err;
- if (!ret)
+ if (!ret) {
+ /* peer will send again */
+ rvt_put_ss(&qp->r_sge);
goto rnr_nak;
+ }
wc.ex.imm_data = ohdr->u.rc.imm_data;
wc.wc_flags = IB_WC_WITH_IMM;
goto send_last;
diff --git a/drivers/infiniband/hw/hfi1/sysfs.c b/drivers/infiniband/hw/hfi1/sysfs.c
index 50d140d25e38..2f3bbcac1e34 100644
--- a/drivers/infiniband/hw/hfi1/sysfs.c
+++ b/drivers/infiniband/hw/hfi1/sysfs.c
@@ -196,7 +196,8 @@ static const struct sysfs_ops port_cc_sysfs_ops = {
};
static struct attribute *port_cc_default_attributes[] = {
- &cc_prescan_attr.attr
+ &cc_prescan_attr.attr,
+ NULL
};
static struct kobj_type port_cc_ktype = {
diff --git a/drivers/infiniband/hw/i40iw/i40iw_cm.c b/drivers/infiniband/hw/i40iw/i40iw_cm.c
index f3bc01bce483..6ae98aa7f74e 100644
--- a/drivers/infiniband/hw/i40iw/i40iw_cm.c
+++ b/drivers/infiniband/hw/i40iw/i40iw_cm.c
@@ -784,7 +784,6 @@ static void i40iw_build_mpa_v2(struct i40iw_cm_node *cm_node,
}
ctrl_ird |= IETF_PEER_TO_PEER;
- ctrl_ird |= IETF_FLPDU_ZERO_LEN;
switch (mpa_key) {
case MPA_KEY_REQUEST:
@@ -2446,8 +2445,8 @@ static void i40iw_handle_rcv_mpa(struct i40iw_cm_node *cm_node,
} else {
type = I40IW_CM_EVENT_CONNECTED;
cm_node->state = I40IW_CM_STATE_OFFLOADED;
- i40iw_send_ack(cm_node);
}
+ i40iw_send_ack(cm_node);
break;
default:
pr_err("%s wrong cm_node state =%d\n", __func__, cm_node->state);
diff --git a/drivers/infiniband/hw/i40iw/i40iw_ctrl.c b/drivers/infiniband/hw/i40iw/i40iw_ctrl.c
index f82483b3d1e7..a027e2072477 100644
--- a/drivers/infiniband/hw/i40iw/i40iw_ctrl.c
+++ b/drivers/infiniband/hw/i40iw/i40iw_ctrl.c
@@ -285,28 +285,20 @@ void i40iw_change_l2params(struct i40iw_sc_vsi *vsi, struct i40iw_l2params *l2pa
struct i40iw_sc_dev *dev = vsi->dev;
struct i40iw_sc_qp *qp = NULL;
bool qs_handle_change = false;
- bool mss_change = false;
unsigned long flags;
u16 qs_handle;
int i;
- if (vsi->mss != l2params->mss) {
- mss_change = true;
- vsi->mss = l2params->mss;
- }
+ vsi->mss = l2params->mss;
i40iw_fill_qos_list(l2params->qs_handle_list);
for (i = 0; i < I40IW_MAX_USER_PRIORITY; i++) {
qs_handle = l2params->qs_handle_list[i];
if (vsi->qos[i].qs_handle != qs_handle)
qs_handle_change = true;
- else if (!mss_change)
- continue; /* no MSS nor qs handle change */
spin_lock_irqsave(&vsi->qos[i].lock, flags);
qp = i40iw_get_qp(&vsi->qos[i].qplist, qp);
while (qp) {
- if (mss_change)
- i40iw_qp_mss_modify(dev, qp);
if (qs_handle_change) {
qp->qs_handle = qs_handle;
/* issue cqp suspend command */
@@ -2395,7 +2387,6 @@ static enum i40iw_status_code i40iw_sc_qp_modify(
set_64bit_val(wqe,
8,
- LS_64(info->new_mss, I40IW_CQPSQ_QP_NEWMSS) |
LS_64(term_len, I40IW_CQPSQ_QP_TERMLEN));
set_64bit_val(wqe, 16, qp->hw_host_ctx_pa);
@@ -2410,7 +2401,6 @@ static enum i40iw_status_code i40iw_sc_qp_modify(
LS_64(info->cq_num_valid, I40IW_CQPSQ_QP_CQNUMVALID) |
LS_64(info->force_loopback, I40IW_CQPSQ_QP_FORCELOOPBACK) |
LS_64(qp->qp_type, I40IW_CQPSQ_QP_QPTYPE) |
- LS_64(info->mss_change, I40IW_CQPSQ_QP_MSSCHANGE) |
LS_64(info->static_rsrc, I40IW_CQPSQ_QP_STATRSRC) |
LS_64(info->remove_hash_idx, I40IW_CQPSQ_QP_REMOVEHASHENTRY) |
LS_64(term_actions, I40IW_CQPSQ_QP_TERMACT) |
diff --git a/drivers/infiniband/hw/i40iw/i40iw_main.c b/drivers/infiniband/hw/i40iw/i40iw_main.c
index 2728af3103ce..e0f47cc2effc 100644
--- a/drivers/infiniband/hw/i40iw/i40iw_main.c
+++ b/drivers/infiniband/hw/i40iw/i40iw_main.c
@@ -1319,13 +1319,13 @@ static enum i40iw_status_code i40iw_initialize_dev(struct i40iw_device *iwdev,
status = i40iw_obj_aligned_mem(iwdev, &mem, I40IW_QUERY_FPM_BUF_SIZE,
I40IW_FPM_QUERY_BUF_ALIGNMENT_MASK);
if (status)
- goto exit;
+ goto error;
info.fpm_query_buf_pa = mem.pa;
info.fpm_query_buf = mem.va;
status = i40iw_obj_aligned_mem(iwdev, &mem, I40IW_COMMIT_FPM_BUF_SIZE,
I40IW_FPM_COMMIT_BUF_ALIGNMENT_MASK);
if (status)
- goto exit;
+ goto error;
info.fpm_commit_buf_pa = mem.pa;
info.fpm_commit_buf = mem.va;
info.hmc_fn_id = ldev->fid;
@@ -1347,11 +1347,9 @@ static enum i40iw_status_code i40iw_initialize_dev(struct i40iw_device *iwdev,
info.exception_lan_queue = 1;
info.vchnl_send = i40iw_virtchnl_send;
status = i40iw_device_init(&iwdev->sc_dev, &info);
-exit:
- if (status) {
- kfree(iwdev->hmc_info_mem);
- iwdev->hmc_info_mem = NULL;
- }
+
+ if (status)
+ goto error;
memset(&vsi_info, 0, sizeof(vsi_info));
vsi_info.dev = &iwdev->sc_dev;
vsi_info.back_vsi = (void *)iwdev;
@@ -1362,11 +1360,19 @@ exit:
memset(&stats_info, 0, sizeof(stats_info));
stats_info.fcn_id = ldev->fid;
stats_info.pestat = kzalloc(sizeof(*stats_info.pestat), GFP_KERNEL);
+ if (!stats_info.pestat) {
+ status = I40IW_ERR_NO_MEMORY;
+ goto error;
+ }
stats_info.stats_initialize = true;
if (stats_info.pestat)
i40iw_vsi_stats_init(&iwdev->vsi, &stats_info);
}
return status;
+error:
+ kfree(iwdev->hmc_info_mem);
+ iwdev->hmc_info_mem = NULL;
+ return status;
}
/**
@@ -1933,7 +1939,7 @@ static int i40iw_virtchnl_receive(struct i40e_info *ldev,
bool i40iw_vf_clear_to_send(struct i40iw_sc_dev *dev)
{
struct i40iw_device *iwdev;
- wait_queue_t wait;
+ wait_queue_entry_t wait;
iwdev = dev->back_dev;
diff --git a/drivers/infiniband/hw/i40iw/i40iw_osdep.h b/drivers/infiniband/hw/i40iw/i40iw_osdep.h
index aa66c1c63dfa..f27be3e7830b 100644
--- a/drivers/infiniband/hw/i40iw/i40iw_osdep.h
+++ b/drivers/infiniband/hw/i40iw/i40iw_osdep.h
@@ -199,7 +199,6 @@ void i40iw_cqp_spawn_worker(struct i40iw_sc_dev *dev,
struct i40iw_virtchnl_work_info *work_info, u32 iw_vf_idx);
void *i40iw_remove_head(struct list_head *list);
void i40iw_qp_suspend_resume(struct i40iw_sc_dev *dev, struct i40iw_sc_qp *qp, bool suspend);
-void i40iw_qp_mss_modify(struct i40iw_sc_dev *dev, struct i40iw_sc_qp *qp);
void i40iw_term_modify_qp(struct i40iw_sc_qp *qp, u8 next_state, u8 term, u8 term_len);
void i40iw_terminate_done(struct i40iw_sc_qp *qp, int timeout_occurred);
diff --git a/drivers/infiniband/hw/i40iw/i40iw_type.h b/drivers/infiniband/hw/i40iw/i40iw_type.h
index 7b76259752b0..959ec81fba99 100644
--- a/drivers/infiniband/hw/i40iw/i40iw_type.h
+++ b/drivers/infiniband/hw/i40iw/i40iw_type.h
@@ -541,7 +541,6 @@ struct i40iw_create_qp_info {
struct i40iw_modify_qp_info {
u64 rx_win0;
u64 rx_win1;
- u16 new_mss;
u8 next_iwarp_state;
u8 termlen;
bool ord_valid;
@@ -554,7 +553,6 @@ struct i40iw_modify_qp_info {
bool dont_send_term;
bool dont_send_fin;
bool cached_var_valid;
- bool mss_change;
bool force_loopback;
};
diff --git a/drivers/infiniband/hw/i40iw/i40iw_utils.c b/drivers/infiniband/hw/i40iw/i40iw_utils.c
index 409a3781e735..56d986924a4c 100644
--- a/drivers/infiniband/hw/i40iw/i40iw_utils.c
+++ b/drivers/infiniband/hw/i40iw/i40iw_utils.c
@@ -757,23 +757,6 @@ void i40iw_qp_suspend_resume(struct i40iw_sc_dev *dev, struct i40iw_sc_qp *qp, b
}
/**
- * i40iw_qp_mss_modify - modify mss for qp
- * @dev: hardware control device structure
- * @qp: hardware control qp
- */
-void i40iw_qp_mss_modify(struct i40iw_sc_dev *dev, struct i40iw_sc_qp *qp)
-{
- struct i40iw_device *iwdev = (struct i40iw_device *)dev->back_dev;
- struct i40iw_qp *iwqp = (struct i40iw_qp *)qp->back_qp;
- struct i40iw_modify_qp_info info;
-
- memset(&info, 0, sizeof(info));
- info.mss_change = true;
- info.new_mss = qp->vsi->mss;
- i40iw_hw_modify_qp(iwdev, iwqp, &info, false);
-}
-
-/**
* i40iw_term_modify_qp - modify qp for term message
* @qp: hardware control qp
* @next_state: qp's next state
diff --git a/drivers/infiniband/hw/i40iw/i40iw_virtchnl.c b/drivers/infiniband/hw/i40iw/i40iw_virtchnl.c
index f4d13683a403..48fd327f876b 100644
--- a/drivers/infiniband/hw/i40iw/i40iw_virtchnl.c
+++ b/drivers/infiniband/hw/i40iw/i40iw_virtchnl.c
@@ -443,10 +443,7 @@ enum i40iw_status_code i40iw_vchnl_recv_pf(struct i40iw_sc_dev *dev,
if (!dev->vchnl_up)
return I40IW_ERR_NOT_READY;
if (vchnl_msg->iw_op_code == I40IW_VCHNL_OP_GET_VER) {
- if (vchnl_msg->iw_op_ver != I40IW_VCHNL_OP_GET_VER_V0)
- vchnl_pf_send_get_ver_resp(dev, vf_id, vchnl_msg);
- else
- vchnl_pf_send_get_ver_resp(dev, vf_id, vchnl_msg);
+ vchnl_pf_send_get_ver_resp(dev, vf_id, vchnl_msg);
return I40IW_SUCCESS;
}
for (iw_vf_idx = 0; iw_vf_idx < I40IW_MAX_PE_ENABLED_VF_COUNT; iw_vf_idx++) {
diff --git a/drivers/infiniband/hw/mlx4/mad.c b/drivers/infiniband/hw/mlx4/mad.c
index b4694717f6f3..21d31cb1325f 100644
--- a/drivers/infiniband/hw/mlx4/mad.c
+++ b/drivers/infiniband/hw/mlx4/mad.c
@@ -1578,6 +1578,7 @@ static void mlx4_ib_multiplex_mad(struct mlx4_ib_demux_pv_ctx *ctx, struct ib_wc
if (port < 0)
return;
ah.av.ib.port_pd = cpu_to_be32(port << 24 | (be32_to_cpu(ah.av.ib.port_pd) & 0xffffff));
+ ah.ibah.type = rdma_ah_find_type(&dev->ib_dev, port);
mlx4_ib_query_ah(&ah.ibah, &ah_attr);
if (rdma_ah_get_ah_flags(&ah_attr) & IB_AH_GRH)
diff --git a/drivers/infiniband/hw/mlx5/main.c b/drivers/infiniband/hw/mlx5/main.c
index d45772da0963..9ecc089d4529 100644
--- a/drivers/infiniband/hw/mlx5/main.c
+++ b/drivers/infiniband/hw/mlx5/main.c
@@ -2979,6 +2979,18 @@ error_0:
return ret;
}
+static u8 mlx5_get_umr_fence(u8 umr_fence_cap)
+{
+ switch (umr_fence_cap) {
+ case MLX5_CAP_UMR_FENCE_NONE:
+ return MLX5_FENCE_MODE_NONE;
+ case MLX5_CAP_UMR_FENCE_SMALL:
+ return MLX5_FENCE_MODE_INITIATOR_SMALL;
+ default:
+ return MLX5_FENCE_MODE_STRONG_ORDERING;
+ }
+}
+
static int create_dev_resources(struct mlx5_ib_resources *devr)
{
struct ib_srq_init_attr attr;
@@ -3680,8 +3692,10 @@ static void *mlx5_ib_add(struct mlx5_core_dev *mdev)
dev->ib_dev.check_mr_status = mlx5_ib_check_mr_status;
dev->ib_dev.get_port_immutable = mlx5_port_immutable;
dev->ib_dev.get_dev_fw_str = get_dev_fw_str;
- dev->ib_dev.alloc_rdma_netdev = mlx5_ib_alloc_rdma_netdev;
- dev->ib_dev.free_rdma_netdev = mlx5_ib_free_rdma_netdev;
+ if (MLX5_CAP_GEN(mdev, ipoib_enhanced_offloads)) {
+ dev->ib_dev.alloc_rdma_netdev = mlx5_ib_alloc_rdma_netdev;
+ dev->ib_dev.free_rdma_netdev = mlx5_ib_free_rdma_netdev;
+ }
if (mlx5_core_is_pf(mdev)) {
dev->ib_dev.get_vf_config = mlx5_ib_get_vf_config;
dev->ib_dev.set_vf_link_state = mlx5_ib_set_vf_link_state;
@@ -3693,6 +3707,8 @@ static void *mlx5_ib_add(struct mlx5_core_dev *mdev)
mlx5_ib_internal_fill_odp_caps(dev);
+ dev->umr_fence = mlx5_get_umr_fence(MLX5_CAP_GEN(mdev, umr_fence));
+
if (MLX5_CAP_GEN(mdev, imaicl)) {
dev->ib_dev.alloc_mw = mlx5_ib_alloc_mw;
dev->ib_dev.dealloc_mw = mlx5_ib_dealloc_mw;
diff --git a/drivers/infiniband/hw/mlx5/mlx5_ib.h b/drivers/infiniband/hw/mlx5/mlx5_ib.h
index 38c877bc45e5..bdcf25410c99 100644
--- a/drivers/infiniband/hw/mlx5/mlx5_ib.h
+++ b/drivers/infiniband/hw/mlx5/mlx5_ib.h
@@ -349,7 +349,7 @@ struct mlx5_ib_qp {
struct mlx5_ib_wq rq;
u8 sq_signal_bits;
- u8 fm_cache;
+ u8 next_fence;
struct mlx5_ib_wq sq;
/* serialize qp state modifications
@@ -654,6 +654,7 @@ struct mlx5_ib_dev {
struct mlx5_ib_port *port;
struct mlx5_sq_bfreg bfreg;
struct mlx5_sq_bfreg fp_bfreg;
+ u8 umr_fence;
};
static inline struct mlx5_ib_cq *to_mibcq(struct mlx5_core_cq *mcq)
diff --git a/drivers/infiniband/hw/mlx5/qp.c b/drivers/infiniband/hw/mlx5/qp.c
index 93959e1e43a3..ebb6768684de 100644
--- a/drivers/infiniband/hw/mlx5/qp.c
+++ b/drivers/infiniband/hw/mlx5/qp.c
@@ -3738,24 +3738,6 @@ static void dump_wqe(struct mlx5_ib_qp *qp, int idx, int size_16)
}
}
-static u8 get_fence(u8 fence, struct ib_send_wr *wr)
-{
- if (unlikely(wr->opcode == IB_WR_LOCAL_INV &&
- wr->send_flags & IB_SEND_FENCE))
- return MLX5_FENCE_MODE_STRONG_ORDERING;
-
- if (unlikely(fence)) {
- if (wr->send_flags & IB_SEND_FENCE)
- return MLX5_FENCE_MODE_SMALL_AND_FENCE;
- else
- return fence;
- } else if (unlikely(wr->send_flags & IB_SEND_FENCE)) {
- return MLX5_FENCE_MODE_FENCE;
- }
-
- return 0;
-}
-
static int begin_wqe(struct mlx5_ib_qp *qp, void **seg,
struct mlx5_wqe_ctrl_seg **ctrl,
struct ib_send_wr *wr, unsigned *idx,
@@ -3784,8 +3766,7 @@ static int begin_wqe(struct mlx5_ib_qp *qp, void **seg,
static void finish_wqe(struct mlx5_ib_qp *qp,
struct mlx5_wqe_ctrl_seg *ctrl,
u8 size, unsigned idx, u64 wr_id,
- int nreq, u8 fence, u8 next_fence,
- u32 mlx5_opcode)
+ int nreq, u8 fence, u32 mlx5_opcode)
{
u8 opmod = 0;
@@ -3793,7 +3774,6 @@ static void finish_wqe(struct mlx5_ib_qp *qp,
mlx5_opcode | ((u32)opmod << 24));
ctrl->qpn_ds = cpu_to_be32(size | (qp->trans_qp.base.mqp.qpn << 8));
ctrl->fm_ce_se |= fence;
- qp->fm_cache = next_fence;
if (unlikely(qp->wq_sig))
ctrl->signature = wq_sig(ctrl);
@@ -3853,7 +3833,6 @@ int mlx5_ib_post_send(struct ib_qp *ibqp, struct ib_send_wr *wr,
goto out;
}
- fence = qp->fm_cache;
num_sge = wr->num_sge;
if (unlikely(num_sge > qp->sq.max_gs)) {
mlx5_ib_warn(dev, "\n");
@@ -3870,6 +3849,19 @@ int mlx5_ib_post_send(struct ib_qp *ibqp, struct ib_send_wr *wr,
goto out;
}
+ if (wr->opcode == IB_WR_LOCAL_INV ||
+ wr->opcode == IB_WR_REG_MR) {
+ fence = dev->umr_fence;
+ next_fence = MLX5_FENCE_MODE_INITIATOR_SMALL;
+ } else if (wr->send_flags & IB_SEND_FENCE) {
+ if (qp->next_fence)
+ fence = MLX5_FENCE_MODE_SMALL_AND_FENCE;
+ else
+ fence = MLX5_FENCE_MODE_FENCE;
+ } else {
+ fence = qp->next_fence;
+ }
+
switch (ibqp->qp_type) {
case IB_QPT_XRC_INI:
xrc = seg;
@@ -3896,7 +3888,6 @@ int mlx5_ib_post_send(struct ib_qp *ibqp, struct ib_send_wr *wr,
goto out;
case IB_WR_LOCAL_INV:
- next_fence = MLX5_FENCE_MODE_INITIATOR_SMALL;
qp->sq.wr_data[idx] = IB_WR_LOCAL_INV;
ctrl->imm = cpu_to_be32(wr->ex.invalidate_rkey);
set_linv_wr(qp, &seg, &size);
@@ -3904,7 +3895,6 @@ int mlx5_ib_post_send(struct ib_qp *ibqp, struct ib_send_wr *wr,
break;
case IB_WR_REG_MR:
- next_fence = MLX5_FENCE_MODE_INITIATOR_SMALL;
qp->sq.wr_data[idx] = IB_WR_REG_MR;
ctrl->imm = cpu_to_be32(reg_wr(wr)->key);
err = set_reg_wr(qp, reg_wr(wr), &seg, &size);
@@ -3927,9 +3917,8 @@ int mlx5_ib_post_send(struct ib_qp *ibqp, struct ib_send_wr *wr,
goto out;
}
- finish_wqe(qp, ctrl, size, idx, wr->wr_id,
- nreq, get_fence(fence, wr),
- next_fence, MLX5_OPCODE_UMR);
+ finish_wqe(qp, ctrl, size, idx, wr->wr_id, nreq,
+ fence, MLX5_OPCODE_UMR);
/*
* SET_PSV WQEs are not signaled and solicited
* on error
@@ -3954,9 +3943,8 @@ int mlx5_ib_post_send(struct ib_qp *ibqp, struct ib_send_wr *wr,
goto out;
}
- finish_wqe(qp, ctrl, size, idx, wr->wr_id,
- nreq, get_fence(fence, wr),
- next_fence, MLX5_OPCODE_SET_PSV);
+ finish_wqe(qp, ctrl, size, idx, wr->wr_id, nreq,
+ fence, MLX5_OPCODE_SET_PSV);
err = begin_wqe(qp, &seg, &ctrl, wr,
&idx, &size, nreq);
if (err) {
@@ -3966,7 +3954,6 @@ int mlx5_ib_post_send(struct ib_qp *ibqp, struct ib_send_wr *wr,
goto out;
}
- next_fence = MLX5_FENCE_MODE_INITIATOR_SMALL;
err = set_psv_wr(&sig_handover_wr(wr)->sig_attrs->wire,
mr->sig->psv_wire.psv_idx, &seg,
&size);
@@ -3976,9 +3963,9 @@ int mlx5_ib_post_send(struct ib_qp *ibqp, struct ib_send_wr *wr,
goto out;
}
- finish_wqe(qp, ctrl, size, idx, wr->wr_id,
- nreq, get_fence(fence, wr),
- next_fence, MLX5_OPCODE_SET_PSV);
+ finish_wqe(qp, ctrl, size, idx, wr->wr_id, nreq,
+ fence, MLX5_OPCODE_SET_PSV);
+ qp->next_fence = MLX5_FENCE_MODE_INITIATOR_SMALL;
num_sge = 0;
goto skip_psv;
@@ -4089,8 +4076,8 @@ int mlx5_ib_post_send(struct ib_qp *ibqp, struct ib_send_wr *wr,
}
}
- finish_wqe(qp, ctrl, size, idx, wr->wr_id, nreq,
- get_fence(fence, wr), next_fence,
+ qp->next_fence = next_fence;
+ finish_wqe(qp, ctrl, size, idx, wr->wr_id, nreq, fence,
mlx5_ib_opcode[wr->opcode]);
skip_psv:
if (0)
diff --git a/drivers/infiniband/hw/nes/nes_cm.c b/drivers/infiniband/hw/nes/nes_cm.c
index fb983df7c157..30b256a2c54e 100644
--- a/drivers/infiniband/hw/nes/nes_cm.c
+++ b/drivers/infiniband/hw/nes/nes_cm.c
@@ -610,7 +610,6 @@ static void build_mpa_v2(struct nes_cm_node *cm_node,
ctrl_ord = cm_node->ord_size & IETF_NO_IRD_ORD;
}
ctrl_ird |= IETF_PEER_TO_PEER;
- ctrl_ird |= IETF_FLPDU_ZERO_LEN;
switch (mpa_key) {
case MPA_KEY_REQUEST:
@@ -1826,7 +1825,7 @@ static void handle_rcv_mpa(struct nes_cm_node *cm_node, struct sk_buff *skb)
type = NES_CM_EVENT_CONNECTED;
cm_node->state = NES_CM_STATE_TSA;
}
-
+ send_ack(cm_node, NULL);
break;
default:
WARN_ON(1);
diff --git a/drivers/infiniband/hw/qedr/qedr.h b/drivers/infiniband/hw/qedr/qedr.h
index aa08c76a4245..d961f79b317c 100644
--- a/drivers/infiniband/hw/qedr/qedr.h
+++ b/drivers/infiniband/hw/qedr/qedr.h
@@ -58,7 +58,10 @@
#define QEDR_MSG_QP " QP"
#define QEDR_MSG_GSI " GSI"
-#define QEDR_CQ_MAGIC_NUMBER (0x11223344)
+#define QEDR_CQ_MAGIC_NUMBER (0x11223344)
+
+#define FW_PAGE_SIZE (RDMA_RING_PAGE_SIZE)
+#define FW_PAGE_SHIFT (12)
struct qedr_dev;
diff --git a/drivers/infiniband/hw/qedr/qedr_cm.c b/drivers/infiniband/hw/qedr/qedr_cm.c
index 3d7705cec770..d86dbe814d98 100644
--- a/drivers/infiniband/hw/qedr/qedr_cm.c
+++ b/drivers/infiniband/hw/qedr/qedr_cm.c
@@ -270,11 +270,13 @@ static inline int qedr_gsi_build_header(struct qedr_dev *dev,
return rc;
}
- vlan_id = rdma_vlan_dev_vlan_id(sgid_attr.ndev);
- if (vlan_id < VLAN_CFI_MASK)
- has_vlan = true;
- if (sgid_attr.ndev)
+ if (sgid_attr.ndev) {
+ vlan_id = rdma_vlan_dev_vlan_id(sgid_attr.ndev);
+ if (vlan_id < VLAN_CFI_MASK)
+ has_vlan = true;
+
dev_put(sgid_attr.ndev);
+ }
if (!memcmp(&sgid, &zgid, sizeof(sgid))) {
DP_ERR(dev, "gsi post send: GID not found GID index %d\n",
diff --git a/drivers/infiniband/hw/qedr/verbs.c b/drivers/infiniband/hw/qedr/verbs.c
index 17685cfea6a2..d6723c365c7f 100644
--- a/drivers/infiniband/hw/qedr/verbs.c
+++ b/drivers/infiniband/hw/qedr/verbs.c
@@ -653,14 +653,15 @@ static int qedr_prepare_pbl_tbl(struct qedr_dev *dev,
static void qedr_populate_pbls(struct qedr_dev *dev, struct ib_umem *umem,
struct qedr_pbl *pbl,
- struct qedr_pbl_info *pbl_info)
+ struct qedr_pbl_info *pbl_info, u32 pg_shift)
{
int shift, pg_cnt, pages, pbe_cnt, total_num_pbes = 0;
+ u32 fw_pg_cnt, fw_pg_per_umem_pg;
struct qedr_pbl *pbl_tbl;
struct scatterlist *sg;
struct regpair *pbe;
+ u64 pg_addr;
int entry;
- u32 addr;
if (!pbl_info->num_pbes)
return;
@@ -683,29 +684,35 @@ static void qedr_populate_pbls(struct qedr_dev *dev, struct ib_umem *umem,
shift = umem->page_shift;
+ fw_pg_per_umem_pg = BIT(umem->page_shift - pg_shift);
+
for_each_sg(umem->sg_head.sgl, sg, umem->nmap, entry) {
pages = sg_dma_len(sg) >> shift;
+ pg_addr = sg_dma_address(sg);
for (pg_cnt = 0; pg_cnt < pages; pg_cnt++) {
- /* store the page address in pbe */
- pbe->lo = cpu_to_le32(sg_dma_address(sg) +
- (pg_cnt << shift));
- addr = upper_32_bits(sg_dma_address(sg) +
- (pg_cnt << shift));
- pbe->hi = cpu_to_le32(addr);
- pbe_cnt++;
- total_num_pbes++;
- pbe++;
-
- if (total_num_pbes == pbl_info->num_pbes)
- return;
-
- /* If the given pbl is full storing the pbes,
- * move to next pbl.
- */
- if (pbe_cnt == (pbl_info->pbl_size / sizeof(u64))) {
- pbl_tbl++;
- pbe = (struct regpair *)pbl_tbl->va;
- pbe_cnt = 0;
+ for (fw_pg_cnt = 0; fw_pg_cnt < fw_pg_per_umem_pg;) {
+ pbe->lo = cpu_to_le32(pg_addr);
+ pbe->hi = cpu_to_le32(upper_32_bits(pg_addr));
+
+ pg_addr += BIT(pg_shift);
+ pbe_cnt++;
+ total_num_pbes++;
+ pbe++;
+
+ if (total_num_pbes == pbl_info->num_pbes)
+ return;
+
+ /* If the given pbl is full storing the pbes,
+ * move to next pbl.
+ */
+ if (pbe_cnt ==
+ (pbl_info->pbl_size / sizeof(u64))) {
+ pbl_tbl++;
+ pbe = (struct regpair *)pbl_tbl->va;
+ pbe_cnt = 0;
+ }
+
+ fw_pg_cnt++;
}
}
}
@@ -754,7 +761,7 @@ static inline int qedr_init_user_queue(struct ib_ucontext *ib_ctx,
u64 buf_addr, size_t buf_len,
int access, int dmasync)
{
- int page_cnt;
+ u32 fw_pages;
int rc;
q->buf_addr = buf_addr;
@@ -766,8 +773,10 @@ static inline int qedr_init_user_queue(struct ib_ucontext *ib_ctx,
return PTR_ERR(q->umem);
}
- page_cnt = ib_umem_page_count(q->umem);
- rc = qedr_prepare_pbl_tbl(dev, &q->pbl_info, page_cnt, 0);
+ fw_pages = ib_umem_page_count(q->umem) <<
+ (q->umem->page_shift - FW_PAGE_SHIFT);
+
+ rc = qedr_prepare_pbl_tbl(dev, &q->pbl_info, fw_pages, 0);
if (rc)
goto err0;
@@ -777,7 +786,8 @@ static inline int qedr_init_user_queue(struct ib_ucontext *ib_ctx,
goto err0;
}
- qedr_populate_pbls(dev, q->umem, q->pbl_tbl, &q->pbl_info);
+ qedr_populate_pbls(dev, q->umem, q->pbl_tbl, &q->pbl_info,
+ FW_PAGE_SHIFT);
return 0;
@@ -2226,7 +2236,7 @@ struct ib_mr *qedr_reg_user_mr(struct ib_pd *ibpd, u64 start, u64 len,
goto err1;
qedr_populate_pbls(dev, mr->umem, mr->info.pbl_table,
- &mr->info.pbl_info);
+ &mr->info.pbl_info, mr->umem->page_shift);
rc = dev->ops->rdma_alloc_tid(dev->rdma_ctx, &mr->hw_mr.itid);
if (rc) {
@@ -3209,6 +3219,10 @@ static int process_req(struct qedr_dev *dev, struct qedr_qp *qp,
case IB_WC_REG_MR:
qp->wqe_wr_id[qp->sq.cons].mr->info.completed++;
break;
+ case IB_WC_RDMA_READ:
+ case IB_WC_SEND:
+ wc->byte_len = qp->wqe_wr_id[qp->sq.cons].bytes_len;
+ break;
default:
break;
}
diff --git a/drivers/infiniband/hw/qib/qib_rc.c b/drivers/infiniband/hw/qib/qib_rc.c
index fc8b88514da5..4ddbcac5eabe 100644
--- a/drivers/infiniband/hw/qib/qib_rc.c
+++ b/drivers/infiniband/hw/qib/qib_rc.c
@@ -1956,8 +1956,10 @@ send_last:
ret = qib_get_rwqe(qp, 1);
if (ret < 0)
goto nack_op_err;
- if (!ret)
+ if (!ret) {
+ rvt_put_ss(&qp->r_sge);
goto rnr_nak;
+ }
wc.ex.imm_data = ohdr->u.rc.imm_data;
hdrsize += 4;
wc.wc_flags = IB_WC_WITH_IMM;
diff --git a/drivers/infiniband/sw/rxe/rxe.h b/drivers/infiniband/sw/rxe/rxe.h
index ecdba2fce083..1ac5b8551a4d 100644
--- a/drivers/infiniband/sw/rxe/rxe.h
+++ b/drivers/infiniband/sw/rxe/rxe.h
@@ -68,6 +68,7 @@
static inline u32 rxe_crc32(struct rxe_dev *rxe,
u32 crc, void *next, size_t len)
{
+ u32 retval;
int err;
SHASH_DESC_ON_STACK(shash, rxe->tfm);
@@ -81,7 +82,9 @@ static inline u32 rxe_crc32(struct rxe_dev *rxe,
return crc32_le(crc, next, len);
}
- return *(u32 *)shash_desc_ctx(shash);
+ retval = *(u32 *)shash_desc_ctx(shash);
+ barrier_data(shash_desc_ctx(shash));
+ return retval;
}
int rxe_set_mtu(struct rxe_dev *rxe, unsigned int dev_mtu);
diff --git a/drivers/infiniband/sw/rxe/rxe_verbs.c b/drivers/infiniband/sw/rxe/rxe_verbs.c
index 83d709e74dfb..073e66783f1d 100644
--- a/drivers/infiniband/sw/rxe/rxe_verbs.c
+++ b/drivers/infiniband/sw/rxe/rxe_verbs.c
@@ -740,13 +740,8 @@ static int init_send_wqe(struct rxe_qp *qp, struct ib_send_wr *ibwr,
sge = ibwr->sg_list;
for (i = 0; i < num_sge; i++, sge++) {
- if (qp->is_user && copy_from_user(p, (__user void *)
- (uintptr_t)sge->addr, sge->length))
- return -EFAULT;
-
- else if (!qp->is_user)
- memcpy(p, (void *)(uintptr_t)sge->addr,
- sge->length);
+ memcpy(p, (void *)(uintptr_t)sge->addr,
+ sge->length);
p += sge->length;
}
diff --git a/drivers/infiniband/ulp/ipoib/ipoib_ethtool.c b/drivers/infiniband/ulp/ipoib/ipoib_ethtool.c
index 874b24366e4d..7871379342f4 100644
--- a/drivers/infiniband/ulp/ipoib/ipoib_ethtool.c
+++ b/drivers/infiniband/ulp/ipoib/ipoib_ethtool.c
@@ -178,7 +178,7 @@ static inline int ib_speed_enum_to_int(int speed)
static int ipoib_get_link_ksettings(struct net_device *netdev,
struct ethtool_link_ksettings *cmd)
{
- struct ipoib_dev_priv *priv = netdev_priv(netdev);
+ struct ipoib_dev_priv *priv = ipoib_priv(netdev);
struct ib_port_attr attr;
int ret, speed, width;
diff --git a/drivers/infiniband/ulp/ipoib/ipoib_ib.c b/drivers/infiniband/ulp/ipoib/ipoib_ib.c
index 0060b2f9f659..efe7402f4885 100644
--- a/drivers/infiniband/ulp/ipoib/ipoib_ib.c
+++ b/drivers/infiniband/ulp/ipoib/ipoib_ib.c
@@ -863,7 +863,6 @@ dev_stop:
set_bit(IPOIB_STOP_REAPER, &priv->flags);
cancel_delayed_work(&priv->ah_reap_task);
set_bit(IPOIB_FLAG_INITIALIZED, &priv->flags);
- napi_enable(&priv->napi);
ipoib_ib_dev_stop(dev);
return -1;
}
diff --git a/drivers/infiniband/ulp/ipoib/ipoib_main.c b/drivers/infiniband/ulp/ipoib/ipoib_main.c
index 2869d1adb1de..1015a63de6ae 100644
--- a/drivers/infiniband/ulp/ipoib/ipoib_main.c
+++ b/drivers/infiniband/ulp/ipoib/ipoib_main.c
@@ -1590,12 +1590,14 @@ static void ipoib_neigh_hash_uninit(struct net_device *dev)
wait_for_completion(&priv->ntbl.deleted);
}
-void ipoib_dev_uninit_default(struct net_device *dev)
+static void ipoib_dev_uninit_default(struct net_device *dev)
{
struct ipoib_dev_priv *priv = ipoib_priv(dev);
ipoib_transport_dev_cleanup(dev);
+ netif_napi_del(&priv->napi);
+
ipoib_cm_dev_cleanup(dev);
kfree(priv->rx_ring);
@@ -1649,6 +1651,7 @@ out_rx_ring_cleanup:
kfree(priv->rx_ring);
out:
+ netif_napi_del(&priv->napi);
return -ENOMEM;
}
@@ -2237,6 +2240,7 @@ event_failed:
device_init_failed:
free_netdev(priv->dev);
+ kfree(priv);
alloc_mem_failed:
return ERR_PTR(result);
@@ -2277,7 +2281,7 @@ static void ipoib_add_one(struct ib_device *device)
static void ipoib_remove_one(struct ib_device *device, void *client_data)
{
- struct ipoib_dev_priv *priv, *tmp;
+ struct ipoib_dev_priv *priv, *tmp, *cpriv, *tcpriv;
struct list_head *dev_list = client_data;
if (!dev_list)
@@ -2300,7 +2304,14 @@ static void ipoib_remove_one(struct ib_device *device, void *client_data)
flush_workqueue(priv->wq);
unregister_netdev(priv->dev);
- free_netdev(priv->dev);
+ if (device->free_rdma_netdev)
+ device->free_rdma_netdev(priv->dev);
+ else
+ free_netdev(priv->dev);
+
+ list_for_each_entry_safe(cpriv, tcpriv, &priv->child_intfs, list)
+ kfree(cpriv);
+
kfree(priv);
}
diff --git a/drivers/infiniband/ulp/ipoib/ipoib_vlan.c b/drivers/infiniband/ulp/ipoib/ipoib_vlan.c
index 36dc4fcaa3cd..081b33deff1b 100644
--- a/drivers/infiniband/ulp/ipoib/ipoib_vlan.c
+++ b/drivers/infiniband/ulp/ipoib/ipoib_vlan.c
@@ -133,13 +133,13 @@ int ipoib_vlan_add(struct net_device *pdev, unsigned short pkey)
snprintf(intf_name, sizeof intf_name, "%s.%04x",
ppriv->dev->name, pkey);
+ if (!rtnl_trylock())
+ return restart_syscall();
+
priv = ipoib_intf_alloc(ppriv->ca, ppriv->port, intf_name);
if (!priv)
return -ENOMEM;
- if (!rtnl_trylock())
- return restart_syscall();
-
down_write(&ppriv->vlan_rwsem);
/*
@@ -167,8 +167,10 @@ out:
rtnl_unlock();
- if (result)
+ if (result) {
free_netdev(priv->dev);
+ kfree(priv);
+ }
return result;
}
@@ -209,6 +211,7 @@ int ipoib_vlan_delete(struct net_device *pdev, unsigned short pkey)
if (dev) {
free_netdev(dev);
+ kfree(priv);
return 0;
}
diff --git a/drivers/infiniband/ulp/srp/ib_srp.c b/drivers/infiniband/ulp/srp/ib_srp.c
index def723a5df29..2354c742caa1 100644
--- a/drivers/infiniband/ulp/srp/ib_srp.c
+++ b/drivers/infiniband/ulp/srp/ib_srp.c
@@ -320,7 +320,7 @@ static int srp_new_cm_id(struct srp_rdma_ch *ch)
ch->path.sgid = target->sgid;
ch->path.dgid = target->orig_dgid;
ch->path.pkey = target->pkey;
- sa_path_set_service_id(&ch->path, target->service_id);
+ ch->path.service_id = target->service_id;
return 0;
}
@@ -575,7 +575,7 @@ static int srp_create_ch_ib(struct srp_rdma_ch *ch)
return 0;
err_qp:
- srp_destroy_qp(ch, qp);
+ ib_destroy_qp(qp);
err_send_cq:
ib_free_cq(send_cq);
diff --git a/drivers/input/keyboard/tm2-touchkey.c b/drivers/input/keyboard/tm2-touchkey.c
index 485900f953e0..abc266e40e17 100644
--- a/drivers/input/keyboard/tm2-touchkey.c
+++ b/drivers/input/keyboard/tm2-touchkey.c
@@ -213,7 +213,7 @@ static int tm2_touchkey_probe(struct i2c_client *client,
/* led device */
touchkey->led_dev.name = TM2_TOUCHKEY_DEV_NAME;
touchkey->led_dev.brightness = LED_FULL;
- touchkey->led_dev.max_brightness = LED_FULL;
+ touchkey->led_dev.max_brightness = LED_ON;
touchkey->led_dev.brightness_set = tm2_touchkey_led_brightness_set;
error = devm_led_classdev_register(&client->dev, &touchkey->led_dev);
diff --git a/drivers/input/misc/axp20x-pek.c b/drivers/input/misc/axp20x-pek.c
index f11807db6979..400869e61a06 100644
--- a/drivers/input/misc/axp20x-pek.c
+++ b/drivers/input/misc/axp20x-pek.c
@@ -256,6 +256,42 @@ static int axp20x_pek_probe_input_device(struct axp20x_pek *axp20x_pek,
return 0;
}
+#ifdef CONFIG_ACPI
+static bool axp20x_pek_should_register_input(struct axp20x_pek *axp20x_pek,
+ struct platform_device *pdev)
+{
+ unsigned long long hrv = 0;
+ acpi_status status;
+
+ if (IS_ENABLED(CONFIG_INPUT_SOC_BUTTON_ARRAY) &&
+ axp20x_pek->axp20x->variant == AXP288_ID) {
+ status = acpi_evaluate_integer(ACPI_HANDLE(pdev->dev.parent),
+ "_HRV", NULL, &hrv);
+ if (ACPI_FAILURE(status))
+ dev_err(&pdev->dev, "Failed to get PMIC hardware revision\n");
+
+ /*
+ * On Cherry Trail platforms (hrv == 3), do not register the
+ * input device if there is an "INTCFD9" or "ACPI0011" gpio
+ * button ACPI device, as that handles the power button too,
+ * and otherwise we end up reporting all presses twice.
+ */
+ if (hrv == 3 && (acpi_dev_present("INTCFD9", NULL, -1) ||
+ acpi_dev_present("ACPI0011", NULL, -1)))
+ return false;
+
+ }
+
+ return true;
+}
+#else
+static bool axp20x_pek_should_register_input(struct axp20x_pek *axp20x_pek,
+ struct platform_device *pdev)
+{
+ return true;
+}
+#endif
+
static int axp20x_pek_probe(struct platform_device *pdev)
{
struct axp20x_pek *axp20x_pek;
@@ -268,13 +304,7 @@ static int axp20x_pek_probe(struct platform_device *pdev)
axp20x_pek->axp20x = dev_get_drvdata(pdev->dev.parent);
- /*
- * Do not register the input device if there is an "INTCFD9"
- * gpio button ACPI device, that handles the power button too,
- * and otherwise we end up reporting all presses twice.
- */
- if (!acpi_dev_found("INTCFD9") ||
- !IS_ENABLED(CONFIG_INPUT_SOC_BUTTON_ARRAY)) {
+ if (axp20x_pek_should_register_input(axp20x_pek, pdev)) {
error = axp20x_pek_probe_input_device(axp20x_pek, pdev);
if (error)
return error;
diff --git a/drivers/input/misc/soc_button_array.c b/drivers/input/misc/soc_button_array.c
index e37d37273182..f600f3a7a3c6 100644
--- a/drivers/input/misc/soc_button_array.c
+++ b/drivers/input/misc/soc_button_array.c
@@ -248,7 +248,8 @@ static struct soc_button_info *soc_button_get_button_info(struct device *dev)
if (!btns_desc) {
dev_err(dev, "ACPI Button Descriptors not found\n");
- return ERR_PTR(-ENODEV);
+ button_info = ERR_PTR(-ENODEV);
+ goto out;
}
/* The first package describes the collection */
@@ -264,24 +265,31 @@ static struct soc_button_info *soc_button_get_button_info(struct device *dev)
}
if (collection_uid == -1) {
dev_err(dev, "Invalid Button Collection Descriptor\n");
- return ERR_PTR(-ENODEV);
+ button_info = ERR_PTR(-ENODEV);
+ goto out;
}
/* There are package.count - 1 buttons + 1 terminating empty entry */
button_info = devm_kcalloc(dev, btns_desc->package.count,
sizeof(*button_info), GFP_KERNEL);
- if (!button_info)
- return ERR_PTR(-ENOMEM);
+ if (!button_info) {
+ button_info = ERR_PTR(-ENOMEM);
+ goto out;
+ }
/* Parse the button descriptors */
for (i = 1, btn = 0; i < btns_desc->package.count; i++, btn++) {
if (soc_button_parse_btn_desc(dev,
&btns_desc->package.elements[i],
collection_uid,
- &button_info[btn]))
- return ERR_PTR(-ENODEV);
+ &button_info[btn])) {
+ button_info = ERR_PTR(-ENODEV);
+ goto out;
+ }
}
+out:
+ kfree(buf.pointer);
return button_info;
}
diff --git a/drivers/input/mouse/elan_i2c_i2c.c b/drivers/input/mouse/elan_i2c_i2c.c
index a679e56c44cd..f431da07f861 100644
--- a/drivers/input/mouse/elan_i2c_i2c.c
+++ b/drivers/input/mouse/elan_i2c_i2c.c
@@ -554,32 +554,34 @@ static int elan_i2c_finish_fw_update(struct i2c_client *client,
struct completion *completion)
{
struct device *dev = &client->dev;
- long ret;
int error;
int len;
- u8 buffer[ETP_I2C_INF_LENGTH];
+ u8 buffer[ETP_I2C_REPORT_LEN];
+
+ len = i2c_master_recv(client, buffer, ETP_I2C_REPORT_LEN);
+ if (len != ETP_I2C_REPORT_LEN) {
+ error = len < 0 ? len : -EIO;
+ dev_warn(dev, "failed to read I2C data after FW WDT reset: %d (%d)\n",
+ error, len);
+ }
reinit_completion(completion);
enable_irq(client->irq);
error = elan_i2c_write_cmd(client, ETP_I2C_STAND_CMD, ETP_I2C_RESET);
- if (!error)
- ret = wait_for_completion_interruptible_timeout(completion,
- msecs_to_jiffies(300));
- disable_irq(client->irq);
-
if (error) {
dev_err(dev, "device reset failed: %d\n", error);
- return error;
- } else if (ret == 0) {
+ } else if (!wait_for_completion_timeout(completion,
+ msecs_to_jiffies(300))) {
dev_err(dev, "timeout waiting for device reset\n");
- return -ETIMEDOUT;
- } else if (ret < 0) {
- error = ret;
- dev_err(dev, "error waiting for device reset: %d\n", error);
- return error;
+ error = -ETIMEDOUT;
}
+ disable_irq(client->irq);
+
+ if (error)
+ return error;
+
len = i2c_master_recv(client, buffer, ETP_I2C_INF_LENGTH);
if (len != ETP_I2C_INF_LENGTH) {
error = len < 0 ? len : -EIO;
diff --git a/drivers/input/mouse/elantech.c b/drivers/input/mouse/elantech.c
index e73d968023f7..f1fa1f172107 100644
--- a/drivers/input/mouse/elantech.c
+++ b/drivers/input/mouse/elantech.c
@@ -1118,8 +1118,10 @@ static int elantech_get_resolution_v4(struct psmouse *psmouse,
* Asus UX32VD 0x361f02 00, 15, 0e clickpad
* Avatar AVIU-145A2 0x361f00 ? clickpad
* Fujitsu LIFEBOOK E544 0x470f00 d0, 12, 09 2 hw buttons
+ * Fujitsu LIFEBOOK E546 0x470f00 50, 12, 09 2 hw buttons
* Fujitsu LIFEBOOK E547 0x470f00 50, 12, 09 2 hw buttons
* Fujitsu LIFEBOOK E554 0x570f01 40, 14, 0c 2 hw buttons
+ * Fujitsu LIFEBOOK E557 0x570f01 40, 14, 0c 2 hw buttons
* Fujitsu T725 0x470f01 05, 12, 09 2 hw buttons
* Fujitsu H730 0x570f00 c0, 14, 0c 3 hw buttons (**)
* Gigabyte U2442 0x450f01 58, 17, 0c 2 hw buttons
@@ -1525,6 +1527,13 @@ static const struct dmi_system_id elantech_dmi_force_crc_enabled[] = {
},
},
{
+ /* Fujitsu LIFEBOOK E546 does not work with crc_enabled == 0 */
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "LIFEBOOK E546"),
+ },
+ },
+ {
/* Fujitsu LIFEBOOK E547 does not work with crc_enabled == 0 */
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU"),
@@ -1546,6 +1555,13 @@ static const struct dmi_system_id elantech_dmi_force_crc_enabled[] = {
},
},
{
+ /* Fujitsu LIFEBOOK E557 does not work with crc_enabled == 0 */
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "LIFEBOOK E557"),
+ },
+ },
+ {
/* Fujitsu LIFEBOOK U745 does not work with crc_enabled == 0 */
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU"),
diff --git a/drivers/input/mouse/synaptics.c b/drivers/input/mouse/synaptics.c
index 131df9d3660f..16c30460ef04 100644
--- a/drivers/input/mouse/synaptics.c
+++ b/drivers/input/mouse/synaptics.c
@@ -176,6 +176,12 @@ static const char * const smbus_pnp_ids[] = {
NULL
};
+static const char * const forcepad_pnp_ids[] = {
+ "SYN300D",
+ "SYN3014",
+ NULL
+};
+
/*
* Send a command to the synpatics touchpad by special commands
*/
@@ -397,6 +403,8 @@ static int synaptics_query_hardware(struct psmouse *psmouse,
{
int error;
+ memset(info, 0, sizeof(*info));
+
error = synaptics_identify(psmouse, info);
if (error)
return error;
@@ -480,13 +488,6 @@ static const struct min_max_quirk min_max_pnpid_table[] = {
{ }
};
-/* This list has been kindly provided by Synaptics. */
-static const char * const forcepad_pnp_ids[] = {
- "SYN300D",
- "SYN3014",
- NULL
-};
-
/*****************************************************************************
* Synaptics communications functions
****************************************************************************/
@@ -1687,7 +1688,8 @@ enum {
SYNAPTICS_INTERTOUCH_ON,
};
-static int synaptics_intertouch = SYNAPTICS_INTERTOUCH_NOT_SET;
+static int synaptics_intertouch = IS_ENABLED(CONFIG_RMI4_SMB) ?
+ SYNAPTICS_INTERTOUCH_NOT_SET : SYNAPTICS_INTERTOUCH_OFF;
module_param_named(synaptics_intertouch, synaptics_intertouch, int, 0644);
MODULE_PARM_DESC(synaptics_intertouch, "Use a secondary bus for the Synaptics device.");
@@ -1737,8 +1739,16 @@ static int synaptics_setup_intertouch(struct psmouse *psmouse,
if (synaptics_intertouch == SYNAPTICS_INTERTOUCH_NOT_SET) {
if (!psmouse_matches_pnp_id(psmouse, topbuttonpad_pnp_ids) &&
- !psmouse_matches_pnp_id(psmouse, smbus_pnp_ids))
+ !psmouse_matches_pnp_id(psmouse, smbus_pnp_ids)) {
+
+ if (!psmouse_matches_pnp_id(psmouse, forcepad_pnp_ids))
+ psmouse_info(psmouse,
+ "Your touchpad (%s) says it can support a different bus. "
+ "If i2c-hid and hid-rmi are not used, you might want to try setting psmouse.synaptics_intertouch to 1 and report this to linux-input@vger.kernel.org.\n",
+ psmouse->ps2dev.serio->firmware_id);
+
return -ENXIO;
+ }
}
psmouse_info(psmouse, "Trying to set up SMBus access\n");
@@ -1810,6 +1820,15 @@ int synaptics_init(struct psmouse *psmouse)
}
if (SYN_CAP_INTERTOUCH(info.ext_cap_0c)) {
+ if ((!IS_ENABLED(CONFIG_RMI4_SMB) ||
+ !IS_ENABLED(CONFIG_MOUSE_PS2_SYNAPTICS_SMBUS)) &&
+ /* Forcepads need F21, which is not ready */
+ !psmouse_matches_pnp_id(psmouse, forcepad_pnp_ids)) {
+ psmouse_warn(psmouse,
+ "The touchpad can support a better bus than the too old PS/2 protocol. "
+ "Make sure MOUSE_PS2_SYNAPTICS_SMBUS and RMI4_SMB are enabled to get a better touchpad experience.\n");
+ }
+
error = synaptics_setup_intertouch(psmouse, &info, true);
if (!error)
return PSMOUSE_SYNAPTICS_SMBUS;
diff --git a/drivers/input/rmi4/rmi_f03.c b/drivers/input/rmi4/rmi_f03.c
index 77dad045a468..ad71a5e768dc 100644
--- a/drivers/input/rmi4/rmi_f03.c
+++ b/drivers/input/rmi4/rmi_f03.c
@@ -146,7 +146,7 @@ static int rmi_f03_register_pt(struct f03_data *f03)
if (!serio)
return -ENOMEM;
- serio->id.type = SERIO_8042;
+ serio->id.type = SERIO_PS_PSTHRU;
serio->write = rmi_f03_pt_write;
serio->port_data = f03;
diff --git a/drivers/input/rmi4/rmi_f54.c b/drivers/input/rmi4/rmi_f54.c
index dea63e2db3e6..f5206e2c767e 100644
--- a/drivers/input/rmi4/rmi_f54.c
+++ b/drivers/input/rmi4/rmi_f54.c
@@ -31,9 +31,6 @@
#define F54_GET_REPORT 1
#define F54_FORCE_CAL 2
-/* Fixed sizes of reports */
-#define F54_QUERY_LEN 27
-
/* F54 capabilities */
#define F54_CAP_BASELINE (1 << 2)
#define F54_CAP_IMAGE8 (1 << 3)
@@ -95,7 +92,6 @@ struct rmi_f54_reports {
struct f54_data {
struct rmi_function *fn;
- u8 qry[F54_QUERY_LEN];
u8 num_rx_electrodes;
u8 num_tx_electrodes;
u8 capabilities;
@@ -632,22 +628,23 @@ static int rmi_f54_detect(struct rmi_function *fn)
{
int error;
struct f54_data *f54;
+ u8 buf[6];
f54 = dev_get_drvdata(&fn->dev);
error = rmi_read_block(fn->rmi_dev, fn->fd.query_base_addr,
- &f54->qry, sizeof(f54->qry));
+ buf, sizeof(buf));
if (error) {
dev_err(&fn->dev, "%s: Failed to query F54 properties\n",
__func__);
return error;
}
- f54->num_rx_electrodes = f54->qry[0];
- f54->num_tx_electrodes = f54->qry[1];
- f54->capabilities = f54->qry[2];
- f54->clock_rate = f54->qry[3] | (f54->qry[4] << 8);
- f54->family = f54->qry[5];
+ f54->num_rx_electrodes = buf[0];
+ f54->num_tx_electrodes = buf[1];
+ f54->capabilities = buf[2];
+ f54->clock_rate = buf[3] | (buf[4] << 8);
+ f54->family = buf[5];
rmi_dbg(RMI_DEBUG_FN, &fn->dev, "F54 num_rx_electrodes: %d\n",
f54->num_rx_electrodes);
diff --git a/drivers/input/serio/i8042-x86ia64io.h b/drivers/input/serio/i8042-x86ia64io.h
index 09720d950686..f932a83b4990 100644
--- a/drivers/input/serio/i8042-x86ia64io.h
+++ b/drivers/input/serio/i8042-x86ia64io.h
@@ -723,6 +723,13 @@ static const struct dmi_system_id __initconst i8042_dmi_notimeout_table[] = {
DMI_MATCH(DMI_PRODUCT_NAME, "LIFEBOOK U574"),
},
},
+ {
+ /* Fujitsu UH554 laptop */
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "LIFEBOOK UH544"),
+ },
+ },
{ }
};
diff --git a/drivers/input/touchscreen/atmel_mxt_ts.c b/drivers/input/touchscreen/atmel_mxt_ts.c
index 2302aef2b2d4..dd042a9b0aaa 100644
--- a/drivers/input/touchscreen/atmel_mxt_ts.c
+++ b/drivers/input/touchscreen/atmel_mxt_ts.c
@@ -350,6 +350,7 @@ static bool mxt_object_readable(unsigned int type)
case MXT_TOUCH_KEYARRAY_T15:
case MXT_TOUCH_PROXIMITY_T23:
case MXT_TOUCH_PROXKEY_T52:
+ case MXT_TOUCH_MULTITOUCHSCREEN_T100:
case MXT_PROCI_GRIPFACE_T20:
case MXT_PROCG_NOISE_T22:
case MXT_PROCI_ONETOUCH_T24:
diff --git a/drivers/input/touchscreen/edt-ft5x06.c b/drivers/input/touchscreen/edt-ft5x06.c
index 8cf8d8d5d4ef..f872817e81e4 100644
--- a/drivers/input/touchscreen/edt-ft5x06.c
+++ b/drivers/input/touchscreen/edt-ft5x06.c
@@ -471,7 +471,7 @@ static EDT_ATTR(gain, S_IWUSR | S_IRUGO, WORK_REGISTER_GAIN,
static EDT_ATTR(offset, S_IWUSR | S_IRUGO, WORK_REGISTER_OFFSET,
M09_REGISTER_OFFSET, 0, 31);
static EDT_ATTR(threshold, S_IWUSR | S_IRUGO, WORK_REGISTER_THRESHOLD,
- M09_REGISTER_THRESHOLD, 20, 80);
+ M09_REGISTER_THRESHOLD, 0, 80);
static EDT_ATTR(report_rate, S_IWUSR | S_IRUGO, WORK_REGISTER_REPORT_RATE,
NO_REGISTER, 3, 14);
diff --git a/drivers/input/touchscreen/silead.c b/drivers/input/touchscreen/silead.c
index 813dd68a5c82..0dbcf105f7db 100644
--- a/drivers/input/touchscreen/silead.c
+++ b/drivers/input/touchscreen/silead.c
@@ -526,6 +526,7 @@ static int __maybe_unused silead_ts_suspend(struct device *dev)
{
struct i2c_client *client = to_i2c_client(dev);
+ disable_irq(client->irq);
silead_ts_set_power(client, SILEAD_POWER_OFF);
return 0;
}
@@ -551,6 +552,8 @@ static int __maybe_unused silead_ts_resume(struct device *dev)
return -ENODEV;
}
+ enable_irq(client->irq);
+
return 0;
}
diff --git a/drivers/iommu/amd_iommu.c b/drivers/iommu/amd_iommu.c
index 63cacf5d6cf2..5c9759ed22ca 100644
--- a/drivers/iommu/amd_iommu.c
+++ b/drivers/iommu/amd_iommu.c
@@ -3879,11 +3879,9 @@ static void irte_ga_prepare(void *entry,
u8 vector, u32 dest_apicid, int devid)
{
struct irte_ga *irte = (struct irte_ga *) entry;
- struct iommu_dev_data *dev_data = search_dev_data(devid);
irte->lo.val = 0;
irte->hi.val = 0;
- irte->lo.fields_remap.guest_mode = dev_data ? dev_data->use_vapic : 0;
irte->lo.fields_remap.int_type = delivery_mode;
irte->lo.fields_remap.dm = dest_mode;
irte->hi.fields.vector = vector;
@@ -3939,10 +3937,10 @@ static void irte_ga_set_affinity(void *entry, u16 devid, u16 index,
struct irte_ga *irte = (struct irte_ga *) entry;
struct iommu_dev_data *dev_data = search_dev_data(devid);
- if (!dev_data || !dev_data->use_vapic) {
+ if (!dev_data || !dev_data->use_vapic ||
+ !irte->lo.fields_remap.guest_mode) {
irte->hi.fields.vector = vector;
irte->lo.fields_remap.destination = dest_apicid;
- irte->lo.fields_remap.guest_mode = 0;
modify_irte_ga(devid, index, irte, NULL);
}
}
@@ -4386,21 +4384,29 @@ static void ir_compose_msi_msg(struct irq_data *irq_data, struct msi_msg *msg)
}
static struct irq_chip amd_ir_chip = {
- .irq_ack = ir_ack_apic_edge,
- .irq_set_affinity = amd_ir_set_affinity,
- .irq_set_vcpu_affinity = amd_ir_set_vcpu_affinity,
- .irq_compose_msi_msg = ir_compose_msi_msg,
+ .name = "AMD-IR",
+ .irq_ack = ir_ack_apic_edge,
+ .irq_set_affinity = amd_ir_set_affinity,
+ .irq_set_vcpu_affinity = amd_ir_set_vcpu_affinity,
+ .irq_compose_msi_msg = ir_compose_msi_msg,
};
int amd_iommu_create_irq_domain(struct amd_iommu *iommu)
{
- iommu->ir_domain = irq_domain_add_tree(NULL, &amd_ir_domain_ops, iommu);
+ struct fwnode_handle *fn;
+
+ fn = irq_domain_alloc_named_id_fwnode("AMD-IR", iommu->index);
+ if (!fn)
+ return -ENOMEM;
+ iommu->ir_domain = irq_domain_create_tree(fn, &amd_ir_domain_ops, iommu);
+ irq_domain_free_fwnode(fn);
if (!iommu->ir_domain)
return -ENOMEM;
iommu->ir_domain->parent = arch_get_ir_parent_domain();
- iommu->msi_domain = arch_create_msi_irq_domain(iommu->ir_domain);
-
+ iommu->msi_domain = arch_create_remap_msi_irq_domain(iommu->ir_domain,
+ "AMD-IR-MSI",
+ iommu->index);
return 0;
}
diff --git a/drivers/iommu/dmar.c b/drivers/iommu/dmar.c
index cbf7763d8091..c8b0329c85d2 100644
--- a/drivers/iommu/dmar.c
+++ b/drivers/iommu/dmar.c
@@ -1808,10 +1808,9 @@ IOMMU_INIT_POST(detect_intel_iommu);
* for Directed-IO Architecture Specifiction, Rev 2.2, Section 8.8
* "Remapping Hardware Unit Hot Plug".
*/
-static u8 dmar_hp_uuid[] = {
- /* 0000 */ 0xA6, 0xA3, 0xC1, 0xD8, 0x9B, 0xBE, 0x9B, 0x4C,
- /* 0008 */ 0x91, 0xBF, 0xC3, 0xCB, 0x81, 0xFC, 0x5D, 0xAF
-};
+static guid_t dmar_hp_guid =
+ GUID_INIT(0xD8C1A3A6, 0xBE9B, 0x4C9B,
+ 0x91, 0xBF, 0xC3, 0xCB, 0x81, 0xFC, 0x5D, 0xAF);
/*
* Currently there's only one revision and BIOS will not check the revision id,
@@ -1824,7 +1823,7 @@ static u8 dmar_hp_uuid[] = {
static inline bool dmar_detect_dsm(acpi_handle handle, int func)
{
- return acpi_check_dsm(handle, dmar_hp_uuid, DMAR_DSM_REV_ID, 1 << func);
+ return acpi_check_dsm(handle, &dmar_hp_guid, DMAR_DSM_REV_ID, 1 << func);
}
static int dmar_walk_dsm_resource(acpi_handle handle, int func,
@@ -1843,7 +1842,7 @@ static int dmar_walk_dsm_resource(acpi_handle handle, int func,
if (!dmar_detect_dsm(handle, func))
return 0;
- obj = acpi_evaluate_dsm_typed(handle, dmar_hp_uuid, DMAR_DSM_REV_ID,
+ obj = acpi_evaluate_dsm_typed(handle, &dmar_hp_guid, DMAR_DSM_REV_ID,
func, NULL, ACPI_TYPE_BUFFER);
if (!obj)
return -ENODEV;
diff --git a/drivers/iommu/intel-iommu.c b/drivers/iommu/intel-iommu.c
index fc2765ccdb57..8500deda9175 100644
--- a/drivers/iommu/intel-iommu.c
+++ b/drivers/iommu/intel-iommu.c
@@ -4315,7 +4315,7 @@ int dmar_parse_one_atsr(struct acpi_dmar_header *hdr, void *arg)
struct acpi_dmar_atsr *atsr;
struct dmar_atsr_unit *atsru;
- if (system_state != SYSTEM_BOOTING && !intel_iommu_enabled)
+ if (system_state >= SYSTEM_RUNNING && !intel_iommu_enabled)
return 0;
atsr = container_of(hdr, struct acpi_dmar_atsr, header);
@@ -4565,7 +4565,7 @@ int dmar_iommu_notify_scope_dev(struct dmar_pci_notify_info *info)
struct acpi_dmar_atsr *atsr;
struct acpi_dmar_reserved_memory *rmrr;
- if (!intel_iommu_enabled && system_state != SYSTEM_BOOTING)
+ if (!intel_iommu_enabled && system_state >= SYSTEM_RUNNING)
return 0;
list_for_each_entry(rmrru, &dmar_rmrr_units, list) {
diff --git a/drivers/iommu/intel_irq_remapping.c b/drivers/iommu/intel_irq_remapping.c
index a190cbd76ef7..8fc641ea2e41 100644
--- a/drivers/iommu/intel_irq_remapping.c
+++ b/drivers/iommu/intel_irq_remapping.c
@@ -500,8 +500,9 @@ static void iommu_enable_irq_remapping(struct intel_iommu *iommu)
static int intel_setup_irq_remapping(struct intel_iommu *iommu)
{
struct ir_table *ir_table;
- struct page *pages;
+ struct fwnode_handle *fn;
unsigned long *bitmap;
+ struct page *pages;
if (iommu->ir_table)
return 0;
@@ -525,15 +526,24 @@ static int intel_setup_irq_remapping(struct intel_iommu *iommu)
goto out_free_pages;
}
- iommu->ir_domain = irq_domain_add_hierarchy(arch_get_ir_parent_domain(),
- 0, INTR_REMAP_TABLE_ENTRIES,
- NULL, &intel_ir_domain_ops,
- iommu);
+ fn = irq_domain_alloc_named_id_fwnode("INTEL-IR", iommu->seq_id);
+ if (!fn)
+ goto out_free_bitmap;
+
+ iommu->ir_domain =
+ irq_domain_create_hierarchy(arch_get_ir_parent_domain(),
+ 0, INTR_REMAP_TABLE_ENTRIES,
+ fn, &intel_ir_domain_ops,
+ iommu);
+ irq_domain_free_fwnode(fn);
if (!iommu->ir_domain) {
pr_err("IR%d: failed to allocate irqdomain\n", iommu->seq_id);
goto out_free_bitmap;
}
- iommu->ir_msi_domain = arch_create_msi_irq_domain(iommu->ir_domain);
+ iommu->ir_msi_domain =
+ arch_create_remap_msi_irq_domain(iommu->ir_domain,
+ "INTEL-IR-MSI",
+ iommu->seq_id);
ir_table->base = page_address(pages);
ir_table->bitmap = bitmap;
@@ -1205,10 +1215,11 @@ static int intel_ir_set_vcpu_affinity(struct irq_data *data, void *info)
}
static struct irq_chip intel_ir_chip = {
- .irq_ack = ir_ack_apic_edge,
- .irq_set_affinity = intel_ir_set_affinity,
- .irq_compose_msi_msg = intel_ir_compose_msi_msg,
- .irq_set_vcpu_affinity = intel_ir_set_vcpu_affinity,
+ .name = "INTEL-IR",
+ .irq_ack = ir_ack_apic_edge,
+ .irq_set_affinity = intel_ir_set_affinity,
+ .irq_compose_msi_msg = intel_ir_compose_msi_msg,
+ .irq_set_vcpu_affinity = intel_ir_set_vcpu_affinity,
};
static void intel_irq_remapping_prepare_irte(struct intel_ir_data *data,
diff --git a/drivers/iommu/of_iommu.c b/drivers/iommu/of_iommu.c
index 9f44ee8ea1bc..8cb60829a7a1 100644
--- a/drivers/iommu/of_iommu.c
+++ b/drivers/iommu/of_iommu.c
@@ -103,7 +103,7 @@ static bool of_iommu_driver_present(struct device_node *np)
* it never will be. We don't want to defer indefinitely, nor attempt
* to dereference __iommu_of_table after it's been freed.
*/
- if (system_state > SYSTEM_BOOTING)
+ if (system_state >= SYSTEM_RUNNING)
return false;
return of_match_node(&__iommu_of_table, np);
@@ -118,6 +118,7 @@ static const struct iommu_ops
ops = iommu_ops_from_fwnode(fwnode);
if ((ops && !ops->of_xlate) ||
+ !of_device_is_available(iommu_spec->np) ||
(!ops && !of_iommu_driver_present(iommu_spec->np)))
return NULL;
@@ -236,6 +237,12 @@ const struct iommu_ops *of_iommu_configure(struct device *dev,
ops = ERR_PTR(err);
}
+ /* Ignore all other errors apart from EPROBE_DEFER */
+ if (IS_ERR(ops) && (PTR_ERR(ops) != -EPROBE_DEFER)) {
+ dev_dbg(dev, "Adding to IOMMU failed: %ld\n", PTR_ERR(ops));
+ ops = NULL;
+ }
+
return ops;
}
diff --git a/drivers/irqchip/Kconfig b/drivers/irqchip/Kconfig
index 478f8ace2664..676232a94f9f 100644
--- a/drivers/irqchip/Kconfig
+++ b/drivers/irqchip/Kconfig
@@ -268,6 +268,12 @@ config IRQ_MXS
select IRQ_DOMAIN
select STMP_DEVICE
+config MVEBU_GICP
+ bool
+
+config MVEBU_ICU
+ bool
+
config MVEBU_ODMI
bool
select GENERIC_MSI_IRQ_DOMAIN
diff --git a/drivers/irqchip/Makefile b/drivers/irqchip/Makefile
index b64c59b838a0..e88d856cc09c 100644
--- a/drivers/irqchip/Makefile
+++ b/drivers/irqchip/Makefile
@@ -69,10 +69,12 @@ obj-$(CONFIG_ARCH_SA1100) += irq-sa11x0.o
obj-$(CONFIG_INGENIC_IRQ) += irq-ingenic.o
obj-$(CONFIG_IMX_GPCV2) += irq-imx-gpcv2.o
obj-$(CONFIG_PIC32_EVIC) += irq-pic32-evic.o
+obj-$(CONFIG_MVEBU_GICP) += irq-mvebu-gicp.o
+obj-$(CONFIG_MVEBU_ICU) += irq-mvebu-icu.o
obj-$(CONFIG_MVEBU_ODMI) += irq-mvebu-odmi.o
obj-$(CONFIG_MVEBU_PIC) += irq-mvebu-pic.o
obj-$(CONFIG_LS_SCFG_MSI) += irq-ls-scfg-msi.o
obj-$(CONFIG_EZNPS_GIC) += irq-eznps.o
-obj-$(CONFIG_ARCH_ASPEED) += irq-aspeed-vic.o
+obj-$(CONFIG_ARCH_ASPEED) += irq-aspeed-vic.o irq-aspeed-i2c-ic.o
obj-$(CONFIG_STM32_EXTI) += irq-stm32-exti.o
obj-$(CONFIG_QCOM_IRQ_COMBINER) += qcom-irq-combiner.o
diff --git a/drivers/irqchip/irq-armada-370-xp.c b/drivers/irqchip/irq-armada-370-xp.c
index eb0d4d41b156..b207b2c3aa55 100644
--- a/drivers/irqchip/irq-armada-370-xp.c
+++ b/drivers/irqchip/irq-armada-370-xp.c
@@ -34,25 +34,104 @@
#include <asm/smp_plat.h>
#include <asm/mach/irq.h>
-/* Interrupt Controller Registers Map */
-#define ARMADA_370_XP_INT_SET_MASK_OFFS (0x48)
-#define ARMADA_370_XP_INT_CLEAR_MASK_OFFS (0x4C)
-#define ARMADA_370_XP_INT_FABRIC_MASK_OFFS (0x54)
-#define ARMADA_370_XP_INT_CAUSE_PERF(cpu) (1 << cpu)
+/*
+ * Overall diagram of the Armada XP interrupt controller:
+ *
+ * To CPU 0 To CPU 1
+ *
+ * /\ /\
+ * || ||
+ * +---------------+ +---------------+
+ * | | | |
+ * | per-CPU | | per-CPU |
+ * | mask/unmask | | mask/unmask |
+ * | CPU0 | | CPU1 |
+ * | | | |
+ * +---------------+ +---------------+
+ * /\ /\
+ * || ||
+ * \\_______________________//
+ * ||
+ * +-------------------+
+ * | |
+ * | Global interrupt |
+ * | mask/unmask |
+ * | |
+ * +-------------------+
+ * /\
+ * ||
+ * interrupt from
+ * device
+ *
+ * The "global interrupt mask/unmask" is modified using the
+ * ARMADA_370_XP_INT_SET_ENABLE_OFFS and
+ * ARMADA_370_XP_INT_CLEAR_ENABLE_OFFS registers, which are relative
+ * to "main_int_base".
+ *
+ * The "per-CPU mask/unmask" is modified using the
+ * ARMADA_370_XP_INT_SET_MASK_OFFS and
+ * ARMADA_370_XP_INT_CLEAR_MASK_OFFS registers, which are relative to
+ * "per_cpu_int_base". This base address points to a special address,
+ * which automatically accesses the registers of the current CPU.
+ *
+ * The per-CPU mask/unmask can also be adjusted using the global
+ * per-interrupt ARMADA_370_XP_INT_SOURCE_CTL register, which we use
+ * to configure interrupt affinity.
+ *
+ * Due to this model, all interrupts need to be mask/unmasked at two
+ * different levels: at the global level and at the per-CPU level.
+ *
+ * This driver takes the following approach to deal with this:
+ *
+ * - For global interrupts:
+ *
+ * At ->map() time, a global interrupt is unmasked at the per-CPU
+ * mask/unmask level. It is therefore unmasked at this level for
+ * the current CPU, running the ->map() code. This allows to have
+ * the interrupt unmasked at this level in non-SMP
+ * configurations. In SMP configurations, the ->set_affinity()
+ * callback is called, which using the
+ * ARMADA_370_XP_INT_SOURCE_CTL() readjusts the per-CPU mask/unmask
+ * for the interrupt.
+ *
+ * The ->mask() and ->unmask() operations only mask/unmask the
+ * interrupt at the "global" level.
+ *
+ * So, a global interrupt is enabled at the per-CPU level as soon
+ * as it is mapped. At run time, the masking/unmasking takes place
+ * at the global level.
+ *
+ * - For per-CPU interrupts
+ *
+ * At ->map() time, a per-CPU interrupt is unmasked at the global
+ * mask/unmask level.
+ *
+ * The ->mask() and ->unmask() operations mask/unmask the interrupt
+ * at the per-CPU level.
+ *
+ * So, a per-CPU interrupt is enabled at the global level as soon
+ * as it is mapped. At run time, the masking/unmasking takes place
+ * at the per-CPU level.
+ */
+/* Registers relative to main_int_base */
#define ARMADA_370_XP_INT_CONTROL (0x00)
+#define ARMADA_370_XP_SW_TRIG_INT_OFFS (0x04)
#define ARMADA_370_XP_INT_SET_ENABLE_OFFS (0x30)
#define ARMADA_370_XP_INT_CLEAR_ENABLE_OFFS (0x34)
#define ARMADA_370_XP_INT_SOURCE_CTL(irq) (0x100 + irq*4)
#define ARMADA_370_XP_INT_SOURCE_CPU_MASK 0xF
#define ARMADA_370_XP_INT_IRQ_FIQ_MASK(cpuid) ((BIT(0) | BIT(8)) << cpuid)
-#define ARMADA_370_XP_CPU_INTACK_OFFS (0x44)
+/* Registers relative to per_cpu_int_base */
+#define ARMADA_370_XP_IN_DRBEL_CAUSE_OFFS (0x08)
+#define ARMADA_370_XP_IN_DRBEL_MSK_OFFS (0x0c)
#define ARMADA_375_PPI_CAUSE (0x10)
-
-#define ARMADA_370_XP_SW_TRIG_INT_OFFS (0x4)
-#define ARMADA_370_XP_IN_DRBEL_MSK_OFFS (0xc)
-#define ARMADA_370_XP_IN_DRBEL_CAUSE_OFFS (0x8)
+#define ARMADA_370_XP_CPU_INTACK_OFFS (0x44)
+#define ARMADA_370_XP_INT_SET_MASK_OFFS (0x48)
+#define ARMADA_370_XP_INT_CLEAR_MASK_OFFS (0x4C)
+#define ARMADA_370_XP_INT_FABRIC_MASK_OFFS (0x54)
+#define ARMADA_370_XP_INT_CAUSE_PERF(cpu) (1 << cpu)
#define ARMADA_370_XP_MAX_PER_CPU_IRQS (28)
@@ -281,13 +360,11 @@ static int armada_370_xp_mpic_irq_map(struct irq_domain *h,
irq_set_percpu_devid(virq);
irq_set_chip_and_handler(virq, &armada_370_xp_irq_chip,
handle_percpu_devid_irq);
-
} else {
irq_set_chip_and_handler(virq, &armada_370_xp_irq_chip,
handle_level_irq);
}
irq_set_probe(virq);
- irq_clear_status_flags(virq, IRQ_NOAUTOEN);
return 0;
}
@@ -345,16 +422,40 @@ static void armada_mpic_send_doorbell(const struct cpumask *mask,
ARMADA_370_XP_SW_TRIG_INT_OFFS);
}
+static void armada_xp_mpic_reenable_percpu(void)
+{
+ unsigned int irq;
+
+ /* Re-enable per-CPU interrupts that were enabled before suspend */
+ for (irq = 0; irq < ARMADA_370_XP_MAX_PER_CPU_IRQS; irq++) {
+ struct irq_data *data;
+ int virq;
+
+ virq = irq_linear_revmap(armada_370_xp_mpic_domain, irq);
+ if (virq == 0)
+ continue;
+
+ data = irq_get_irq_data(virq);
+
+ if (!irq_percpu_is_enabled(virq))
+ continue;
+
+ armada_370_xp_irq_unmask(data);
+ }
+}
+
static int armada_xp_mpic_starting_cpu(unsigned int cpu)
{
armada_xp_mpic_perf_init();
armada_xp_mpic_smp_cpu_init();
+ armada_xp_mpic_reenable_percpu();
return 0;
}
static int mpic_cascaded_starting_cpu(unsigned int cpu)
{
armada_xp_mpic_perf_init();
+ armada_xp_mpic_reenable_percpu();
enable_percpu_irq(parent_irq, IRQ_TYPE_NONE);
return 0;
}
@@ -502,16 +603,27 @@ static void armada_370_xp_mpic_resume(void)
if (virq == 0)
continue;
- if (!is_percpu_irq(irq))
+ data = irq_get_irq_data(virq);
+
+ if (!is_percpu_irq(irq)) {
+ /* Non per-CPU interrupts */
writel(irq, per_cpu_int_base +
ARMADA_370_XP_INT_CLEAR_MASK_OFFS);
- else
+ if (!irqd_irq_disabled(data))
+ armada_370_xp_irq_unmask(data);
+ } else {
+ /* Per-CPU interrupts */
writel(irq, main_int_base +
ARMADA_370_XP_INT_SET_ENABLE_OFFS);
- data = irq_get_irq_data(virq);
- if (!irqd_irq_disabled(data))
- armada_370_xp_irq_unmask(data);
+ /*
+ * Re-enable on the current CPU,
+ * armada_xp_mpic_reenable_percpu() will take
+ * care of secondary CPUs when they come up.
+ */
+ if (irq_percpu_is_enabled(virq))
+ armada_370_xp_irq_unmask(data);
+ }
}
/* Reconfigure doorbells for IPIs and MSIs */
@@ -563,7 +675,7 @@ static int __init armada_370_xp_mpic_of_init(struct device_node *node,
irq_domain_add_linear(node, nr_irqs,
&armada_370_xp_mpic_irq_ops, NULL);
BUG_ON(!armada_370_xp_mpic_domain);
- armada_370_xp_mpic_domain->bus_token = DOMAIN_BUS_WIRED;
+ irq_domain_update_bus_token(armada_370_xp_mpic_domain, DOMAIN_BUS_WIRED);
/* Setup for the boot CPU */
armada_xp_mpic_perf_init();
diff --git a/drivers/irqchip/irq-aspeed-i2c-ic.c b/drivers/irqchip/irq-aspeed-i2c-ic.c
new file mode 100644
index 000000000000..815b88dd18f2
--- /dev/null
+++ b/drivers/irqchip/irq-aspeed-i2c-ic.c
@@ -0,0 +1,115 @@
+/*
+ * Aspeed 24XX/25XX I2C Interrupt Controller.
+ *
+ * Copyright (C) 2012-2017 ASPEED Technology Inc.
+ * Copyright 2017 IBM Corporation
+ * Copyright 2017 Google, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/irq.h>
+#include <linux/irqchip.h>
+#include <linux/irqchip/chained_irq.h>
+#include <linux/irqdomain.h>
+#include <linux/of_address.h>
+#include <linux/of_irq.h>
+#include <linux/io.h>
+
+
+#define ASPEED_I2C_IC_NUM_BUS 14
+
+struct aspeed_i2c_ic {
+ void __iomem *base;
+ int parent_irq;
+ struct irq_domain *irq_domain;
+};
+
+/*
+ * The aspeed chip provides a single hardware interrupt for all of the I2C
+ * busses, so we use a dummy interrupt chip to translate this single interrupt
+ * into multiple interrupts, each associated with a single I2C bus.
+ */
+static void aspeed_i2c_ic_irq_handler(struct irq_desc *desc)
+{
+ struct aspeed_i2c_ic *i2c_ic = irq_desc_get_handler_data(desc);
+ struct irq_chip *chip = irq_desc_get_chip(desc);
+ unsigned long bit, status;
+ unsigned int bus_irq;
+
+ chained_irq_enter(chip, desc);
+ status = readl(i2c_ic->base);
+ for_each_set_bit(bit, &status, ASPEED_I2C_IC_NUM_BUS) {
+ bus_irq = irq_find_mapping(i2c_ic->irq_domain, bit);
+ generic_handle_irq(bus_irq);
+ }
+ chained_irq_exit(chip, desc);
+}
+
+/*
+ * Set simple handler and mark IRQ as valid. Nothing interesting to do here
+ * since we are using a dummy interrupt chip.
+ */
+static int aspeed_i2c_ic_map_irq_domain(struct irq_domain *domain,
+ unsigned int irq, irq_hw_number_t hwirq)
+{
+ irq_set_chip_and_handler(irq, &dummy_irq_chip, handle_simple_irq);
+ irq_set_chip_data(irq, domain->host_data);
+
+ return 0;
+}
+
+static const struct irq_domain_ops aspeed_i2c_ic_irq_domain_ops = {
+ .map = aspeed_i2c_ic_map_irq_domain,
+};
+
+static int __init aspeed_i2c_ic_of_init(struct device_node *node,
+ struct device_node *parent)
+{
+ struct aspeed_i2c_ic *i2c_ic;
+ int ret = 0;
+
+ i2c_ic = kzalloc(sizeof(*i2c_ic), GFP_KERNEL);
+ if (!i2c_ic)
+ return -ENOMEM;
+
+ i2c_ic->base = of_iomap(node, 0);
+ if (IS_ERR(i2c_ic->base)) {
+ ret = PTR_ERR(i2c_ic->base);
+ goto err_free_ic;
+ }
+
+ i2c_ic->parent_irq = irq_of_parse_and_map(node, 0);
+ if (i2c_ic->parent_irq < 0) {
+ ret = i2c_ic->parent_irq;
+ goto err_iounmap;
+ }
+
+ i2c_ic->irq_domain = irq_domain_add_linear(node, ASPEED_I2C_IC_NUM_BUS,
+ &aspeed_i2c_ic_irq_domain_ops,
+ NULL);
+ if (!i2c_ic->irq_domain) {
+ ret = -ENOMEM;
+ goto err_iounmap;
+ }
+
+ i2c_ic->irq_domain->name = "aspeed-i2c-domain";
+
+ irq_set_chained_handler_and_data(i2c_ic->parent_irq,
+ aspeed_i2c_ic_irq_handler, i2c_ic);
+
+ pr_info("i2c controller registered, irq %d\n", i2c_ic->parent_irq);
+
+ return 0;
+
+err_iounmap:
+ iounmap(i2c_ic->base);
+err_free_ic:
+ kfree(i2c_ic);
+ return ret;
+}
+
+IRQCHIP_DECLARE(ast2400_i2c_ic, "aspeed,ast2400-i2c-ic", aspeed_i2c_ic_of_init);
+IRQCHIP_DECLARE(ast2500_i2c_ic, "aspeed,ast2500-i2c-ic", aspeed_i2c_ic_of_init);
diff --git a/drivers/irqchip/irq-aspeed-vic.c b/drivers/irqchip/irq-aspeed-vic.c
index d24451d5bf8a..03ba477ea0d0 100644
--- a/drivers/irqchip/irq-aspeed-vic.c
+++ b/drivers/irqchip/irq-aspeed-vic.c
@@ -186,7 +186,7 @@ static int avic_map(struct irq_domain *d, unsigned int irq,
return 0;
}
-static struct irq_domain_ops avic_dom_ops = {
+static const struct irq_domain_ops avic_dom_ops = {
.map = avic_map,
.xlate = irq_domain_xlate_onetwocell,
};
@@ -227,4 +227,5 @@ static int __init avic_of_init(struct device_node *node,
return 0;
}
-IRQCHIP_DECLARE(aspeed_new_vic, "aspeed,ast2400-vic", avic_of_init);
+IRQCHIP_DECLARE(ast2400_vic, "aspeed,ast2400-vic", avic_of_init);
+IRQCHIP_DECLARE(ast2500_vic, "aspeed,ast2500-vic", avic_of_init);
diff --git a/drivers/irqchip/irq-gic-v2m.c b/drivers/irqchip/irq-gic-v2m.c
index 863e073c6f7f..993a8426a453 100644
--- a/drivers/irqchip/irq-gic-v2m.c
+++ b/drivers/irqchip/irq-gic-v2m.c
@@ -280,7 +280,7 @@ static int gicv2m_allocate_domains(struct irq_domain *parent)
return -ENOMEM;
}
- inner_domain->bus_token = DOMAIN_BUS_NEXUS;
+ irq_domain_update_bus_token(inner_domain, DOMAIN_BUS_NEXUS);
inner_domain->parent = parent;
pci_domain = pci_msi_create_irq_domain(v2m->fwnode,
&gicv2m_msi_domain_info,
diff --git a/drivers/irqchip/irq-gic-v3-its-pci-msi.c b/drivers/irqchip/irq-gic-v3-its-pci-msi.c
index aee1c60d7ab5..77931214d954 100644
--- a/drivers/irqchip/irq-gic-v3-its-pci-msi.c
+++ b/drivers/irqchip/irq-gic-v3-its-pci-msi.c
@@ -41,27 +41,22 @@ static struct irq_chip its_msi_irq_chip = {
.irq_write_msi_msg = pci_msi_domain_write_msg,
};
-struct its_pci_alias {
- struct pci_dev *pdev;
- u32 count;
-};
-
-static int its_pci_msi_vec_count(struct pci_dev *pdev)
+static int its_pci_msi_vec_count(struct pci_dev *pdev, void *data)
{
- int msi, msix;
+ int msi, msix, *count = data;
msi = max(pci_msi_vec_count(pdev), 0);
msix = max(pci_msix_vec_count(pdev), 0);
+ *count += max(msi, msix);
- return max(msi, msix);
+ return 0;
}
static int its_get_pci_alias(struct pci_dev *pdev, u16 alias, void *data)
{
- struct its_pci_alias *dev_alias = data;
+ struct pci_dev **alias_dev = data;
- if (pdev != dev_alias->pdev)
- dev_alias->count += its_pci_msi_vec_count(pdev);
+ *alias_dev = pdev;
return 0;
}
@@ -69,9 +64,9 @@ static int its_get_pci_alias(struct pci_dev *pdev, u16 alias, void *data)
static int its_pci_msi_prepare(struct irq_domain *domain, struct device *dev,
int nvec, msi_alloc_info_t *info)
{
- struct pci_dev *pdev;
- struct its_pci_alias dev_alias;
+ struct pci_dev *pdev, *alias_dev;
struct msi_domain_info *msi_info;
+ int alias_count = 0;
if (!dev_is_pci(dev))
return -EINVAL;
@@ -79,16 +74,20 @@ static int its_pci_msi_prepare(struct irq_domain *domain, struct device *dev,
msi_info = msi_get_domain_info(domain->parent);
pdev = to_pci_dev(dev);
- dev_alias.pdev = pdev;
- dev_alias.count = nvec;
-
- pci_for_each_dma_alias(pdev, its_get_pci_alias, &dev_alias);
+ /*
+ * If pdev is downstream of any aliasing bridges, take an upper
+ * bound of how many other vectors could map to the same DevID.
+ */
+ pci_for_each_dma_alias(pdev, its_get_pci_alias, &alias_dev);
+ if (alias_dev != pdev && alias_dev->subordinate)
+ pci_walk_bus(alias_dev->subordinate, its_pci_msi_vec_count,
+ &alias_count);
/* ITS specific DeviceID, as the core ITS ignores dev. */
info->scratchpad[0].ul = pci_msi_domain_get_msi_rid(domain, pdev);
return msi_info->ops->msi_prepare(domain->parent,
- dev, dev_alias.count, info);
+ dev, max(nvec, alias_count), info);
}
static struct msi_domain_ops its_pci_msi_ops = {
diff --git a/drivers/irqchip/irq-gic-v3-its-platform-msi.c b/drivers/irqchip/irq-gic-v3-its-platform-msi.c
index 9e9dda33eb17..249240d9a425 100644
--- a/drivers/irqchip/irq-gic-v3-its-platform-msi.c
+++ b/drivers/irqchip/irq-gic-v3-its-platform-msi.c
@@ -86,7 +86,7 @@ static struct msi_domain_info its_pmsi_domain_info = {
.chip = &its_pmsi_irq_chip,
};
-static struct of_device_id its_device_id[] = {
+static const struct of_device_id its_device_id[] = {
{ .compatible = "arm,gic-v3-its", },
{},
};
diff --git a/drivers/irqchip/irq-gic-v3-its.c b/drivers/irqchip/irq-gic-v3-its.c
index 45ea193325d2..68932873eebc 100644
--- a/drivers/irqchip/irq-gic-v3-its.c
+++ b/drivers/irqchip/irq-gic-v3-its.c
@@ -644,9 +644,12 @@ static int its_set_affinity(struct irq_data *d, const struct cpumask *mask_val,
if (cpu >= nr_cpu_ids)
return -EINVAL;
- target_col = &its_dev->its->collections[cpu];
- its_send_movi(its_dev, target_col, id);
- its_dev->event_map.col_map[id] = cpu;
+ /* don't set the affinity when the target cpu is same as current one */
+ if (cpu != its_dev->event_map.col_map[id]) {
+ target_col = &its_dev->its->collections[cpu];
+ its_send_movi(its_dev, target_col, id);
+ its_dev->event_map.col_map[id] = cpu;
+ }
return IRQ_SET_MASK_OK_DONE;
}
@@ -688,9 +691,11 @@ static struct irq_chip its_irq_chip = {
*/
#define IRQS_PER_CHUNK_SHIFT 5
#define IRQS_PER_CHUNK (1 << IRQS_PER_CHUNK_SHIFT)
+#define ITS_MAX_LPI_NRBITS 16 /* 64K LPIs */
static unsigned long *lpi_bitmap;
static u32 lpi_chunks;
+static u32 lpi_id_bits;
static DEFINE_SPINLOCK(lpi_lock);
static int its_lpi_to_chunk(int lpi)
@@ -786,17 +791,13 @@ static void its_lpi_free(struct event_lpi_map *map)
}
/*
- * We allocate 64kB for PROPBASE. That gives us at most 64K LPIs to
+ * We allocate memory for PROPBASE to cover 2 ^ lpi_id_bits LPIs to
* deal with (one configuration byte per interrupt). PENDBASE has to
* be 64kB aligned (one bit per LPI, plus 8192 bits for SPI/PPI/SGI).
*/
-#define LPI_PROPBASE_SZ SZ_64K
-#define LPI_PENDBASE_SZ (LPI_PROPBASE_SZ / 8 + SZ_1K)
-
-/*
- * This is how many bits of ID we need, including the useless ones.
- */
-#define LPI_NRBITS ilog2(LPI_PROPBASE_SZ + SZ_8K)
+#define LPI_NRBITS lpi_id_bits
+#define LPI_PROPBASE_SZ ALIGN(BIT(LPI_NRBITS), SZ_64K)
+#define LPI_PENDBASE_SZ ALIGN(BIT(LPI_NRBITS) / 8, SZ_64K)
#define LPI_PROP_DEFAULT_PRIO 0xa0
@@ -804,6 +805,7 @@ static int __init its_alloc_lpi_tables(void)
{
phys_addr_t paddr;
+ lpi_id_bits = min_t(u32, gic_rdists->id_bits, ITS_MAX_LPI_NRBITS);
gic_rdists->prop_page = alloc_pages(GFP_NOWAIT,
get_order(LPI_PROPBASE_SZ));
if (!gic_rdists->prop_page) {
@@ -822,7 +824,7 @@ static int __init its_alloc_lpi_tables(void)
/* Make sure the GIC will observe the written configuration */
gic_flush_dcache_to_poc(page_address(gic_rdists->prop_page), LPI_PROPBASE_SZ);
- return 0;
+ return its_lpi_init(lpi_id_bits);
}
static const char *its_base_type_string[] = {
@@ -1097,7 +1099,7 @@ static void its_cpu_init_lpis(void)
* hence the 'max(LPI_PENDBASE_SZ, SZ_64K)' below.
*/
pend_page = alloc_pages(GFP_NOWAIT | __GFP_ZERO,
- get_order(max(LPI_PENDBASE_SZ, SZ_64K)));
+ get_order(max_t(u32, LPI_PENDBASE_SZ, SZ_64K)));
if (!pend_page) {
pr_err("Failed to allocate PENDBASE for CPU%d\n",
smp_processor_id());
@@ -1661,7 +1663,7 @@ static int its_init_domain(struct fwnode_handle *handle, struct its_node *its)
}
inner_domain->parent = its_parent;
- inner_domain->bus_token = DOMAIN_BUS_NEXUS;
+ irq_domain_update_bus_token(inner_domain, DOMAIN_BUS_NEXUS);
inner_domain->flags |= IRQ_DOMAIN_FLAG_MSI_REMAP;
info->ops = &its_msi_domain_ops;
info->data = its;
@@ -1801,7 +1803,7 @@ int its_cpu_init(void)
return 0;
}
-static struct of_device_id its_device_id[] = {
+static const struct of_device_id its_device_id[] = {
{ .compatible = "arm,gic-v3-its", },
{},
};
@@ -1833,6 +1835,78 @@ static int __init its_of_probe(struct device_node *node)
#define ACPI_GICV3_ITS_MEM_SIZE (SZ_128K)
+#if defined(CONFIG_ACPI_NUMA) && (ACPI_CA_VERSION >= 0x20170531)
+struct its_srat_map {
+ /* numa node id */
+ u32 numa_node;
+ /* GIC ITS ID */
+ u32 its_id;
+};
+
+static struct its_srat_map its_srat_maps[MAX_NUMNODES] __initdata;
+static int its_in_srat __initdata;
+
+static int __init acpi_get_its_numa_node(u32 its_id)
+{
+ int i;
+
+ for (i = 0; i < its_in_srat; i++) {
+ if (its_id == its_srat_maps[i].its_id)
+ return its_srat_maps[i].numa_node;
+ }
+ return NUMA_NO_NODE;
+}
+
+static int __init gic_acpi_parse_srat_its(struct acpi_subtable_header *header,
+ const unsigned long end)
+{
+ int node;
+ struct acpi_srat_gic_its_affinity *its_affinity;
+
+ its_affinity = (struct acpi_srat_gic_its_affinity *)header;
+ if (!its_affinity)
+ return -EINVAL;
+
+ if (its_affinity->header.length < sizeof(*its_affinity)) {
+ pr_err("SRAT: Invalid header length %d in ITS affinity\n",
+ its_affinity->header.length);
+ return -EINVAL;
+ }
+
+ if (its_in_srat >= MAX_NUMNODES) {
+ pr_err("SRAT: ITS affinity exceeding max count[%d]\n",
+ MAX_NUMNODES);
+ return -EINVAL;
+ }
+
+ node = acpi_map_pxm_to_node(its_affinity->proximity_domain);
+
+ if (node == NUMA_NO_NODE || node >= MAX_NUMNODES) {
+ pr_err("SRAT: Invalid NUMA node %d in ITS affinity\n", node);
+ return 0;
+ }
+
+ its_srat_maps[its_in_srat].numa_node = node;
+ its_srat_maps[its_in_srat].its_id = its_affinity->its_id;
+ its_in_srat++;
+ pr_info("SRAT: PXM %d -> ITS %d -> Node %d\n",
+ its_affinity->proximity_domain, its_affinity->its_id, node);
+
+ return 0;
+}
+
+static void __init acpi_table_parse_srat_its(void)
+{
+ acpi_table_parse_entries(ACPI_SIG_SRAT,
+ sizeof(struct acpi_table_srat),
+ ACPI_SRAT_TYPE_GIC_ITS_AFFINITY,
+ gic_acpi_parse_srat_its, 0);
+}
+#else
+static void __init acpi_table_parse_srat_its(void) { }
+static int __init acpi_get_its_numa_node(u32 its_id) { return NUMA_NO_NODE; }
+#endif
+
static int __init gic_acpi_parse_madt_its(struct acpi_subtable_header *header,
const unsigned long end)
{
@@ -1861,7 +1935,8 @@ static int __init gic_acpi_parse_madt_its(struct acpi_subtable_header *header,
goto dom_err;
}
- err = its_probe_one(&res, dom_handle, NUMA_NO_NODE);
+ err = its_probe_one(&res, dom_handle,
+ acpi_get_its_numa_node(its_entry->translation_id));
if (!err)
return 0;
@@ -1873,6 +1948,7 @@ dom_err:
static void __init its_acpi_probe(void)
{
+ acpi_table_parse_srat_its();
acpi_table_parse_madt(ACPI_MADT_TYPE_GENERIC_TRANSLATOR,
gic_acpi_parse_madt_its, 0);
}
@@ -1898,8 +1974,5 @@ int __init its_init(struct fwnode_handle *handle, struct rdists *rdists,
}
gic_rdists = rdists;
- its_alloc_lpi_tables();
- its_lpi_init(rdists->id_bits);
-
- return 0;
+ return its_alloc_lpi_tables();
}
diff --git a/drivers/irqchip/irq-gic-v3.c b/drivers/irqchip/irq-gic-v3.c
index c132f29322cc..dbffb7ab6203 100644
--- a/drivers/irqchip/irq-gic-v3.c
+++ b/drivers/irqchip/irq-gic-v3.c
@@ -645,6 +645,9 @@ static int gic_set_affinity(struct irq_data *d, const struct cpumask *mask_val,
int enabled;
u64 val;
+ if (cpu >= nr_cpu_ids)
+ return -EINVAL;
+
if (gic_irq_in_rdist(d))
return -EINVAL;
diff --git a/drivers/irqchip/irq-i8259.c b/drivers/irqchip/irq-i8259.c
index 1aec12c6d9ac..7aafbb091b67 100644
--- a/drivers/irqchip/irq-i8259.c
+++ b/drivers/irqchip/irq-i8259.c
@@ -307,7 +307,7 @@ static int i8259A_irq_domain_map(struct irq_domain *d, unsigned int virq,
return 0;
}
-static struct irq_domain_ops i8259A_ops = {
+static const struct irq_domain_ops i8259A_ops = {
.map = i8259A_irq_domain_map,
.xlate = irq_domain_xlate_onecell,
};
diff --git a/drivers/irqchip/irq-imx-gpcv2.c b/drivers/irqchip/irq-imx-gpcv2.c
index 9463f3557e82..bb36f572e322 100644
--- a/drivers/irqchip/irq-imx-gpcv2.c
+++ b/drivers/irqchip/irq-imx-gpcv2.c
@@ -200,7 +200,7 @@ static int imx_gpcv2_domain_alloc(struct irq_domain *domain,
&parent_fwspec);
}
-static struct irq_domain_ops gpcv2_irqchip_data_domain_ops = {
+static const struct irq_domain_ops gpcv2_irqchip_data_domain_ops = {
.translate = imx_gpcv2_domain_translate,
.alloc = imx_gpcv2_domain_alloc,
.free = irq_domain_free_irqs_common,
diff --git a/drivers/irqchip/irq-mbigen.c b/drivers/irqchip/irq-mbigen.c
index 31d6b5a582d2..567b29c47608 100644
--- a/drivers/irqchip/irq-mbigen.c
+++ b/drivers/irqchip/irq-mbigen.c
@@ -228,7 +228,7 @@ static int mbigen_irq_domain_alloc(struct irq_domain *domain,
return 0;
}
-static struct irq_domain_ops mbigen_domain_ops = {
+static const struct irq_domain_ops mbigen_domain_ops = {
.translate = mbigen_domain_translate,
.alloc = mbigen_irq_domain_alloc,
.free = irq_domain_free_irqs_common,
diff --git a/drivers/irqchip/irq-mips-cpu.c b/drivers/irqchip/irq-mips-cpu.c
index b247f3c743ac..0a8ed1c05518 100644
--- a/drivers/irqchip/irq-mips-cpu.c
+++ b/drivers/irqchip/irq-mips-cpu.c
@@ -240,7 +240,7 @@ static void mips_cpu_register_ipi_domain(struct device_node *of_node)
ipi_domain_state);
if (!ipi_domain)
panic("Failed to add MIPS CPU IPI domain");
- ipi_domain->bus_token = DOMAIN_BUS_IPI;
+ irq_domain_update_bus_token(ipi_domain, DOMAIN_BUS_IPI);
}
#else /* !CONFIG_GENERIC_IRQ_IPI */
diff --git a/drivers/irqchip/irq-mips-gic.c b/drivers/irqchip/irq-mips-gic.c
index eb7fbe159963..832ebf4062f7 100644
--- a/drivers/irqchip/irq-mips-gic.c
+++ b/drivers/irqchip/irq-mips-gic.c
@@ -140,7 +140,7 @@ static inline void gic_map_to_vpe(unsigned int intr, unsigned int vpe)
}
#ifdef CONFIG_CLKSRC_MIPS_GIC
-u64 gic_read_count(void)
+u64 notrace gic_read_count(void)
{
unsigned int hi, hi2, lo;
@@ -167,7 +167,7 @@ unsigned int gic_get_count_width(void)
return bits;
}
-void gic_write_compare(u64 cnt)
+void notrace gic_write_compare(u64 cnt)
{
if (mips_cm_is64) {
gic_write(GIC_REG(VPE_LOCAL, GIC_VPE_COMPARE), cnt);
@@ -179,7 +179,7 @@ void gic_write_compare(u64 cnt)
}
}
-void gic_write_cpu_compare(u64 cnt, int cpu)
+void notrace gic_write_cpu_compare(u64 cnt, int cpu)
{
unsigned long flags;
@@ -874,7 +874,7 @@ int gic_ipi_domain_match(struct irq_domain *d, struct device_node *node,
}
}
-static struct irq_domain_ops gic_ipi_domain_ops = {
+static const struct irq_domain_ops gic_ipi_domain_ops = {
.xlate = gic_ipi_domain_xlate,
.alloc = gic_ipi_domain_alloc,
.free = gic_ipi_domain_free,
@@ -960,7 +960,7 @@ static void __init __gic_init(unsigned long gic_base_addr,
panic("Failed to add GIC IPI domain");
gic_ipi_domain->name = "mips-gic-ipi";
- gic_ipi_domain->bus_token = DOMAIN_BUS_IPI;
+ irq_domain_update_bus_token(gic_ipi_domain, DOMAIN_BUS_IPI);
if (node &&
!of_property_read_u32_array(node, "mti,reserved-ipi-vectors", v, 2)) {
diff --git a/drivers/irqchip/irq-mvebu-gicp.c b/drivers/irqchip/irq-mvebu-gicp.c
new file mode 100644
index 000000000000..b283fc90be1e
--- /dev/null
+++ b/drivers/irqchip/irq-mvebu-gicp.c
@@ -0,0 +1,279 @@
+/*
+ * Copyright (C) 2017 Marvell
+ *
+ * Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
+ *
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2. This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ */
+
+#include <linux/io.h>
+#include <linux/irq.h>
+#include <linux/irqdomain.h>
+#include <linux/msi.h>
+#include <linux/of.h>
+#include <linux/of_irq.h>
+#include <linux/of_platform.h>
+#include <linux/platform_device.h>
+
+#include <dt-bindings/interrupt-controller/arm-gic.h>
+
+#include "irq-mvebu-gicp.h"
+
+#define GICP_SETSPI_NSR_OFFSET 0x0
+#define GICP_CLRSPI_NSR_OFFSET 0x8
+
+struct mvebu_gicp_spi_range {
+ unsigned int start;
+ unsigned int count;
+};
+
+struct mvebu_gicp {
+ struct mvebu_gicp_spi_range *spi_ranges;
+ unsigned int spi_ranges_cnt;
+ unsigned int spi_cnt;
+ unsigned long *spi_bitmap;
+ spinlock_t spi_lock;
+ struct resource *res;
+ struct device *dev;
+};
+
+static int gicp_idx_to_spi(struct mvebu_gicp *gicp, int idx)
+{
+ int i;
+
+ for (i = 0; i < gicp->spi_ranges_cnt; i++) {
+ struct mvebu_gicp_spi_range *r = &gicp->spi_ranges[i];
+
+ if (idx < r->count)
+ return r->start + idx;
+
+ idx -= r->count;
+ }
+
+ return -EINVAL;
+}
+
+int mvebu_gicp_get_doorbells(struct device_node *dn, phys_addr_t *setspi,
+ phys_addr_t *clrspi)
+{
+ struct platform_device *pdev;
+ struct mvebu_gicp *gicp;
+
+ pdev = of_find_device_by_node(dn);
+ if (!pdev)
+ return -ENODEV;
+
+ gicp = platform_get_drvdata(pdev);
+ if (!gicp)
+ return -ENODEV;
+
+ *setspi = gicp->res->start + GICP_SETSPI_NSR_OFFSET;
+ *clrspi = gicp->res->start + GICP_CLRSPI_NSR_OFFSET;
+
+ return 0;
+}
+
+static void gicp_compose_msi_msg(struct irq_data *data, struct msi_msg *msg)
+{
+ struct mvebu_gicp *gicp = data->chip_data;
+ phys_addr_t setspi = gicp->res->start + GICP_SETSPI_NSR_OFFSET;
+
+ msg->data = data->hwirq;
+ msg->address_lo = lower_32_bits(setspi);
+ msg->address_hi = upper_32_bits(setspi);
+}
+
+static struct irq_chip gicp_irq_chip = {
+ .name = "GICP",
+ .irq_mask = irq_chip_mask_parent,
+ .irq_unmask = irq_chip_unmask_parent,
+ .irq_eoi = irq_chip_eoi_parent,
+ .irq_set_affinity = irq_chip_set_affinity_parent,
+ .irq_set_type = irq_chip_set_type_parent,
+ .irq_compose_msi_msg = gicp_compose_msi_msg,
+};
+
+static int gicp_irq_domain_alloc(struct irq_domain *domain, unsigned int virq,
+ unsigned int nr_irqs, void *args)
+{
+ struct mvebu_gicp *gicp = domain->host_data;
+ struct irq_fwspec fwspec;
+ unsigned int hwirq;
+ int ret;
+
+ spin_lock(&gicp->spi_lock);
+ hwirq = find_first_zero_bit(gicp->spi_bitmap, gicp->spi_cnt);
+ if (hwirq == gicp->spi_cnt) {
+ spin_unlock(&gicp->spi_lock);
+ return -ENOSPC;
+ }
+ __set_bit(hwirq, gicp->spi_bitmap);
+ spin_unlock(&gicp->spi_lock);
+
+ fwspec.fwnode = domain->parent->fwnode;
+ fwspec.param_count = 3;
+ fwspec.param[0] = GIC_SPI;
+ fwspec.param[1] = gicp_idx_to_spi(gicp, hwirq) - 32;
+ /*
+ * Assume edge rising for now, it will be properly set when
+ * ->set_type() is called
+ */
+ fwspec.param[2] = IRQ_TYPE_EDGE_RISING;
+
+ ret = irq_domain_alloc_irqs_parent(domain, virq, 1, &fwspec);
+ if (ret) {
+ dev_err(gicp->dev, "Cannot allocate parent IRQ\n");
+ goto free_hwirq;
+ }
+
+ ret = irq_domain_set_hwirq_and_chip(domain, virq, hwirq,
+ &gicp_irq_chip, gicp);
+ if (ret)
+ goto free_irqs_parent;
+
+ return 0;
+
+free_irqs_parent:
+ irq_domain_free_irqs_parent(domain, virq, nr_irqs);
+free_hwirq:
+ spin_lock(&gicp->spi_lock);
+ __clear_bit(hwirq, gicp->spi_bitmap);
+ spin_unlock(&gicp->spi_lock);
+ return ret;
+}
+
+static void gicp_irq_domain_free(struct irq_domain *domain,
+ unsigned int virq, unsigned int nr_irqs)
+{
+ struct mvebu_gicp *gicp = domain->host_data;
+ struct irq_data *d = irq_domain_get_irq_data(domain, virq);
+
+ if (d->hwirq >= gicp->spi_cnt) {
+ dev_err(gicp->dev, "Invalid hwirq %lu\n", d->hwirq);
+ return;
+ }
+
+ irq_domain_free_irqs_parent(domain, virq, nr_irqs);
+
+ spin_lock(&gicp->spi_lock);
+ __clear_bit(d->hwirq, gicp->spi_bitmap);
+ spin_unlock(&gicp->spi_lock);
+}
+
+static const struct irq_domain_ops gicp_domain_ops = {
+ .alloc = gicp_irq_domain_alloc,
+ .free = gicp_irq_domain_free,
+};
+
+static struct irq_chip gicp_msi_irq_chip = {
+ .name = "GICP",
+ .irq_set_type = irq_chip_set_type_parent,
+};
+
+static struct msi_domain_ops gicp_msi_ops = {
+};
+
+static struct msi_domain_info gicp_msi_domain_info = {
+ .flags = (MSI_FLAG_USE_DEF_DOM_OPS | MSI_FLAG_USE_DEF_CHIP_OPS),
+ .ops = &gicp_msi_ops,
+ .chip = &gicp_msi_irq_chip,
+};
+
+static int mvebu_gicp_probe(struct platform_device *pdev)
+{
+ struct mvebu_gicp *gicp;
+ struct irq_domain *inner_domain, *plat_domain, *parent_domain;
+ struct device_node *node = pdev->dev.of_node;
+ struct device_node *irq_parent_dn;
+ int ret, i;
+
+ gicp = devm_kzalloc(&pdev->dev, sizeof(*gicp), GFP_KERNEL);
+ if (!gicp)
+ return -ENOMEM;
+
+ gicp->dev = &pdev->dev;
+
+ gicp->res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (!gicp->res)
+ return -ENODEV;
+
+ ret = of_property_count_u32_elems(node, "marvell,spi-ranges");
+ if (ret < 0)
+ return ret;
+
+ gicp->spi_ranges_cnt = ret / 2;
+
+ gicp->spi_ranges =
+ devm_kzalloc(&pdev->dev,
+ gicp->spi_ranges_cnt *
+ sizeof(struct mvebu_gicp_spi_range),
+ GFP_KERNEL);
+ if (!gicp->spi_ranges)
+ return -ENOMEM;
+
+ for (i = 0; i < gicp->spi_ranges_cnt; i++) {
+ of_property_read_u32_index(node, "marvell,spi-ranges",
+ i * 2,
+ &gicp->spi_ranges[i].start);
+
+ of_property_read_u32_index(node, "marvell,spi-ranges",
+ i * 2 + 1,
+ &gicp->spi_ranges[i].count);
+
+ gicp->spi_cnt += gicp->spi_ranges[i].count;
+ }
+
+ gicp->spi_bitmap = devm_kzalloc(&pdev->dev,
+ BITS_TO_LONGS(gicp->spi_cnt) * sizeof(long),
+ GFP_KERNEL);
+ if (!gicp->spi_bitmap)
+ return -ENOMEM;
+
+ irq_parent_dn = of_irq_find_parent(node);
+ if (!irq_parent_dn) {
+ dev_err(&pdev->dev, "failed to find parent IRQ node\n");
+ return -ENODEV;
+ }
+
+ parent_domain = irq_find_host(irq_parent_dn);
+ if (!parent_domain) {
+ dev_err(&pdev->dev, "failed to find parent IRQ domain\n");
+ return -ENODEV;
+ }
+
+ inner_domain = irq_domain_create_hierarchy(parent_domain, 0,
+ gicp->spi_cnt,
+ of_node_to_fwnode(node),
+ &gicp_domain_ops, gicp);
+ if (!inner_domain)
+ return -ENOMEM;
+
+
+ plat_domain = platform_msi_create_irq_domain(of_node_to_fwnode(node),
+ &gicp_msi_domain_info,
+ inner_domain);
+ if (!plat_domain) {
+ irq_domain_remove(inner_domain);
+ return -ENOMEM;
+ }
+
+ platform_set_drvdata(pdev, gicp);
+
+ return 0;
+}
+
+static const struct of_device_id mvebu_gicp_of_match[] = {
+ { .compatible = "marvell,ap806-gicp", },
+ {},
+};
+
+static struct platform_driver mvebu_gicp_driver = {
+ .probe = mvebu_gicp_probe,
+ .driver = {
+ .name = "mvebu-gicp",
+ .of_match_table = mvebu_gicp_of_match,
+ },
+};
+builtin_platform_driver(mvebu_gicp_driver);
diff --git a/drivers/irqchip/irq-mvebu-gicp.h b/drivers/irqchip/irq-mvebu-gicp.h
new file mode 100644
index 000000000000..98535e886ea5
--- /dev/null
+++ b/drivers/irqchip/irq-mvebu-gicp.h
@@ -0,0 +1,11 @@
+#ifndef __MVEBU_GICP_H__
+#define __MVEBU_GICP_H__
+
+#include <linux/types.h>
+
+struct device_node;
+
+int mvebu_gicp_get_doorbells(struct device_node *dn, phys_addr_t *setspi,
+ phys_addr_t *clrspi);
+
+#endif /* __MVEBU_GICP_H__ */
diff --git a/drivers/irqchip/irq-mvebu-icu.c b/drivers/irqchip/irq-mvebu-icu.c
new file mode 100644
index 000000000000..e18c48d3a92e
--- /dev/null
+++ b/drivers/irqchip/irq-mvebu-icu.c
@@ -0,0 +1,289 @@
+/*
+ * Copyright (C) 2017 Marvell
+ *
+ * Hanna Hawa <hannah@marvell.com>
+ * Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
+ *
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2. This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ */
+
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/irqchip.h>
+#include <linux/irqdomain.h>
+#include <linux/kernel.h>
+#include <linux/msi.h>
+#include <linux/of_irq.h>
+#include <linux/of_platform.h>
+#include <linux/platform_device.h>
+
+#include <dt-bindings/interrupt-controller/mvebu-icu.h>
+
+#include "irq-mvebu-gicp.h"
+
+/* ICU registers */
+#define ICU_SETSPI_NSR_AL 0x10
+#define ICU_SETSPI_NSR_AH 0x14
+#define ICU_CLRSPI_NSR_AL 0x18
+#define ICU_CLRSPI_NSR_AH 0x1c
+#define ICU_INT_CFG(x) (0x100 + 4 * (x))
+#define ICU_INT_ENABLE BIT(24)
+#define ICU_IS_EDGE BIT(28)
+#define ICU_GROUP_SHIFT 29
+
+/* ICU definitions */
+#define ICU_MAX_IRQS 207
+#define ICU_SATA0_ICU_ID 109
+#define ICU_SATA1_ICU_ID 107
+
+struct mvebu_icu {
+ struct irq_chip irq_chip;
+ void __iomem *base;
+ struct irq_domain *domain;
+ struct device *dev;
+};
+
+struct mvebu_icu_irq_data {
+ struct mvebu_icu *icu;
+ unsigned int icu_group;
+ unsigned int type;
+};
+
+static void mvebu_icu_write_msg(struct msi_desc *desc, struct msi_msg *msg)
+{
+ struct irq_data *d = irq_get_irq_data(desc->irq);
+ struct mvebu_icu_irq_data *icu_irqd = d->chip_data;
+ struct mvebu_icu *icu = icu_irqd->icu;
+ unsigned int icu_int;
+
+ if (msg->address_lo || msg->address_hi) {
+ /* Configure the ICU with irq number & type */
+ icu_int = msg->data | ICU_INT_ENABLE;
+ if (icu_irqd->type & IRQ_TYPE_EDGE_RISING)
+ icu_int |= ICU_IS_EDGE;
+ icu_int |= icu_irqd->icu_group << ICU_GROUP_SHIFT;
+ } else {
+ /* De-configure the ICU */
+ icu_int = 0;
+ }
+
+ writel_relaxed(icu_int, icu->base + ICU_INT_CFG(d->hwirq));
+
+ /*
+ * The SATA unit has 2 ports, and a dedicated ICU entry per
+ * port. The ahci sata driver supports only one irq interrupt
+ * per SATA unit. To solve this conflict, we configure the 2
+ * SATA wired interrupts in the south bridge into 1 GIC
+ * interrupt in the north bridge. Even if only a single port
+ * is enabled, if sata node is enabled, both interrupts are
+ * configured (regardless of which port is actually in use).
+ */
+ if (d->hwirq == ICU_SATA0_ICU_ID || d->hwirq == ICU_SATA1_ICU_ID) {
+ writel_relaxed(icu_int,
+ icu->base + ICU_INT_CFG(ICU_SATA0_ICU_ID));
+ writel_relaxed(icu_int,
+ icu->base + ICU_INT_CFG(ICU_SATA1_ICU_ID));
+ }
+}
+
+static int
+mvebu_icu_irq_domain_translate(struct irq_domain *d, struct irq_fwspec *fwspec,
+ unsigned long *hwirq, unsigned int *type)
+{
+ struct mvebu_icu *icu = d->host_data;
+ unsigned int icu_group;
+
+ /* Check the count of the parameters in dt */
+ if (WARN_ON(fwspec->param_count < 3)) {
+ dev_err(icu->dev, "wrong ICU parameter count %d\n",
+ fwspec->param_count);
+ return -EINVAL;
+ }
+
+ /* Only ICU group type is handled */
+ icu_group = fwspec->param[0];
+ if (icu_group != ICU_GRP_NSR && icu_group != ICU_GRP_SR &&
+ icu_group != ICU_GRP_SEI && icu_group != ICU_GRP_REI) {
+ dev_err(icu->dev, "wrong ICU group type %x\n", icu_group);
+ return -EINVAL;
+ }
+
+ *hwirq = fwspec->param[1];
+ if (*hwirq >= ICU_MAX_IRQS) {
+ dev_err(icu->dev, "invalid interrupt number %ld\n", *hwirq);
+ return -EINVAL;
+ }
+
+ /* Mask the type to prevent wrong DT configuration */
+ *type = fwspec->param[2] & IRQ_TYPE_SENSE_MASK;
+
+ return 0;
+}
+
+static int
+mvebu_icu_irq_domain_alloc(struct irq_domain *domain, unsigned int virq,
+ unsigned int nr_irqs, void *args)
+{
+ int err;
+ unsigned long hwirq;
+ struct irq_fwspec *fwspec = args;
+ struct mvebu_icu *icu = platform_msi_get_host_data(domain);
+ struct mvebu_icu_irq_data *icu_irqd;
+
+ icu_irqd = kmalloc(sizeof(*icu_irqd), GFP_KERNEL);
+ if (!icu_irqd)
+ return -ENOMEM;
+
+ err = mvebu_icu_irq_domain_translate(domain, fwspec, &hwirq,
+ &icu_irqd->type);
+ if (err) {
+ dev_err(icu->dev, "failed to translate ICU parameters\n");
+ goto free_irqd;
+ }
+
+ icu_irqd->icu_group = fwspec->param[0];
+ icu_irqd->icu = icu;
+
+ err = platform_msi_domain_alloc(domain, virq, nr_irqs);
+ if (err) {
+ dev_err(icu->dev, "failed to allocate ICU interrupt in parent domain\n");
+ goto free_irqd;
+ }
+
+ /* Make sure there is no interrupt left pending by the firmware */
+ err = irq_set_irqchip_state(virq, IRQCHIP_STATE_PENDING, false);
+ if (err)
+ goto free_msi;
+
+ err = irq_domain_set_hwirq_and_chip(domain, virq, hwirq,
+ &icu->irq_chip, icu_irqd);
+ if (err) {
+ dev_err(icu->dev, "failed to set the data to IRQ domain\n");
+ goto free_msi;
+ }
+
+ return 0;
+
+free_msi:
+ platform_msi_domain_free(domain, virq, nr_irqs);
+free_irqd:
+ kfree(icu_irqd);
+ return err;
+}
+
+static void
+mvebu_icu_irq_domain_free(struct irq_domain *domain, unsigned int virq,
+ unsigned int nr_irqs)
+{
+ struct irq_data *d = irq_get_irq_data(virq);
+ struct mvebu_icu_irq_data *icu_irqd = d->chip_data;
+
+ kfree(icu_irqd);
+
+ platform_msi_domain_free(domain, virq, nr_irqs);
+}
+
+static const struct irq_domain_ops mvebu_icu_domain_ops = {
+ .translate = mvebu_icu_irq_domain_translate,
+ .alloc = mvebu_icu_irq_domain_alloc,
+ .free = mvebu_icu_irq_domain_free,
+};
+
+static int mvebu_icu_probe(struct platform_device *pdev)
+{
+ struct mvebu_icu *icu;
+ struct device_node *node = pdev->dev.of_node;
+ struct device_node *gicp_dn;
+ struct resource *res;
+ phys_addr_t setspi, clrspi;
+ u32 i, icu_int;
+ int ret;
+
+ icu = devm_kzalloc(&pdev->dev, sizeof(struct mvebu_icu),
+ GFP_KERNEL);
+ if (!icu)
+ return -ENOMEM;
+
+ icu->dev = &pdev->dev;
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ icu->base = devm_ioremap_resource(&pdev->dev, res);
+ if (IS_ERR(icu->base)) {
+ dev_err(&pdev->dev, "Failed to map icu base address.\n");
+ return PTR_ERR(icu->base);
+ }
+
+ icu->irq_chip.name = devm_kasprintf(&pdev->dev, GFP_KERNEL,
+ "ICU.%x",
+ (unsigned int)res->start);
+ if (!icu->irq_chip.name)
+ return -ENOMEM;
+
+ icu->irq_chip.irq_mask = irq_chip_mask_parent;
+ icu->irq_chip.irq_unmask = irq_chip_unmask_parent;
+ icu->irq_chip.irq_eoi = irq_chip_eoi_parent;
+ icu->irq_chip.irq_set_type = irq_chip_set_type_parent;
+#ifdef CONFIG_SMP
+ icu->irq_chip.irq_set_affinity = irq_chip_set_affinity_parent;
+#endif
+
+ /*
+ * We're probed after MSI domains have been resolved, so force
+ * resolution here.
+ */
+ pdev->dev.msi_domain = of_msi_get_domain(&pdev->dev, node,
+ DOMAIN_BUS_PLATFORM_MSI);
+ if (!pdev->dev.msi_domain)
+ return -EPROBE_DEFER;
+
+ gicp_dn = irq_domain_get_of_node(pdev->dev.msi_domain);
+ if (!gicp_dn)
+ return -ENODEV;
+
+ ret = mvebu_gicp_get_doorbells(gicp_dn, &setspi, &clrspi);
+ if (ret)
+ return ret;
+
+ /* Set Clear/Set ICU SPI message address in AP */
+ writel_relaxed(upper_32_bits(setspi), icu->base + ICU_SETSPI_NSR_AH);
+ writel_relaxed(lower_32_bits(setspi), icu->base + ICU_SETSPI_NSR_AL);
+ writel_relaxed(upper_32_bits(clrspi), icu->base + ICU_CLRSPI_NSR_AH);
+ writel_relaxed(lower_32_bits(clrspi), icu->base + ICU_CLRSPI_NSR_AL);
+
+ /*
+ * Clean all ICU interrupts with type SPI_NSR, required to
+ * avoid unpredictable SPI assignments done by firmware.
+ */
+ for (i = 0 ; i < ICU_MAX_IRQS ; i++) {
+ icu_int = readl(icu->base + ICU_INT_CFG(i));
+ if ((icu_int >> ICU_GROUP_SHIFT) == ICU_GRP_NSR)
+ writel_relaxed(0x0, icu->base + ICU_INT_CFG(i));
+ }
+
+ icu->domain =
+ platform_msi_create_device_domain(&pdev->dev, ICU_MAX_IRQS,
+ mvebu_icu_write_msg,
+ &mvebu_icu_domain_ops, icu);
+ if (!icu->domain) {
+ dev_err(&pdev->dev, "Failed to create ICU domain\n");
+ return -ENOMEM;
+ }
+
+ return 0;
+}
+
+static const struct of_device_id mvebu_icu_of_match[] = {
+ { .compatible = "marvell,cp110-icu", },
+ {},
+};
+
+static struct platform_driver mvebu_icu_driver = {
+ .probe = mvebu_icu_probe,
+ .driver = {
+ .name = "mvebu-icu",
+ .of_match_table = mvebu_icu_of_match,
+ },
+};
+builtin_platform_driver(mvebu_icu_driver);
diff --git a/drivers/irqchip/irq-or1k-pic.c b/drivers/irqchip/irq-or1k-pic.c
index 6a9a3e79218b..dd9d5d12fea2 100644
--- a/drivers/irqchip/irq-or1k-pic.c
+++ b/drivers/irqchip/irq-or1k-pic.c
@@ -70,7 +70,7 @@ static struct or1k_pic_dev or1k_pic_level = {
.name = "or1k-PIC-level",
.irq_unmask = or1k_pic_unmask,
.irq_mask = or1k_pic_mask,
- .irq_mask_ack = or1k_pic_mask,
+ .irq_mask_ack = or1k_pic_mask_ack,
},
.handle = handle_level_irq,
.flags = IRQ_LEVEL | IRQ_NOPROBE,
diff --git a/drivers/irqchip/irq-renesas-h8300h.c b/drivers/irqchip/irq-renesas-h8300h.c
index c378768d75b3..b8327590ae52 100644
--- a/drivers/irqchip/irq-renesas-h8300h.c
+++ b/drivers/irqchip/irq-renesas-h8300h.c
@@ -67,7 +67,7 @@ static int irq_map(struct irq_domain *h, unsigned int virq,
return 0;
}
-static struct irq_domain_ops irq_ops = {
+static const struct irq_domain_ops irq_ops = {
.map = irq_map,
.xlate = irq_domain_xlate_onecell,
};
diff --git a/drivers/irqchip/irq-renesas-h8s.c b/drivers/irqchip/irq-renesas-h8s.c
index af8c6c61c824..71d8139be26c 100644
--- a/drivers/irqchip/irq-renesas-h8s.c
+++ b/drivers/irqchip/irq-renesas-h8s.c
@@ -73,7 +73,7 @@ static __init int irq_map(struct irq_domain *h, unsigned int virq,
return 0;
}
-static struct irq_domain_ops irq_ops = {
+static const struct irq_domain_ops irq_ops = {
.map = irq_map,
.xlate = irq_domain_xlate_onecell,
};
diff --git a/drivers/irqchip/irq-sunxi-nmi.c b/drivers/irqchip/irq-sunxi-nmi.c
index 668730c5cb66..a412b5d5d0fa 100644
--- a/drivers/irqchip/irq-sunxi-nmi.c
+++ b/drivers/irqchip/irq-sunxi-nmi.c
@@ -25,6 +25,29 @@
#define SUNXI_NMI_SRC_TYPE_MASK 0x00000003
+#define SUNXI_NMI_IRQ_BIT BIT(0)
+
+#define SUN6I_R_INTC_CTRL 0x0c
+#define SUN6I_R_INTC_PENDING 0x10
+#define SUN6I_R_INTC_ENABLE 0x40
+
+/*
+ * For deprecated sun6i-a31-sc-nmi compatible.
+ * Registers are offset by 0x0c.
+ */
+#define SUN6I_R_INTC_NMI_OFFSET 0x0c
+#define SUN6I_NMI_CTRL (SUN6I_R_INTC_CTRL - SUN6I_R_INTC_NMI_OFFSET)
+#define SUN6I_NMI_PENDING (SUN6I_R_INTC_PENDING - SUN6I_R_INTC_NMI_OFFSET)
+#define SUN6I_NMI_ENABLE (SUN6I_R_INTC_ENABLE - SUN6I_R_INTC_NMI_OFFSET)
+
+#define SUN7I_NMI_CTRL 0x00
+#define SUN7I_NMI_PENDING 0x04
+#define SUN7I_NMI_ENABLE 0x08
+
+#define SUN9I_NMI_CTRL 0x00
+#define SUN9I_NMI_ENABLE 0x04
+#define SUN9I_NMI_PENDING 0x08
+
enum {
SUNXI_SRC_TYPE_LEVEL_LOW = 0,
SUNXI_SRC_TYPE_EDGE_FALLING,
@@ -38,22 +61,28 @@ struct sunxi_sc_nmi_reg_offs {
u32 enable;
};
-static struct sunxi_sc_nmi_reg_offs sun7i_reg_offs = {
- .ctrl = 0x00,
- .pend = 0x04,
- .enable = 0x08,
+static const struct sunxi_sc_nmi_reg_offs sun6i_r_intc_reg_offs __initconst = {
+ .ctrl = SUN6I_R_INTC_CTRL,
+ .pend = SUN6I_R_INTC_PENDING,
+ .enable = SUN6I_R_INTC_ENABLE,
};
-static struct sunxi_sc_nmi_reg_offs sun6i_reg_offs = {
- .ctrl = 0x00,
- .pend = 0x04,
- .enable = 0x34,
+static const struct sunxi_sc_nmi_reg_offs sun6i_reg_offs __initconst = {
+ .ctrl = SUN6I_NMI_CTRL,
+ .pend = SUN6I_NMI_PENDING,
+ .enable = SUN6I_NMI_ENABLE,
};
-static struct sunxi_sc_nmi_reg_offs sun9i_reg_offs = {
- .ctrl = 0x00,
- .pend = 0x08,
- .enable = 0x04,
+static const struct sunxi_sc_nmi_reg_offs sun7i_reg_offs __initconst = {
+ .ctrl = SUN7I_NMI_CTRL,
+ .pend = SUN7I_NMI_PENDING,
+ .enable = SUN7I_NMI_ENABLE,
+};
+
+static const struct sunxi_sc_nmi_reg_offs sun9i_reg_offs __initconst = {
+ .ctrl = SUN9I_NMI_CTRL,
+ .pend = SUN9I_NMI_PENDING,
+ .enable = SUN9I_NMI_ENABLE,
};
static inline void sunxi_sc_nmi_write(struct irq_chip_generic *gc, u32 off,
@@ -128,7 +157,7 @@ static int sunxi_sc_nmi_set_type(struct irq_data *data, unsigned int flow_type)
}
static int __init sunxi_sc_nmi_irq_init(struct device_node *node,
- struct sunxi_sc_nmi_reg_offs *reg_offs)
+ const struct sunxi_sc_nmi_reg_offs *reg_offs)
{
struct irq_domain *domain;
struct irq_chip_generic *gc;
@@ -187,8 +216,11 @@ static int __init sunxi_sc_nmi_irq_init(struct device_node *node,
gc->chip_types[1].regs.type = reg_offs->ctrl;
gc->chip_types[1].handler = handle_edge_irq;
+ /* Disable any active interrupts */
sunxi_sc_nmi_write(gc, reg_offs->enable, 0);
- sunxi_sc_nmi_write(gc, reg_offs->pend, 0x1);
+
+ /* Clear any pending NMI interrupts */
+ sunxi_sc_nmi_write(gc, reg_offs->pend, SUNXI_NMI_IRQ_BIT);
irq_set_chained_handler_and_data(irq, sunxi_sc_nmi_handle_irq, domain);
@@ -200,6 +232,14 @@ fail_irqd_remove:
return ret;
}
+static int __init sun6i_r_intc_irq_init(struct device_node *node,
+ struct device_node *parent)
+{
+ return sunxi_sc_nmi_irq_init(node, &sun6i_r_intc_reg_offs);
+}
+IRQCHIP_DECLARE(sun6i_r_intc, "allwinner,sun6i-a31-r-intc",
+ sun6i_r_intc_irq_init);
+
static int __init sun6i_sc_nmi_irq_init(struct device_node *node,
struct device_node *parent)
{
diff --git a/drivers/irqchip/irq-xtensa-mx.c b/drivers/irqchip/irq-xtensa-mx.c
index bb3ac5fe5846..72a391e01011 100644
--- a/drivers/irqchip/irq-xtensa-mx.c
+++ b/drivers/irqchip/irq-xtensa-mx.c
@@ -142,7 +142,7 @@ static struct irq_chip xtensa_mx_irq_chip = {
int __init xtensa_mx_init_legacy(struct device_node *interrupt_parent)
{
struct irq_domain *root_domain =
- irq_domain_add_legacy(NULL, NR_IRQS, 0, 0,
+ irq_domain_add_legacy(NULL, NR_IRQS - 1, 1, 0,
&xtensa_mx_irq_domain_ops,
&xtensa_mx_irq_chip);
irq_set_default_host(root_domain);
diff --git a/drivers/irqchip/irq-xtensa-pic.c b/drivers/irqchip/irq-xtensa-pic.c
index 472ae1770964..f728755fa292 100644
--- a/drivers/irqchip/irq-xtensa-pic.c
+++ b/drivers/irqchip/irq-xtensa-pic.c
@@ -89,7 +89,7 @@ static struct irq_chip xtensa_irq_chip = {
int __init xtensa_pic_init_legacy(struct device_node *interrupt_parent)
{
struct irq_domain *root_domain =
- irq_domain_add_legacy(NULL, NR_IRQS, 0, 0,
+ irq_domain_add_legacy(NULL, NR_IRQS - 1, 1, 0,
&xtensa_irq_domain_ops, &xtensa_irq_chip);
irq_set_default_host(root_domain);
return 0;
diff --git a/drivers/irqchip/qcom-irq-combiner.c b/drivers/irqchip/qcom-irq-combiner.c
index 226558698344..6aa3ea479214 100644
--- a/drivers/irqchip/qcom-irq-combiner.c
+++ b/drivers/irqchip/qcom-irq-combiner.c
@@ -288,9 +288,4 @@ static struct platform_driver qcom_irq_combiner_probe = {
},
.probe = combiner_probe,
};
-
-static int __init register_qcom_irq_combiner(void)
-{
- return platform_driver_register(&qcom_irq_combiner_probe);
-}
-device_initcall(register_qcom_irq_combiner);
+builtin_platform_driver(qcom_irq_combiner_probe);
diff --git a/drivers/isdn/i4l/isdn_ppp.c b/drivers/isdn/i4l/isdn_ppp.c
index d07dd5196ffc..8aa158a09180 100644
--- a/drivers/isdn/i4l/isdn_ppp.c
+++ b/drivers/isdn/i4l/isdn_ppp.c
@@ -2364,7 +2364,7 @@ static struct ippp_ccp_reset_state *isdn_ppp_ccp_reset_alloc_state(struct ippp_s
id);
return NULL;
} else {
- rs = kzalloc(sizeof(struct ippp_ccp_reset_state), GFP_KERNEL);
+ rs = kzalloc(sizeof(struct ippp_ccp_reset_state), GFP_ATOMIC);
if (!rs)
return NULL;
rs->state = CCPResetIdle;
diff --git a/drivers/isdn/mISDN/stack.c b/drivers/isdn/mISDN/stack.c
index 8b7faea2ddf8..422dced7c90a 100644
--- a/drivers/isdn/mISDN/stack.c
+++ b/drivers/isdn/mISDN/stack.c
@@ -75,7 +75,7 @@ send_socklist(struct mISDN_sock_list *sl, struct sk_buff *skb)
if (sk->sk_state != MISDN_BOUND)
continue;
if (!cskb)
- cskb = skb_copy(skb, GFP_KERNEL);
+ cskb = skb_copy(skb, GFP_ATOMIC);
if (!cskb) {
printk(KERN_WARNING "%s no skb\n", __func__);
break;
diff --git a/drivers/leds/leds-bcm6328.c b/drivers/leds/leds-bcm6328.c
index 1548259297c1..2cfd9389ee96 100644
--- a/drivers/leds/leds-bcm6328.c
+++ b/drivers/leds/leds-bcm6328.c
@@ -242,7 +242,7 @@ static int bcm6328_hwled(struct device *dev, struct device_node *nc, u32 reg,
spin_lock_irqsave(lock, flags);
val = bcm6328_led_read(addr);
- val |= (BIT(reg) << (((sel % 4) * 4) + 16));
+ val |= (BIT(reg % 4) << (((sel % 4) * 4) + 16));
bcm6328_led_write(addr, val);
spin_unlock_irqrestore(lock, flags);
}
@@ -269,7 +269,7 @@ static int bcm6328_hwled(struct device *dev, struct device_node *nc, u32 reg,
spin_lock_irqsave(lock, flags);
val = bcm6328_led_read(addr);
- val |= (BIT(reg) << ((sel % 4) * 4));
+ val |= (BIT(reg % 4) << ((sel % 4) * 4));
bcm6328_led_write(addr, val);
spin_unlock_irqrestore(lock, flags);
}
diff --git a/drivers/leds/leds-pca955x.c b/drivers/leds/leds-pca955x.c
index 78a7ce816a47..9a873118ea5f 100644
--- a/drivers/leds/leds-pca955x.c
+++ b/drivers/leds/leds-pca955x.c
@@ -285,7 +285,7 @@ static int pca955x_probe(struct i2c_client *client,
"slave address 0x%02x\n",
client->name, chip->bits, client->addr);
- if (!i2c_check_functionality(adapter, I2C_FUNC_I2C))
+ if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA))
return -EIO;
if (pdata) {
diff --git a/drivers/leds/trigger/ledtrig-heartbeat.c b/drivers/leds/trigger/ledtrig-heartbeat.c
index afa3b4099214..e95ea65380c8 100644
--- a/drivers/leds/trigger/ledtrig-heartbeat.c
+++ b/drivers/leds/trigger/ledtrig-heartbeat.c
@@ -20,7 +20,6 @@
#include <linux/sched/loadavg.h>
#include <linux/leds.h>
#include <linux/reboot.h>
-#include <linux/suspend.h>
#include "../leds.h"
static int panic_heartbeats;
@@ -163,30 +162,6 @@ static struct led_trigger heartbeat_led_trigger = {
.deactivate = heartbeat_trig_deactivate,
};
-static int heartbeat_pm_notifier(struct notifier_block *nb,
- unsigned long pm_event, void *unused)
-{
- int rc;
-
- switch (pm_event) {
- case PM_SUSPEND_PREPARE:
- case PM_HIBERNATION_PREPARE:
- case PM_RESTORE_PREPARE:
- led_trigger_unregister(&heartbeat_led_trigger);
- break;
- case PM_POST_SUSPEND:
- case PM_POST_HIBERNATION:
- case PM_POST_RESTORE:
- rc = led_trigger_register(&heartbeat_led_trigger);
- if (rc)
- pr_err("could not re-register heartbeat trigger\n");
- break;
- default:
- break;
- }
- return NOTIFY_DONE;
-}
-
static int heartbeat_reboot_notifier(struct notifier_block *nb,
unsigned long code, void *unused)
{
@@ -201,10 +176,6 @@ static int heartbeat_panic_notifier(struct notifier_block *nb,
return NOTIFY_DONE;
}
-static struct notifier_block heartbeat_pm_nb = {
- .notifier_call = heartbeat_pm_notifier,
-};
-
static struct notifier_block heartbeat_reboot_nb = {
.notifier_call = heartbeat_reboot_notifier,
};
@@ -221,14 +192,12 @@ static int __init heartbeat_trig_init(void)
atomic_notifier_chain_register(&panic_notifier_list,
&heartbeat_panic_nb);
register_reboot_notifier(&heartbeat_reboot_nb);
- register_pm_notifier(&heartbeat_pm_nb);
}
return rc;
}
static void __exit heartbeat_trig_exit(void)
{
- unregister_pm_notifier(&heartbeat_pm_nb);
unregister_reboot_notifier(&heartbeat_reboot_nb);
atomic_notifier_chain_unregister(&panic_notifier_list,
&heartbeat_panic_nb);
diff --git a/drivers/lightnvm/core.c b/drivers/lightnvm/core.c
index 6a4aa608ad95..ddae430b6eae 100644
--- a/drivers/lightnvm/core.c
+++ b/drivers/lightnvm/core.c
@@ -252,8 +252,9 @@ static int nvm_create_tgt(struct nvm_dev *dev, struct nvm_ioctl_create *create)
}
mutex_unlock(&dev->mlock);
- if (nvm_reserve_luns(dev, s->lun_begin, s->lun_end))
- return -ENOMEM;
+ ret = nvm_reserve_luns(dev, s->lun_begin, s->lun_end);
+ if (ret)
+ return ret;
t = kmalloc(sizeof(struct nvm_target), GFP_KERNEL);
if (!t) {
@@ -640,6 +641,7 @@ EXPORT_SYMBOL(nvm_max_phys_sects);
int nvm_submit_io(struct nvm_tgt_dev *tgt_dev, struct nvm_rq *rqd)
{
struct nvm_dev *dev = tgt_dev->parent;
+ int ret;
if (!dev->ops->submit_io)
return -ENODEV;
@@ -647,7 +649,12 @@ int nvm_submit_io(struct nvm_tgt_dev *tgt_dev, struct nvm_rq *rqd)
nvm_rq_tgt_to_dev(tgt_dev, rqd);
rqd->dev = tgt_dev;
- return dev->ops->submit_io(dev, rqd);
+
+ /* In case of error, fail with right address format */
+ ret = dev->ops->submit_io(dev, rqd);
+ if (ret)
+ nvm_rq_dev_to_tgt(tgt_dev, rqd);
+ return ret;
}
EXPORT_SYMBOL(nvm_submit_io);
diff --git a/drivers/lightnvm/pblk-cache.c b/drivers/lightnvm/pblk-cache.c
index 59bcea88db84..024a8fc93069 100644
--- a/drivers/lightnvm/pblk-cache.c
+++ b/drivers/lightnvm/pblk-cache.c
@@ -31,9 +31,13 @@ int pblk_write_to_cache(struct pblk *pblk, struct bio *bio, unsigned long flags)
*/
retry:
ret = pblk_rb_may_write_user(&pblk->rwb, bio, nr_entries, &bpos);
- if (ret == NVM_IO_REQUEUE) {
+ switch (ret) {
+ case NVM_IO_REQUEUE:
io_schedule();
goto retry;
+ case NVM_IO_ERR:
+ pblk_pipeline_stop(pblk);
+ goto out;
}
if (unlikely(!bio_has_data(bio)))
@@ -58,6 +62,8 @@ retry:
atomic_long_add(nr_entries, &pblk->req_writes);
#endif
+ pblk_rl_inserted(&pblk->rl, nr_entries);
+
out:
pblk_write_should_kick(pblk);
return ret;
diff --git a/drivers/lightnvm/pblk-core.c b/drivers/lightnvm/pblk-core.c
index 5e44768ccffa..11fe0c5b2a9c 100644
--- a/drivers/lightnvm/pblk-core.c
+++ b/drivers/lightnvm/pblk-core.c
@@ -17,7 +17,6 @@
*/
#include "pblk.h"
-#include <linux/time.h>
static void pblk_mark_bb(struct pblk *pblk, struct pblk_line *line,
struct ppa_addr *ppa)
@@ -34,7 +33,7 @@ static void pblk_mark_bb(struct pblk *pblk, struct pblk_line *line,
pr_err("pblk: attempted to erase bb: line:%d, pos:%d\n",
line->id, pos);
- pblk_line_run_ws(pblk, NULL, ppa, pblk_line_mark_bb);
+ pblk_line_run_ws(pblk, NULL, ppa, pblk_line_mark_bb, pblk->bb_wq);
}
static void __pblk_end_io_erase(struct pblk *pblk, struct nvm_rq *rqd)
@@ -54,6 +53,8 @@ static void __pblk_end_io_erase(struct pblk *pblk, struct nvm_rq *rqd)
*ppa = rqd->ppa_addr;
pblk_mark_bb(pblk, line, ppa);
}
+
+ atomic_dec(&pblk->inflight_io);
}
/* Erase completion assumes that only one block is erased at the time */
@@ -61,13 +62,12 @@ static void pblk_end_io_erase(struct nvm_rq *rqd)
{
struct pblk *pblk = rqd->private;
- up(&pblk->erase_sem);
__pblk_end_io_erase(pblk, rqd);
- mempool_free(rqd, pblk->r_rq_pool);
+ mempool_free(rqd, pblk->g_rq_pool);
}
-static void __pblk_map_invalidate(struct pblk *pblk, struct pblk_line *line,
- u64 paddr)
+void __pblk_map_invalidate(struct pblk *pblk, struct pblk_line *line,
+ u64 paddr)
{
struct pblk_line_mgmt *l_mg = &pblk->l_mg;
struct list_head *move_list = NULL;
@@ -88,7 +88,7 @@ static void __pblk_map_invalidate(struct pblk *pblk, struct pblk_line *line,
spin_unlock(&line->lock);
return;
}
- line->vsc--;
+ le32_add_cpu(line->vsc, -1);
if (line->state == PBLK_LINESTATE_CLOSED)
move_list = pblk_line_gc_list(pblk, line);
@@ -130,18 +130,6 @@ void pblk_map_invalidate(struct pblk *pblk, struct ppa_addr ppa)
__pblk_map_invalidate(pblk, line, paddr);
}
-void pblk_map_pad_invalidate(struct pblk *pblk, struct pblk_line *line,
- u64 paddr)
-{
- __pblk_map_invalidate(pblk, line, paddr);
-
- pblk_rb_sync_init(&pblk->rwb, NULL);
- line->left_ssecs--;
- if (!line->left_ssecs)
- pblk_line_run_ws(pblk, line, NULL, pblk_line_close_ws);
- pblk_rb_sync_end(&pblk->rwb, NULL);
-}
-
static void pblk_invalidate_range(struct pblk *pblk, sector_t slba,
unsigned int nr_secs)
{
@@ -172,8 +160,8 @@ struct nvm_rq *pblk_alloc_rqd(struct pblk *pblk, int rw)
pool = pblk->w_rq_pool;
rq_size = pblk_w_rq_size;
} else {
- pool = pblk->r_rq_pool;
- rq_size = pblk_r_rq_size;
+ pool = pblk->g_rq_pool;
+ rq_size = pblk_g_rq_size;
}
rqd = mempool_alloc(pool, GFP_KERNEL);
@@ -189,7 +177,7 @@ void pblk_free_rqd(struct pblk *pblk, struct nvm_rq *rqd, int rw)
if (rw == WRITE)
pool = pblk->w_rq_pool;
else
- pool = pblk->r_rq_pool;
+ pool = pblk->g_rq_pool;
mempool_free(rqd, pool);
}
@@ -271,35 +259,26 @@ void pblk_end_io_sync(struct nvm_rq *rqd)
complete(waiting);
}
-void pblk_flush_writer(struct pblk *pblk)
+void pblk_wait_for_meta(struct pblk *pblk)
{
- struct bio *bio;
- int ret;
- DECLARE_COMPLETION_ONSTACK(wait);
-
- bio = bio_alloc(GFP_KERNEL, 1);
- if (!bio)
- return;
-
- bio->bi_iter.bi_sector = 0; /* internal bio */
- bio_set_op_attrs(bio, REQ_OP_WRITE, REQ_OP_FLUSH);
- bio->bi_private = &wait;
- bio->bi_end_io = pblk_end_bio_sync;
+ do {
+ if (!atomic_read(&pblk->inflight_io))
+ break;
- ret = pblk_write_to_cache(pblk, bio, 0);
- if (ret == NVM_IO_OK) {
- if (!wait_for_completion_io_timeout(&wait,
- msecs_to_jiffies(PBLK_COMMAND_TIMEOUT_MS))) {
- pr_err("pblk: flush cache timed out\n");
- }
- } else if (ret != NVM_IO_DONE) {
- pr_err("pblk: tear down bio failed\n");
- }
+ schedule();
+ } while (1);
+}
- if (bio->bi_error)
- pr_err("pblk: flush sync write failed (%u)\n", bio->bi_error);
+static void pblk_flush_writer(struct pblk *pblk)
+{
+ pblk_rb_flush(&pblk->rwb);
+ do {
+ if (!pblk_rb_sync_count(&pblk->rwb))
+ break;
- bio_put(bio);
+ pblk_write_kick(pblk);
+ schedule();
+ } while (1);
}
struct list_head *pblk_line_gc_list(struct pblk *pblk, struct pblk_line *line)
@@ -307,28 +286,31 @@ struct list_head *pblk_line_gc_list(struct pblk *pblk, struct pblk_line *line)
struct pblk_line_meta *lm = &pblk->lm;
struct pblk_line_mgmt *l_mg = &pblk->l_mg;
struct list_head *move_list = NULL;
+ int vsc = le32_to_cpu(*line->vsc);
- if (!line->vsc) {
+ lockdep_assert_held(&line->lock);
+
+ if (!vsc) {
if (line->gc_group != PBLK_LINEGC_FULL) {
line->gc_group = PBLK_LINEGC_FULL;
move_list = &l_mg->gc_full_list;
}
- } else if (line->vsc < lm->mid_thrs) {
+ } else if (vsc < lm->high_thrs) {
if (line->gc_group != PBLK_LINEGC_HIGH) {
line->gc_group = PBLK_LINEGC_HIGH;
move_list = &l_mg->gc_high_list;
}
- } else if (line->vsc < lm->high_thrs) {
+ } else if (vsc < lm->mid_thrs) {
if (line->gc_group != PBLK_LINEGC_MID) {
line->gc_group = PBLK_LINEGC_MID;
move_list = &l_mg->gc_mid_list;
}
- } else if (line->vsc < line->sec_in_line) {
+ } else if (vsc < line->sec_in_line) {
if (line->gc_group != PBLK_LINEGC_LOW) {
line->gc_group = PBLK_LINEGC_LOW;
move_list = &l_mg->gc_low_list;
}
- } else if (line->vsc == line->sec_in_line) {
+ } else if (vsc == line->sec_in_line) {
if (line->gc_group != PBLK_LINEGC_EMPTY) {
line->gc_group = PBLK_LINEGC_EMPTY;
move_list = &l_mg->gc_empty_list;
@@ -338,7 +320,7 @@ struct list_head *pblk_line_gc_list(struct pblk *pblk, struct pblk_line *line)
line->gc_group = PBLK_LINEGC_NONE;
move_list = &l_mg->corrupt_list;
pr_err("pblk: corrupted vsc for line %d, vsc:%d (%d/%d/%d)\n",
- line->id, line->vsc,
+ line->id, vsc,
line->sec_in_line,
lm->high_thrs, lm->mid_thrs);
}
@@ -397,6 +379,11 @@ void pblk_log_read_err(struct pblk *pblk, struct nvm_rq *rqd)
#endif
}
+void pblk_set_sec_per_write(struct pblk *pblk, int sec_per_write)
+{
+ pblk->sec_per_write = sec_per_write;
+}
+
int pblk_submit_io(struct pblk *pblk, struct nvm_rq *rqd)
{
struct nvm_tgt_dev *dev = pblk->dev;
@@ -431,21 +418,23 @@ int pblk_submit_io(struct pblk *pblk, struct nvm_rq *rqd)
}
}
#endif
+
+ atomic_inc(&pblk->inflight_io);
+
return nvm_submit_io(dev, rqd);
}
struct bio *pblk_bio_map_addr(struct pblk *pblk, void *data,
unsigned int nr_secs, unsigned int len,
- gfp_t gfp_mask)
+ int alloc_type, gfp_t gfp_mask)
{
struct nvm_tgt_dev *dev = pblk->dev;
- struct pblk_line_mgmt *l_mg = &pblk->l_mg;
void *kaddr = data;
struct page *page;
struct bio *bio;
int i, ret;
- if (l_mg->emeta_alloc_type == PBLK_KMALLOC_META)
+ if (alloc_type == PBLK_KMALLOC_META)
return bio_map_kern(dev->q, kaddr, len, gfp_mask);
bio = bio_kmalloc(gfp_mask, nr_secs);
@@ -478,7 +467,7 @@ out:
int pblk_calc_secs(struct pblk *pblk, unsigned long secs_avail,
unsigned long secs_to_flush)
{
- int max = pblk->max_write_pgs;
+ int max = pblk->sec_per_write;
int min = pblk->min_write_pgs;
int secs_to_sync = 0;
@@ -492,12 +481,26 @@ int pblk_calc_secs(struct pblk *pblk, unsigned long secs_avail,
return secs_to_sync;
}
-static u64 __pblk_alloc_page(struct pblk *pblk, struct pblk_line *line,
- int nr_secs)
+void pblk_dealloc_page(struct pblk *pblk, struct pblk_line *line, int nr_secs)
+{
+ u64 addr;
+ int i;
+
+ addr = find_next_zero_bit(line->map_bitmap,
+ pblk->lm.sec_per_line, line->cur_sec);
+ line->cur_sec = addr - nr_secs;
+
+ for (i = 0; i < nr_secs; i++, line->cur_sec--)
+ WARN_ON(!test_and_clear_bit(line->cur_sec, line->map_bitmap));
+}
+
+u64 __pblk_alloc_page(struct pblk *pblk, struct pblk_line *line, int nr_secs)
{
u64 addr;
int i;
+ lockdep_assert_held(&line->lock);
+
/* logic error: ppa out-of-bounds. Prevent generating bad address */
if (line->cur_sec + nr_secs > pblk->lm.sec_per_line) {
WARN(1, "pblk: page allocation out of bounds\n");
@@ -528,27 +531,38 @@ u64 pblk_alloc_page(struct pblk *pblk, struct pblk_line *line, int nr_secs)
return addr;
}
+u64 pblk_lookup_page(struct pblk *pblk, struct pblk_line *line)
+{
+ u64 paddr;
+
+ spin_lock(&line->lock);
+ paddr = find_next_zero_bit(line->map_bitmap,
+ pblk->lm.sec_per_line, line->cur_sec);
+ spin_unlock(&line->lock);
+
+ return paddr;
+}
+
/*
* Submit emeta to one LUN in the raid line at the time to avoid a deadlock when
* taking the per LUN semaphore.
*/
static int pblk_line_submit_emeta_io(struct pblk *pblk, struct pblk_line *line,
- u64 paddr, int dir)
+ void *emeta_buf, u64 paddr, int dir)
{
struct nvm_tgt_dev *dev = pblk->dev;
struct nvm_geo *geo = &dev->geo;
+ struct pblk_line_mgmt *l_mg = &pblk->l_mg;
struct pblk_line_meta *lm = &pblk->lm;
+ void *ppa_list, *meta_list;
struct bio *bio;
struct nvm_rq rqd;
- struct ppa_addr *ppa_list;
- dma_addr_t dma_ppa_list;
- void *emeta = line->emeta;
+ dma_addr_t dma_ppa_list, dma_meta_list;
int min = pblk->min_write_pgs;
- int left_ppas = lm->emeta_sec;
+ int left_ppas = lm->emeta_sec[0];
int id = line->id;
int rq_ppas, rq_len;
int cmd_op, bio_op;
- int flags;
int i, j;
int ret;
DECLARE_COMPLETION_ONSTACK(wait);
@@ -556,25 +570,28 @@ static int pblk_line_submit_emeta_io(struct pblk *pblk, struct pblk_line *line,
if (dir == WRITE) {
bio_op = REQ_OP_WRITE;
cmd_op = NVM_OP_PWRITE;
- flags = pblk_set_progr_mode(pblk, WRITE);
} else if (dir == READ) {
bio_op = REQ_OP_READ;
cmd_op = NVM_OP_PREAD;
- flags = pblk_set_read_mode(pblk);
} else
return -EINVAL;
- ppa_list = nvm_dev_dma_alloc(dev->parent, GFP_KERNEL, &dma_ppa_list);
- if (!ppa_list)
+ meta_list = nvm_dev_dma_alloc(dev->parent, GFP_KERNEL,
+ &dma_meta_list);
+ if (!meta_list)
return -ENOMEM;
+ ppa_list = meta_list + pblk_dma_meta_size;
+ dma_ppa_list = dma_meta_list + pblk_dma_meta_size;
+
next_rq:
memset(&rqd, 0, sizeof(struct nvm_rq));
rq_ppas = pblk_calc_secs(pblk, left_ppas, 0);
rq_len = rq_ppas * geo->sec_size;
- bio = pblk_bio_map_addr(pblk, emeta, rq_ppas, rq_len, GFP_KERNEL);
+ bio = pblk_bio_map_addr(pblk, emeta_buf, rq_ppas, rq_len,
+ l_mg->emeta_alloc_type, GFP_KERNEL);
if (IS_ERR(bio)) {
ret = PTR_ERR(bio);
goto free_rqd_dma;
@@ -584,27 +601,38 @@ next_rq:
bio_set_op_attrs(bio, bio_op, 0);
rqd.bio = bio;
- rqd.opcode = cmd_op;
- rqd.flags = flags;
- rqd.nr_ppas = rq_ppas;
+ rqd.meta_list = meta_list;
rqd.ppa_list = ppa_list;
+ rqd.dma_meta_list = dma_meta_list;
rqd.dma_ppa_list = dma_ppa_list;
+ rqd.opcode = cmd_op;
+ rqd.nr_ppas = rq_ppas;
rqd.end_io = pblk_end_io_sync;
rqd.private = &wait;
if (dir == WRITE) {
+ struct pblk_sec_meta *meta_list = rqd.meta_list;
+
+ rqd.flags = pblk_set_progr_mode(pblk, WRITE);
for (i = 0; i < rqd.nr_ppas; ) {
spin_lock(&line->lock);
paddr = __pblk_alloc_page(pblk, line, min);
spin_unlock(&line->lock);
- for (j = 0; j < min; j++, i++, paddr++)
+ for (j = 0; j < min; j++, i++, paddr++) {
+ meta_list[i].lba = cpu_to_le64(ADDR_EMPTY);
rqd.ppa_list[i] =
addr_to_gen_ppa(pblk, paddr, id);
+ }
}
} else {
for (i = 0; i < rqd.nr_ppas; ) {
struct ppa_addr ppa = addr_to_gen_ppa(pblk, paddr, id);
int pos = pblk_dev_ppa_to_pos(geo, ppa);
+ int read_type = PBLK_READ_RANDOM;
+
+ if (pblk_io_aligned(pblk, rq_ppas))
+ read_type = PBLK_READ_SEQUENTIAL;
+ rqd.flags = pblk_set_read_mode(pblk, read_type);
while (test_bit(pos, line->blk_bitmap)) {
paddr += min;
@@ -645,9 +673,11 @@ next_rq:
msecs_to_jiffies(PBLK_COMMAND_TIMEOUT_MS))) {
pr_err("pblk: emeta I/O timed out\n");
}
+ atomic_dec(&pblk->inflight_io);
reinit_completion(&wait);
- bio_put(bio);
+ if (likely(pblk->l_mg.emeta_alloc_type == PBLK_VMALLOC_META))
+ bio_put(bio);
if (rqd.error) {
if (dir == WRITE)
@@ -656,12 +686,12 @@ next_rq:
pblk_log_read_err(pblk, &rqd);
}
- emeta += rq_len;
+ emeta_buf += rq_len;
left_ppas -= rq_ppas;
if (left_ppas)
goto next_rq;
free_rqd_dma:
- nvm_dev_dma_free(dev->parent, ppa_list, dma_ppa_list);
+ nvm_dev_dma_free(dev->parent, rqd.meta_list, rqd.dma_meta_list);
return ret;
}
@@ -697,21 +727,24 @@ static int pblk_line_submit_smeta_io(struct pblk *pblk, struct pblk_line *line,
bio_op = REQ_OP_WRITE;
cmd_op = NVM_OP_PWRITE;
flags = pblk_set_progr_mode(pblk, WRITE);
- lba_list = pblk_line_emeta_to_lbas(line->emeta);
+ lba_list = emeta_to_lbas(pblk, line->emeta->buf);
} else if (dir == READ) {
bio_op = REQ_OP_READ;
cmd_op = NVM_OP_PREAD;
- flags = pblk_set_read_mode(pblk);
+ flags = pblk_set_read_mode(pblk, PBLK_READ_SEQUENTIAL);
} else
return -EINVAL;
memset(&rqd, 0, sizeof(struct nvm_rq));
- rqd.ppa_list = nvm_dev_dma_alloc(dev->parent, GFP_KERNEL,
- &rqd.dma_ppa_list);
- if (!rqd.ppa_list)
+ rqd.meta_list = nvm_dev_dma_alloc(dev->parent, GFP_KERNEL,
+ &rqd.dma_meta_list);
+ if (!rqd.meta_list)
return -ENOMEM;
+ rqd.ppa_list = rqd.meta_list + pblk_dma_meta_size;
+ rqd.dma_ppa_list = rqd.dma_meta_list + pblk_dma_meta_size;
+
bio = bio_map_kern(dev->q, line->smeta, lm->smeta_len, GFP_KERNEL);
if (IS_ERR(bio)) {
ret = PTR_ERR(bio);
@@ -729,9 +762,15 @@ static int pblk_line_submit_smeta_io(struct pblk *pblk, struct pblk_line *line,
rqd.private = &wait;
for (i = 0; i < lm->smeta_sec; i++, paddr++) {
+ struct pblk_sec_meta *meta_list = rqd.meta_list;
+
rqd.ppa_list[i] = addr_to_gen_ppa(pblk, paddr, line->id);
- if (dir == WRITE)
- lba_list[paddr] = cpu_to_le64(ADDR_EMPTY);
+
+ if (dir == WRITE) {
+ __le64 addr_empty = cpu_to_le64(ADDR_EMPTY);
+
+ meta_list[i].lba = lba_list[paddr] = addr_empty;
+ }
}
/*
@@ -750,6 +789,7 @@ static int pblk_line_submit_smeta_io(struct pblk *pblk, struct pblk_line *line,
msecs_to_jiffies(PBLK_COMMAND_TIMEOUT_MS))) {
pr_err("pblk: smeta I/O timed out\n");
}
+ atomic_dec(&pblk->inflight_io);
if (rqd.error) {
if (dir == WRITE)
@@ -759,7 +799,7 @@ static int pblk_line_submit_smeta_io(struct pblk *pblk, struct pblk_line *line,
}
free_ppa_list:
- nvm_dev_dma_free(dev->parent, rqd.ppa_list, rqd.dma_ppa_list);
+ nvm_dev_dma_free(dev->parent, rqd.meta_list, rqd.dma_meta_list);
return ret;
}
@@ -771,9 +811,11 @@ int pblk_line_read_smeta(struct pblk *pblk, struct pblk_line *line)
return pblk_line_submit_smeta_io(pblk, line, bpaddr, READ);
}
-int pblk_line_read_emeta(struct pblk *pblk, struct pblk_line *line)
+int pblk_line_read_emeta(struct pblk *pblk, struct pblk_line *line,
+ void *emeta_buf)
{
- return pblk_line_submit_emeta_io(pblk, line, line->emeta_ssec, READ);
+ return pblk_line_submit_emeta_io(pblk, line, emeta_buf,
+ line->emeta_ssec, READ);
}
static void pblk_setup_e_rq(struct pblk *pblk, struct nvm_rq *rqd,
@@ -789,7 +831,7 @@ static void pblk_setup_e_rq(struct pblk *pblk, struct nvm_rq *rqd,
static int pblk_blk_erase_sync(struct pblk *pblk, struct ppa_addr ppa)
{
struct nvm_rq rqd;
- int ret;
+ int ret = 0;
DECLARE_COMPLETION_ONSTACK(wait);
memset(&rqd, 0, sizeof(struct nvm_rq));
@@ -824,14 +866,14 @@ out:
rqd.private = pblk;
__pblk_end_io_erase(pblk, &rqd);
- return 0;
+ return ret;
}
int pblk_line_erase(struct pblk *pblk, struct pblk_line *line)
{
struct pblk_line_meta *lm = &pblk->lm;
struct ppa_addr ppa;
- int bit = -1;
+ int ret, bit = -1;
/* Erase only good blocks, one at a time */
do {
@@ -850,27 +892,59 @@ int pblk_line_erase(struct pblk *pblk, struct pblk_line *line)
WARN_ON(test_and_set_bit(bit, line->erase_bitmap));
spin_unlock(&line->lock);
- if (pblk_blk_erase_sync(pblk, ppa)) {
+ ret = pblk_blk_erase_sync(pblk, ppa);
+ if (ret) {
pr_err("pblk: failed to erase line %d\n", line->id);
- return -ENOMEM;
+ return ret;
}
} while (1);
return 0;
}
+static void pblk_line_setup_metadata(struct pblk_line *line,
+ struct pblk_line_mgmt *l_mg,
+ struct pblk_line_meta *lm)
+{
+ int meta_line;
+
+ lockdep_assert_held(&l_mg->free_lock);
+
+retry_meta:
+ meta_line = find_first_zero_bit(&l_mg->meta_bitmap, PBLK_DATA_LINES);
+ if (meta_line == PBLK_DATA_LINES) {
+ spin_unlock(&l_mg->free_lock);
+ io_schedule();
+ spin_lock(&l_mg->free_lock);
+ goto retry_meta;
+ }
+
+ set_bit(meta_line, &l_mg->meta_bitmap);
+ line->meta_line = meta_line;
+
+ line->smeta = l_mg->sline_meta[meta_line];
+ line->emeta = l_mg->eline_meta[meta_line];
+
+ memset(line->smeta, 0, lm->smeta_len);
+ memset(line->emeta->buf, 0, lm->emeta_len[0]);
+
+ line->emeta->mem = 0;
+ atomic_set(&line->emeta->sync, 0);
+}
+
/* For now lines are always assumed full lines. Thus, smeta former and current
* lun bitmaps are omitted.
*/
-static int pblk_line_set_metadata(struct pblk *pblk, struct pblk_line *line,
+static int pblk_line_init_metadata(struct pblk *pblk, struct pblk_line *line,
struct pblk_line *cur)
{
struct nvm_tgt_dev *dev = pblk->dev;
struct nvm_geo *geo = &dev->geo;
struct pblk_line_meta *lm = &pblk->lm;
struct pblk_line_mgmt *l_mg = &pblk->l_mg;
- struct line_smeta *smeta = line->smeta;
- struct line_emeta *emeta = line->emeta;
+ struct pblk_emeta *emeta = line->emeta;
+ struct line_emeta *emeta_buf = emeta->buf;
+ struct line_smeta *smeta_buf = (struct line_smeta *)line->smeta;
int nr_blk_line;
/* After erasing the line, new bad blocks might appear and we risk
@@ -893,42 +967,44 @@ static int pblk_line_set_metadata(struct pblk *pblk, struct pblk_line *line,
}
/* Run-time metadata */
- line->lun_bitmap = ((void *)(smeta)) + sizeof(struct line_smeta);
+ line->lun_bitmap = ((void *)(smeta_buf)) + sizeof(struct line_smeta);
/* Mark LUNs allocated in this line (all for now) */
bitmap_set(line->lun_bitmap, 0, lm->lun_bitmap_len);
- smeta->header.identifier = cpu_to_le32(PBLK_MAGIC);
- memcpy(smeta->header.uuid, pblk->instance_uuid, 16);
- smeta->header.id = cpu_to_le32(line->id);
- smeta->header.type = cpu_to_le16(line->type);
- smeta->header.version = cpu_to_le16(1);
+ smeta_buf->header.identifier = cpu_to_le32(PBLK_MAGIC);
+ memcpy(smeta_buf->header.uuid, pblk->instance_uuid, 16);
+ smeta_buf->header.id = cpu_to_le32(line->id);
+ smeta_buf->header.type = cpu_to_le16(line->type);
+ smeta_buf->header.version = cpu_to_le16(1);
/* Start metadata */
- smeta->seq_nr = cpu_to_le64(line->seq_nr);
- smeta->window_wr_lun = cpu_to_le32(geo->nr_luns);
+ smeta_buf->seq_nr = cpu_to_le64(line->seq_nr);
+ smeta_buf->window_wr_lun = cpu_to_le32(geo->nr_luns);
/* Fill metadata among lines */
if (cur) {
memcpy(line->lun_bitmap, cur->lun_bitmap, lm->lun_bitmap_len);
- smeta->prev_id = cpu_to_le32(cur->id);
- cur->emeta->next_id = cpu_to_le32(line->id);
+ smeta_buf->prev_id = cpu_to_le32(cur->id);
+ cur->emeta->buf->next_id = cpu_to_le32(line->id);
} else {
- smeta->prev_id = cpu_to_le32(PBLK_LINE_EMPTY);
+ smeta_buf->prev_id = cpu_to_le32(PBLK_LINE_EMPTY);
}
/* All smeta must be set at this point */
- smeta->header.crc = cpu_to_le32(pblk_calc_meta_header_crc(pblk, smeta));
- smeta->crc = cpu_to_le32(pblk_calc_smeta_crc(pblk, smeta));
+ smeta_buf->header.crc = cpu_to_le32(
+ pblk_calc_meta_header_crc(pblk, &smeta_buf->header));
+ smeta_buf->crc = cpu_to_le32(pblk_calc_smeta_crc(pblk, smeta_buf));
/* End metadata */
- memcpy(&emeta->header, &smeta->header, sizeof(struct line_header));
- emeta->seq_nr = cpu_to_le64(line->seq_nr);
- emeta->nr_lbas = cpu_to_le64(line->sec_in_line);
- emeta->nr_valid_lbas = cpu_to_le64(0);
- emeta->next_id = cpu_to_le32(PBLK_LINE_EMPTY);
- emeta->crc = cpu_to_le32(0);
- emeta->prev_id = smeta->prev_id;
+ memcpy(&emeta_buf->header, &smeta_buf->header,
+ sizeof(struct line_header));
+ emeta_buf->seq_nr = cpu_to_le64(line->seq_nr);
+ emeta_buf->nr_lbas = cpu_to_le64(line->sec_in_line);
+ emeta_buf->nr_valid_lbas = cpu_to_le64(0);
+ emeta_buf->next_id = cpu_to_le32(PBLK_LINE_EMPTY);
+ emeta_buf->crc = cpu_to_le32(0);
+ emeta_buf->prev_id = smeta_buf->prev_id;
return 1;
}
@@ -965,7 +1041,6 @@ static int pblk_line_init_bb(struct pblk *pblk, struct pblk_line *line,
/* Mark smeta metadata sectors as bad sectors */
bit = find_first_zero_bit(line->blk_bitmap, lm->blk_per_line);
off = bit * geo->sec_per_pl;
-retry_smeta:
bitmap_set(line->map_bitmap, off, lm->smeta_sec);
line->sec_in_line -= lm->smeta_sec;
line->smeta_ssec = off;
@@ -973,8 +1048,7 @@ retry_smeta:
if (init && pblk_line_submit_smeta_io(pblk, line, off, WRITE)) {
pr_debug("pblk: line smeta I/O failed. Retry\n");
- off += geo->sec_per_pl;
- goto retry_smeta;
+ return 1;
}
bitmap_copy(line->invalid_bitmap, line->map_bitmap, lm->sec_per_line);
@@ -983,8 +1057,8 @@ retry_smeta:
* blocks to make sure that there are enough sectors to store emeta
*/
bit = lm->sec_per_line;
- off = lm->sec_per_line - lm->emeta_sec;
- bitmap_set(line->invalid_bitmap, off, lm->emeta_sec);
+ off = lm->sec_per_line - lm->emeta_sec[0];
+ bitmap_set(line->invalid_bitmap, off, lm->emeta_sec[0]);
while (nr_bb) {
off -= geo->sec_per_pl;
if (!test_bit(off, line->invalid_bitmap)) {
@@ -993,9 +1067,11 @@ retry_smeta:
}
}
- line->sec_in_line -= lm->emeta_sec;
+ line->sec_in_line -= lm->emeta_sec[0];
line->emeta_ssec = off;
- line->vsc = line->left_ssecs = line->left_msecs = line->sec_in_line;
+ line->nr_valid_lbas = 0;
+ line->left_msecs = line->sec_in_line;
+ *line->vsc = cpu_to_le32(line->sec_in_line);
if (lm->sec_per_line - line->sec_in_line !=
bitmap_weight(line->invalid_bitmap, lm->sec_per_line)) {
@@ -1034,14 +1110,20 @@ static int pblk_line_prepare(struct pblk *pblk, struct pblk_line *line)
spin_lock(&line->lock);
if (line->state != PBLK_LINESTATE_FREE) {
+ mempool_free(line->invalid_bitmap, pblk->line_meta_pool);
+ mempool_free(line->map_bitmap, pblk->line_meta_pool);
spin_unlock(&line->lock);
- WARN(1, "pblk: corrupted line state\n");
- return -EINTR;
+ WARN(1, "pblk: corrupted line %d, state %d\n",
+ line->id, line->state);
+ return -EAGAIN;
}
+
line->state = PBLK_LINESTATE_OPEN;
atomic_set(&line->left_eblks, blk_in_line);
atomic_set(&line->left_seblks, blk_in_line);
+
+ line->meta_distance = lm->meta_distance;
spin_unlock(&line->lock);
/* Bad blocks do not need to be erased */
@@ -1091,15 +1173,15 @@ struct pblk_line *pblk_line_get(struct pblk *pblk)
{
struct pblk_line_mgmt *l_mg = &pblk->l_mg;
struct pblk_line_meta *lm = &pblk->lm;
- struct pblk_line *line = NULL;
- int bit;
+ struct pblk_line *line;
+ int ret, bit;
lockdep_assert_held(&l_mg->free_lock);
-retry_get:
+retry:
if (list_empty(&l_mg->free_list)) {
pr_err("pblk: no free lines\n");
- goto out;
+ return NULL;
}
line = list_first_entry(&l_mg->free_list, struct pblk_line, list);
@@ -1115,16 +1197,22 @@ retry_get:
list_add_tail(&line->list, &l_mg->bad_list);
pr_debug("pblk: line %d is bad\n", line->id);
- goto retry_get;
+ goto retry;
}
- if (pblk_line_prepare(pblk, line)) {
- pr_err("pblk: failed to prepare line %d\n", line->id);
- list_add(&line->list, &l_mg->free_list);
- return NULL;
+ ret = pblk_line_prepare(pblk, line);
+ if (ret) {
+ if (ret == -EAGAIN) {
+ list_add(&line->list, &l_mg->corrupt_list);
+ goto retry;
+ } else {
+ pr_err("pblk: failed to prepare line %d\n", line->id);
+ list_add(&line->list, &l_mg->free_list);
+ l_mg->nr_free_lines++;
+ return NULL;
+ }
}
-out:
return line;
}
@@ -1134,6 +1222,7 @@ static struct pblk_line *pblk_line_retry(struct pblk *pblk,
struct pblk_line_mgmt *l_mg = &pblk->l_mg;
struct pblk_line *retry_line;
+retry:
spin_lock(&l_mg->free_lock);
retry_line = pblk_line_get(pblk);
if (!retry_line) {
@@ -1150,23 +1239,25 @@ static struct pblk_line *pblk_line_retry(struct pblk *pblk,
l_mg->data_line = retry_line;
spin_unlock(&l_mg->free_lock);
- if (pblk_line_erase(pblk, retry_line)) {
- spin_lock(&l_mg->free_lock);
- l_mg->data_line = NULL;
- spin_unlock(&l_mg->free_lock);
- return NULL;
- }
-
pblk_rl_free_lines_dec(&pblk->rl, retry_line);
+ if (pblk_line_erase(pblk, retry_line))
+ goto retry;
+
return retry_line;
}
+static void pblk_set_space_limit(struct pblk *pblk)
+{
+ struct pblk_rl *rl = &pblk->rl;
+
+ atomic_set(&rl->rb_space, 0);
+}
+
struct pblk_line *pblk_line_get_first_data(struct pblk *pblk)
{
struct pblk_line_mgmt *l_mg = &pblk->l_mg;
struct pblk_line *line;
- int meta_line;
int is_next = 0;
spin_lock(&l_mg->free_lock);
@@ -1180,30 +1271,37 @@ struct pblk_line *pblk_line_get_first_data(struct pblk *pblk)
line->type = PBLK_LINETYPE_DATA;
l_mg->data_line = line;
- meta_line = find_first_zero_bit(&l_mg->meta_bitmap, PBLK_DATA_LINES);
- set_bit(meta_line, &l_mg->meta_bitmap);
- line->smeta = l_mg->sline_meta[meta_line].meta;
- line->emeta = l_mg->eline_meta[meta_line].meta;
- line->meta_line = meta_line;
+ pblk_line_setup_metadata(line, l_mg, &pblk->lm);
/* Allocate next line for preparation */
l_mg->data_next = pblk_line_get(pblk);
- if (l_mg->data_next) {
+ if (!l_mg->data_next) {
+ /* If we cannot get a new line, we need to stop the pipeline.
+ * Only allow as many writes in as we can store safely and then
+ * fail gracefully
+ */
+ pblk_set_space_limit(pblk);
+
+ l_mg->data_next = NULL;
+ } else {
l_mg->data_next->seq_nr = l_mg->d_seq_nr++;
l_mg->data_next->type = PBLK_LINETYPE_DATA;
is_next = 1;
}
spin_unlock(&l_mg->free_lock);
+ if (pblk_line_erase(pblk, line)) {
+ line = pblk_line_retry(pblk, line);
+ if (!line)
+ return NULL;
+ }
+
pblk_rl_free_lines_dec(&pblk->rl, line);
if (is_next)
pblk_rl_free_lines_dec(&pblk->rl, l_mg->data_next);
- if (pblk_line_erase(pblk, line))
- return NULL;
-
retry_setup:
- if (!pblk_line_set_metadata(pblk, line, NULL)) {
+ if (!pblk_line_init_metadata(pblk, line, NULL)) {
line = pblk_line_retry(pblk, line);
if (!line)
return NULL;
@@ -1222,69 +1320,89 @@ retry_setup:
return line;
}
-struct pblk_line *pblk_line_replace_data(struct pblk *pblk)
+static void pblk_stop_writes(struct pblk *pblk, struct pblk_line *line)
+{
+ lockdep_assert_held(&pblk->l_mg.free_lock);
+
+ pblk_set_space_limit(pblk);
+ pblk->state = PBLK_STATE_STOPPING;
+}
+
+void pblk_pipeline_stop(struct pblk *pblk)
+{
+ struct pblk_line_mgmt *l_mg = &pblk->l_mg;
+ int ret;
+
+ spin_lock(&l_mg->free_lock);
+ if (pblk->state == PBLK_STATE_RECOVERING ||
+ pblk->state == PBLK_STATE_STOPPED) {
+ spin_unlock(&l_mg->free_lock);
+ return;
+ }
+ pblk->state = PBLK_STATE_RECOVERING;
+ spin_unlock(&l_mg->free_lock);
+
+ pblk_flush_writer(pblk);
+ pblk_wait_for_meta(pblk);
+
+ ret = pblk_recov_pad(pblk);
+ if (ret) {
+ pr_err("pblk: could not close data on teardown(%d)\n", ret);
+ return;
+ }
+
+ flush_workqueue(pblk->bb_wq);
+ pblk_line_close_meta_sync(pblk);
+
+ spin_lock(&l_mg->free_lock);
+ pblk->state = PBLK_STATE_STOPPED;
+ l_mg->data_line = NULL;
+ l_mg->data_next = NULL;
+ spin_unlock(&l_mg->free_lock);
+}
+
+void pblk_line_replace_data(struct pblk *pblk)
{
- struct pblk_line_meta *lm = &pblk->lm;
struct pblk_line_mgmt *l_mg = &pblk->l_mg;
struct pblk_line *cur, *new;
unsigned int left_seblks;
- int meta_line;
int is_next = 0;
cur = l_mg->data_line;
new = l_mg->data_next;
if (!new)
- return NULL;
+ return;
l_mg->data_line = new;
-retry_line:
+ spin_lock(&l_mg->free_lock);
+ if (pblk->state != PBLK_STATE_RUNNING) {
+ l_mg->data_line = NULL;
+ l_mg->data_next = NULL;
+ spin_unlock(&l_mg->free_lock);
+ return;
+ }
+
+ pblk_line_setup_metadata(new, l_mg, &pblk->lm);
+ spin_unlock(&l_mg->free_lock);
+
+retry_erase:
left_seblks = atomic_read(&new->left_seblks);
if (left_seblks) {
/* If line is not fully erased, erase it */
if (atomic_read(&new->left_eblks)) {
if (pblk_line_erase(pblk, new))
- return NULL;
+ return;
} else {
io_schedule();
}
- goto retry_line;
+ goto retry_erase;
}
- spin_lock(&l_mg->free_lock);
- /* Allocate next line for preparation */
- l_mg->data_next = pblk_line_get(pblk);
- if (l_mg->data_next) {
- l_mg->data_next->seq_nr = l_mg->d_seq_nr++;
- l_mg->data_next->type = PBLK_LINETYPE_DATA;
- is_next = 1;
- }
-
-retry_meta:
- meta_line = find_first_zero_bit(&l_mg->meta_bitmap, PBLK_DATA_LINES);
- if (meta_line == PBLK_DATA_LINES) {
- spin_unlock(&l_mg->free_lock);
- io_schedule();
- spin_lock(&l_mg->free_lock);
- goto retry_meta;
- }
-
- set_bit(meta_line, &l_mg->meta_bitmap);
- new->smeta = l_mg->sline_meta[meta_line].meta;
- new->emeta = l_mg->eline_meta[meta_line].meta;
- new->meta_line = meta_line;
-
- memset(new->smeta, 0, lm->smeta_len);
- memset(new->emeta, 0, lm->emeta_len);
- spin_unlock(&l_mg->free_lock);
-
- if (is_next)
- pblk_rl_free_lines_dec(&pblk->rl, l_mg->data_next);
-
retry_setup:
- if (!pblk_line_set_metadata(pblk, new, cur)) {
+ if (!pblk_line_init_metadata(pblk, new, cur)) {
new = pblk_line_retry(pblk, new);
if (!new)
- return NULL;
+ return;
goto retry_setup;
}
@@ -1292,12 +1410,30 @@ retry_setup:
if (!pblk_line_init_bb(pblk, new, 1)) {
new = pblk_line_retry(pblk, new);
if (!new)
- return NULL;
+ return;
goto retry_setup;
}
- return new;
+ /* Allocate next line for preparation */
+ spin_lock(&l_mg->free_lock);
+ l_mg->data_next = pblk_line_get(pblk);
+ if (!l_mg->data_next) {
+ /* If we cannot get a new line, we need to stop the pipeline.
+ * Only allow as many writes in as we can store safely and then
+ * fail gracefully
+ */
+ pblk_stop_writes(pblk, new);
+ l_mg->data_next = NULL;
+ } else {
+ l_mg->data_next->seq_nr = l_mg->d_seq_nr++;
+ l_mg->data_next->type = PBLK_LINETYPE_DATA;
+ is_next = 1;
+ }
+ spin_unlock(&l_mg->free_lock);
+
+ if (is_next)
+ pblk_rl_free_lines_dec(&pblk->rl, l_mg->data_next);
}
void pblk_line_free(struct pblk *pblk, struct pblk_line *line)
@@ -1307,6 +1443,8 @@ void pblk_line_free(struct pblk *pblk, struct pblk_line *line)
if (line->invalid_bitmap)
mempool_free(line->invalid_bitmap, pblk->line_meta_pool);
+ *line->vsc = cpu_to_le32(EMPTY_ENTRY);
+
line->map_bitmap = NULL;
line->invalid_bitmap = NULL;
line->smeta = NULL;
@@ -1339,8 +1477,8 @@ int pblk_blk_erase_async(struct pblk *pblk, struct ppa_addr ppa)
struct nvm_rq *rqd;
int err;
- rqd = mempool_alloc(pblk->r_rq_pool, GFP_KERNEL);
- memset(rqd, 0, pblk_r_rq_size);
+ rqd = mempool_alloc(pblk->g_rq_pool, GFP_KERNEL);
+ memset(rqd, 0, pblk_g_rq_size);
pblk_setup_e_rq(pblk, rqd, ppa);
@@ -1368,7 +1506,8 @@ struct pblk_line *pblk_line_get_data(struct pblk *pblk)
return pblk->l_mg.data_line;
}
-struct pblk_line *pblk_line_get_data_next(struct pblk *pblk)
+/* For now, always erase next line */
+struct pblk_line *pblk_line_get_erase(struct pblk *pblk)
{
return pblk->l_mg.data_next;
}
@@ -1378,18 +1517,58 @@ int pblk_line_is_full(struct pblk_line *line)
return (line->left_msecs == 0);
}
+void pblk_line_close_meta_sync(struct pblk *pblk)
+{
+ struct pblk_line_mgmt *l_mg = &pblk->l_mg;
+ struct pblk_line_meta *lm = &pblk->lm;
+ struct pblk_line *line, *tline;
+ LIST_HEAD(list);
+
+ spin_lock(&l_mg->close_lock);
+ if (list_empty(&l_mg->emeta_list)) {
+ spin_unlock(&l_mg->close_lock);
+ return;
+ }
+
+ list_cut_position(&list, &l_mg->emeta_list, l_mg->emeta_list.prev);
+ spin_unlock(&l_mg->close_lock);
+
+ list_for_each_entry_safe(line, tline, &list, list) {
+ struct pblk_emeta *emeta = line->emeta;
+
+ while (emeta->mem < lm->emeta_len[0]) {
+ int ret;
+
+ ret = pblk_submit_meta_io(pblk, line);
+ if (ret) {
+ pr_err("pblk: sync meta line %d failed (%d)\n",
+ line->id, ret);
+ return;
+ }
+ }
+ }
+
+ pblk_wait_for_meta(pblk);
+ flush_workqueue(pblk->close_wq);
+}
+
+static void pblk_line_should_sync_meta(struct pblk *pblk)
+{
+ if (pblk_rl_is_limit(&pblk->rl))
+ pblk_line_close_meta_sync(pblk);
+}
+
void pblk_line_close(struct pblk *pblk, struct pblk_line *line)
{
struct pblk_line_mgmt *l_mg = &pblk->l_mg;
struct list_head *move_list;
- line->emeta->crc = cpu_to_le32(pblk_calc_emeta_crc(pblk, line->emeta));
-
- if (pblk_line_submit_emeta_io(pblk, line, line->cur_sec, WRITE))
- pr_err("pblk: line %d close I/O failed\n", line->id);
+#ifdef CONFIG_NVM_DEBUG
+ struct pblk_line_meta *lm = &pblk->lm;
- WARN(!bitmap_full(line->map_bitmap, line->sec_in_line),
+ WARN(!bitmap_full(line->map_bitmap, lm->sec_per_line),
"pblk: corrupt closed line %d\n", line->id);
+#endif
spin_lock(&l_mg->free_lock);
WARN_ON(!test_and_clear_bit(line->meta_line, &l_mg->meta_bitmap));
@@ -1410,6 +1589,31 @@ void pblk_line_close(struct pblk *pblk, struct pblk_line *line)
spin_unlock(&line->lock);
spin_unlock(&l_mg->gc_lock);
+
+ pblk_gc_should_kick(pblk);
+}
+
+void pblk_line_close_meta(struct pblk *pblk, struct pblk_line *line)
+{
+ struct pblk_line_mgmt *l_mg = &pblk->l_mg;
+ struct pblk_line_meta *lm = &pblk->lm;
+ struct pblk_emeta *emeta = line->emeta;
+ struct line_emeta *emeta_buf = emeta->buf;
+
+ /* No need for exact vsc value; avoid a big line lock and take aprox. */
+ memcpy(emeta_to_vsc(pblk, emeta_buf), l_mg->vsc_list, lm->vsc_list_len);
+ memcpy(emeta_to_bb(emeta_buf), line->blk_bitmap, lm->blk_bitmap_len);
+
+ emeta_buf->nr_valid_lbas = cpu_to_le64(line->nr_valid_lbas);
+ emeta_buf->crc = cpu_to_le32(pblk_calc_emeta_crc(pblk, emeta_buf));
+
+ spin_lock(&l_mg->close_lock);
+ spin_lock(&line->lock);
+ list_add_tail(&line->list, &l_mg->emeta_list);
+ spin_unlock(&line->lock);
+ spin_unlock(&l_mg->close_lock);
+
+ pblk_line_should_sync_meta(pblk);
}
void pblk_line_close_ws(struct work_struct *work)
@@ -1449,7 +1653,8 @@ void pblk_line_mark_bb(struct work_struct *work)
}
void pblk_line_run_ws(struct pblk *pblk, struct pblk_line *line, void *priv,
- void (*work)(struct work_struct *))
+ void (*work)(struct work_struct *),
+ struct workqueue_struct *wq)
{
struct pblk_line_ws *line_ws;
@@ -1462,7 +1667,7 @@ void pblk_line_run_ws(struct pblk *pblk, struct pblk_line *line, void *priv,
line_ws->priv = priv;
INIT_WORK(&line_ws->ws, work);
- queue_work(pblk->kw_wq, &line_ws->ws);
+ queue_work(wq, &line_ws->ws);
}
void pblk_down_rq(struct pblk *pblk, struct ppa_addr *ppa_list, int nr_ppas,
@@ -1471,7 +1676,7 @@ void pblk_down_rq(struct pblk *pblk, struct ppa_addr *ppa_list, int nr_ppas,
struct nvm_tgt_dev *dev = pblk->dev;
struct nvm_geo *geo = &dev->geo;
struct pblk_lun *rlun;
- int lun_id = ppa_list[0].g.ch * geo->luns_per_chnl + ppa_list[0].g.lun;
+ int pos = pblk_ppa_to_pos(geo, ppa_list[0]);
int ret;
/*
@@ -1488,10 +1693,10 @@ void pblk_down_rq(struct pblk *pblk, struct ppa_addr *ppa_list, int nr_ppas,
/* If the LUN has been locked for this same request, do no attempt to
* lock it again
*/
- if (test_and_set_bit(lun_id, lun_bitmap))
+ if (test_and_set_bit(pos, lun_bitmap))
return;
- rlun = &pblk->luns[lun_id];
+ rlun = &pblk->luns[pos];
ret = down_timeout(&rlun->wr_sem, msecs_to_jiffies(5000));
if (ret) {
switch (ret) {
diff --git a/drivers/lightnvm/pblk-gc.c b/drivers/lightnvm/pblk-gc.c
index eaf479c6b63c..6090d28f7995 100644
--- a/drivers/lightnvm/pblk-gc.c
+++ b/drivers/lightnvm/pblk-gc.c
@@ -20,8 +20,7 @@
static void pblk_gc_free_gc_rq(struct pblk_gc_rq *gc_rq)
{
- kfree(gc_rq->data);
- kfree(gc_rq->lba_list);
+ vfree(gc_rq->data);
kfree(gc_rq);
}
@@ -37,10 +36,8 @@ static int pblk_gc_write(struct pblk *pblk)
return 1;
}
- list_for_each_entry_safe(gc_rq, tgc_rq, &gc->w_list, list) {
- list_move_tail(&gc_rq->list, &w_list);
- gc->w_entries--;
- }
+ list_cut_position(&w_list, &gc->w_list, gc->w_list.prev);
+ gc->w_entries = 0;
spin_unlock(&gc->w_lock);
list_for_each_entry_safe(gc_rq, tgc_rq, &w_list, list) {
@@ -48,9 +45,8 @@ static int pblk_gc_write(struct pblk *pblk)
gc_rq->nr_secs, gc_rq->secs_to_gc,
gc_rq->line, PBLK_IOTYPE_GC);
- kref_put(&gc_rq->line->ref, pblk_line_put);
-
list_del(&gc_rq->list);
+ kref_put(&gc_rq->line->ref, pblk_line_put);
pblk_gc_free_gc_rq(gc_rq);
}
@@ -66,52 +62,41 @@ static void pblk_gc_writer_kick(struct pblk_gc *gc)
* Responsible for managing all memory related to a gc request. Also in case of
* failure
*/
-static int pblk_gc_move_valid_secs(struct pblk *pblk, struct pblk_line *line,
- u64 *lba_list, unsigned int nr_secs)
+static int pblk_gc_move_valid_secs(struct pblk *pblk, struct pblk_gc_rq *gc_rq)
{
struct nvm_tgt_dev *dev = pblk->dev;
struct nvm_geo *geo = &dev->geo;
struct pblk_gc *gc = &pblk->gc;
- struct pblk_gc_rq *gc_rq;
+ struct pblk_line *line = gc_rq->line;
void *data;
unsigned int secs_to_gc;
- int ret = NVM_IO_OK;
+ int ret = 0;
- data = kmalloc(nr_secs * geo->sec_size, GFP_KERNEL);
+ data = vmalloc(gc_rq->nr_secs * geo->sec_size);
if (!data) {
- ret = NVM_IO_ERR;
- goto free_lba_list;
+ ret = -ENOMEM;
+ goto out;
}
/* Read from GC victim block */
- if (pblk_submit_read_gc(pblk, lba_list, data, nr_secs,
+ if (pblk_submit_read_gc(pblk, gc_rq->lba_list, data, gc_rq->nr_secs,
&secs_to_gc, line)) {
- ret = NVM_IO_ERR;
+ ret = -EFAULT;
goto free_data;
}
if (!secs_to_gc)
- goto free_data;
-
- gc_rq = kmalloc(sizeof(struct pblk_gc_rq), GFP_KERNEL);
- if (!gc_rq) {
- ret = NVM_IO_ERR;
- goto free_data;
- }
+ goto free_rq;
- gc_rq->line = line;
gc_rq->data = data;
- gc_rq->lba_list = lba_list;
- gc_rq->nr_secs = nr_secs;
gc_rq->secs_to_gc = secs_to_gc;
- kref_get(&line->ref);
-
retry:
spin_lock(&gc->w_lock);
- if (gc->w_entries > 256) {
+ if (gc->w_entries >= PBLK_GC_W_QD) {
spin_unlock(&gc->w_lock);
- usleep_range(256, 1024);
+ pblk_gc_writer_kick(&pblk->gc);
+ usleep_range(128, 256);
goto retry;
}
gc->w_entries++;
@@ -120,13 +105,14 @@ retry:
pblk_gc_writer_kick(&pblk->gc);
- return NVM_IO_OK;
+ return 0;
+free_rq:
+ kfree(gc_rq);
free_data:
- kfree(data);
-free_lba_list:
- kfree(lba_list);
-
+ vfree(data);
+out:
+ kref_put(&line->ref, pblk_line_put);
return ret;
}
@@ -150,140 +136,206 @@ static void pblk_put_line_back(struct pblk *pblk, struct pblk_line *line)
static void pblk_gc_line_ws(struct work_struct *work)
{
+ struct pblk_line_ws *line_rq_ws = container_of(work,
+ struct pblk_line_ws, ws);
+ struct pblk *pblk = line_rq_ws->pblk;
+ struct pblk_gc *gc = &pblk->gc;
+ struct pblk_line *line = line_rq_ws->line;
+ struct pblk_gc_rq *gc_rq = line_rq_ws->priv;
+
+ up(&gc->gc_sem);
+
+ if (pblk_gc_move_valid_secs(pblk, gc_rq)) {
+ pr_err("pblk: could not GC all sectors: line:%d (%d/%d)\n",
+ line->id, *line->vsc,
+ gc_rq->nr_secs);
+ }
+
+ mempool_free(line_rq_ws, pblk->line_ws_pool);
+}
+
+static void pblk_gc_line_prepare_ws(struct work_struct *work)
+{
struct pblk_line_ws *line_ws = container_of(work, struct pblk_line_ws,
ws);
struct pblk *pblk = line_ws->pblk;
- struct pblk_line_mgmt *l_mg = &pblk->l_mg;
struct pblk_line *line = line_ws->line;
+ struct pblk_line_mgmt *l_mg = &pblk->l_mg;
struct pblk_line_meta *lm = &pblk->lm;
- __le64 *lba_list = line_ws->priv;
- u64 *gc_list;
- int sec_left;
- int nr_ppas, bit;
- int put_line = 1;
+ struct pblk_gc *gc = &pblk->gc;
+ struct line_emeta *emeta_buf;
+ struct pblk_line_ws *line_rq_ws;
+ struct pblk_gc_rq *gc_rq;
+ __le64 *lba_list;
+ int sec_left, nr_secs, bit;
+ int ret;
- pr_debug("pblk: line '%d' being reclaimed for GC\n", line->id);
+ emeta_buf = pblk_malloc(lm->emeta_len[0], l_mg->emeta_alloc_type,
+ GFP_KERNEL);
+ if (!emeta_buf) {
+ pr_err("pblk: cannot use GC emeta\n");
+ return;
+ }
- spin_lock(&line->lock);
- sec_left = line->vsc;
- if (!sec_left) {
- /* Lines are erased before being used (l_mg->data_/log_next) */
- spin_unlock(&line->lock);
- goto out;
+ ret = pblk_line_read_emeta(pblk, line, emeta_buf);
+ if (ret) {
+ pr_err("pblk: line %d read emeta failed (%d)\n", line->id, ret);
+ goto fail_free_emeta;
+ }
+
+ /* If this read fails, it means that emeta is corrupted. For now, leave
+ * the line untouched. TODO: Implement a recovery routine that scans and
+ * moves all sectors on the line.
+ */
+ lba_list = pblk_recov_get_lba_list(pblk, emeta_buf);
+ if (!lba_list) {
+ pr_err("pblk: could not interpret emeta (line %d)\n", line->id);
+ goto fail_free_emeta;
}
- spin_unlock(&line->lock);
+ sec_left = pblk_line_vsc(line);
if (sec_left < 0) {
pr_err("pblk: corrupted GC line (%d)\n", line->id);
- put_line = 0;
- pblk_put_line_back(pblk, line);
- goto out;
+ goto fail_free_emeta;
}
bit = -1;
next_rq:
- gc_list = kmalloc_array(pblk->max_write_pgs, sizeof(u64), GFP_KERNEL);
- if (!gc_list) {
- put_line = 0;
- pblk_put_line_back(pblk, line);
- goto out;
- }
+ gc_rq = kmalloc(sizeof(struct pblk_gc_rq), GFP_KERNEL);
+ if (!gc_rq)
+ goto fail_free_emeta;
- nr_ppas = 0;
+ nr_secs = 0;
do {
bit = find_next_zero_bit(line->invalid_bitmap, lm->sec_per_line,
bit + 1);
if (bit > line->emeta_ssec)
break;
- gc_list[nr_ppas++] = le64_to_cpu(lba_list[bit]);
- } while (nr_ppas < pblk->max_write_pgs);
+ gc_rq->lba_list[nr_secs++] = le64_to_cpu(lba_list[bit]);
+ } while (nr_secs < pblk->max_write_pgs);
- if (unlikely(!nr_ppas)) {
- kfree(gc_list);
+ if (unlikely(!nr_secs)) {
+ kfree(gc_rq);
goto out;
}
- if (pblk_gc_move_valid_secs(pblk, line, gc_list, nr_ppas)) {
- pr_err("pblk: could not GC all sectors: line:%d (%d/%d/%d)\n",
- line->id, line->vsc,
- nr_ppas, nr_ppas);
- put_line = 0;
- pblk_put_line_back(pblk, line);
- goto out;
- }
+ gc_rq->nr_secs = nr_secs;
+ gc_rq->line = line;
+
+ line_rq_ws = mempool_alloc(pblk->line_ws_pool, GFP_KERNEL);
+ if (!line_rq_ws)
+ goto fail_free_gc_rq;
- sec_left -= nr_ppas;
+ line_rq_ws->pblk = pblk;
+ line_rq_ws->line = line;
+ line_rq_ws->priv = gc_rq;
+
+ down(&gc->gc_sem);
+ kref_get(&line->ref);
+
+ INIT_WORK(&line_rq_ws->ws, pblk_gc_line_ws);
+ queue_work(gc->gc_line_reader_wq, &line_rq_ws->ws);
+
+ sec_left -= nr_secs;
if (sec_left > 0)
goto next_rq;
out:
- pblk_mfree(line->emeta, l_mg->emeta_alloc_type);
+ pblk_mfree(emeta_buf, l_mg->emeta_alloc_type);
mempool_free(line_ws, pblk->line_ws_pool);
- atomic_dec(&pblk->gc.inflight_gc);
- if (put_line)
- kref_put(&line->ref, pblk_line_put);
+
+ kref_put(&line->ref, pblk_line_put);
+ atomic_dec(&gc->inflight_gc);
+
+ return;
+
+fail_free_gc_rq:
+ kfree(gc_rq);
+fail_free_emeta:
+ pblk_mfree(emeta_buf, l_mg->emeta_alloc_type);
+ pblk_put_line_back(pblk, line);
+ kref_put(&line->ref, pblk_line_put);
+ mempool_free(line_ws, pblk->line_ws_pool);
+ atomic_dec(&gc->inflight_gc);
+
+ pr_err("pblk: Failed to GC line %d\n", line->id);
}
static int pblk_gc_line(struct pblk *pblk, struct pblk_line *line)
{
- struct pblk_line_mgmt *l_mg = &pblk->l_mg;
- struct pblk_line_meta *lm = &pblk->lm;
+ struct pblk_gc *gc = &pblk->gc;
struct pblk_line_ws *line_ws;
- __le64 *lba_list;
- int ret;
- line_ws = mempool_alloc(pblk->line_ws_pool, GFP_KERNEL);
- line->emeta = pblk_malloc(lm->emeta_len, l_mg->emeta_alloc_type,
- GFP_KERNEL);
- if (!line->emeta) {
- pr_err("pblk: cannot use GC emeta\n");
- goto fail_free_ws;
- }
-
- ret = pblk_line_read_emeta(pblk, line);
- if (ret) {
- pr_err("pblk: line %d read emeta failed (%d)\n", line->id, ret);
- goto fail_free_emeta;
- }
+ pr_debug("pblk: line '%d' being reclaimed for GC\n", line->id);
- /* If this read fails, it means that emeta is corrupted. For now, leave
- * the line untouched. TODO: Implement a recovery routine that scans and
- * moves all sectors on the line.
- */
- lba_list = pblk_recov_get_lba_list(pblk, line->emeta);
- if (!lba_list) {
- pr_err("pblk: could not interpret emeta (line %d)\n", line->id);
- goto fail_free_emeta;
- }
+ line_ws = mempool_alloc(pblk->line_ws_pool, GFP_KERNEL);
+ if (!line_ws)
+ return -ENOMEM;
line_ws->pblk = pblk;
line_ws->line = line;
- line_ws->priv = lba_list;
- INIT_WORK(&line_ws->ws, pblk_gc_line_ws);
- queue_work(pblk->gc.gc_reader_wq, &line_ws->ws);
+ INIT_WORK(&line_ws->ws, pblk_gc_line_prepare_ws);
+ queue_work(gc->gc_reader_wq, &line_ws->ws);
return 0;
+}
-fail_free_emeta:
- pblk_mfree(line->emeta, l_mg->emeta_alloc_type);
-fail_free_ws:
- mempool_free(line_ws, pblk->line_ws_pool);
- pblk_put_line_back(pblk, line);
+static int pblk_gc_read(struct pblk *pblk)
+{
+ struct pblk_gc *gc = &pblk->gc;
+ struct pblk_line *line;
+
+ spin_lock(&gc->r_lock);
+ if (list_empty(&gc->r_list)) {
+ spin_unlock(&gc->r_lock);
+ return 1;
+ }
+
+ line = list_first_entry(&gc->r_list, struct pblk_line, list);
+ list_del(&line->list);
+ spin_unlock(&gc->r_lock);
+
+ pblk_gc_kick(pblk);
- return 1;
+ if (pblk_gc_line(pblk, line))
+ pr_err("pblk: failed to GC line %d\n", line->id);
+
+ return 0;
}
-static void pblk_gc_lines(struct pblk *pblk, struct list_head *gc_list)
+static void pblk_gc_reader_kick(struct pblk_gc *gc)
{
- struct pblk_line *line, *tline;
+ wake_up_process(gc->gc_reader_ts);
+}
- list_for_each_entry_safe(line, tline, gc_list, list) {
- if (pblk_gc_line(pblk, line))
- pr_err("pblk: failed to GC line %d\n", line->id);
- list_del(&line->list);
+static struct pblk_line *pblk_gc_get_victim_line(struct pblk *pblk,
+ struct list_head *group_list)
+{
+ struct pblk_line *line, *victim;
+ int line_vsc, victim_vsc;
+
+ victim = list_first_entry(group_list, struct pblk_line, list);
+ list_for_each_entry(line, group_list, list) {
+ line_vsc = le32_to_cpu(*line->vsc);
+ victim_vsc = le32_to_cpu(*victim->vsc);
+ if (line_vsc < victim_vsc)
+ victim = line;
}
+
+ return victim;
+}
+
+static bool pblk_gc_should_run(struct pblk_gc *gc, struct pblk_rl *rl)
+{
+ unsigned int nr_blocks_free, nr_blocks_need;
+
+ nr_blocks_need = pblk_rl_high_thrs(rl);
+ nr_blocks_free = pblk_rl_nr_free_blks(rl);
+
+ /* This is not critical, no need to take lock here */
+ return ((gc->gc_active) && (nr_blocks_need > nr_blocks_free));
}
/*
@@ -296,71 +348,83 @@ static void pblk_gc_run(struct pblk *pblk)
{
struct pblk_line_mgmt *l_mg = &pblk->l_mg;
struct pblk_gc *gc = &pblk->gc;
- struct pblk_line *line, *tline;
- unsigned int nr_blocks_free, nr_blocks_need;
+ struct pblk_line *line;
struct list_head *group_list;
- int run_gc, gc_group = 0;
- int prev_gc = 0;
- int inflight_gc = atomic_read(&gc->inflight_gc);
- LIST_HEAD(gc_list);
+ bool run_gc;
+ int inflight_gc, gc_group = 0, prev_group = 0;
+
+ do {
+ spin_lock(&l_mg->gc_lock);
+ if (list_empty(&l_mg->gc_full_list)) {
+ spin_unlock(&l_mg->gc_lock);
+ break;
+ }
+
+ line = list_first_entry(&l_mg->gc_full_list,
+ struct pblk_line, list);
- spin_lock(&l_mg->gc_lock);
- list_for_each_entry_safe(line, tline, &l_mg->gc_full_list, list) {
spin_lock(&line->lock);
WARN_ON(line->state != PBLK_LINESTATE_CLOSED);
line->state = PBLK_LINESTATE_GC;
spin_unlock(&line->lock);
list_del(&line->list);
+ spin_unlock(&l_mg->gc_lock);
+
kref_put(&line->ref, pblk_line_put);
- }
- spin_unlock(&l_mg->gc_lock);
+ } while (1);
- nr_blocks_need = pblk_rl_gc_thrs(&pblk->rl);
- nr_blocks_free = pblk_rl_nr_free_blks(&pblk->rl);
- run_gc = (nr_blocks_need > nr_blocks_free || gc->gc_forced);
+ run_gc = pblk_gc_should_run(&pblk->gc, &pblk->rl);
+ if (!run_gc || (atomic_read(&gc->inflight_gc) >= PBLK_GC_L_QD))
+ return;
next_gc_group:
group_list = l_mg->gc_lists[gc_group++];
- spin_lock(&l_mg->gc_lock);
- while (run_gc && !list_empty(group_list)) {
- /* No need to queue up more GC lines than we can handle */
- if (!run_gc || inflight_gc > gc->gc_jobs_active) {
+
+ do {
+ spin_lock(&l_mg->gc_lock);
+ if (list_empty(group_list)) {
spin_unlock(&l_mg->gc_lock);
- pblk_gc_lines(pblk, &gc_list);
- return;
+ break;
}
- line = list_first_entry(group_list, struct pblk_line, list);
- nr_blocks_free += atomic_read(&line->blk_in_line);
+ line = pblk_gc_get_victim_line(pblk, group_list);
spin_lock(&line->lock);
WARN_ON(line->state != PBLK_LINESTATE_CLOSED);
line->state = PBLK_LINESTATE_GC;
- list_move_tail(&line->list, &gc_list);
- atomic_inc(&gc->inflight_gc);
- inflight_gc++;
spin_unlock(&line->lock);
- prev_gc = 1;
- run_gc = (nr_blocks_need > nr_blocks_free || gc->gc_forced);
- }
- spin_unlock(&l_mg->gc_lock);
+ list_del(&line->list);
+ spin_unlock(&l_mg->gc_lock);
+
+ spin_lock(&gc->r_lock);
+ list_add_tail(&line->list, &gc->r_list);
+ spin_unlock(&gc->r_lock);
- pblk_gc_lines(pblk, &gc_list);
+ inflight_gc = atomic_inc_return(&gc->inflight_gc);
+ pblk_gc_reader_kick(gc);
- if (!prev_gc && pblk->rl.rb_state > gc_group &&
- gc_group < PBLK_NR_GC_LISTS)
+ prev_group = 1;
+
+ /* No need to queue up more GC lines than we can handle */
+ run_gc = pblk_gc_should_run(&pblk->gc, &pblk->rl);
+ if (!run_gc || inflight_gc >= PBLK_GC_L_QD)
+ break;
+ } while (1);
+
+ if (!prev_group && pblk->rl.rb_state > gc_group &&
+ gc_group < PBLK_GC_NR_LISTS)
goto next_gc_group;
}
-
-static void pblk_gc_kick(struct pblk *pblk)
+void pblk_gc_kick(struct pblk *pblk)
{
struct pblk_gc *gc = &pblk->gc;
wake_up_process(gc->gc_ts);
pblk_gc_writer_kick(gc);
+ pblk_gc_reader_kick(gc);
mod_timer(&gc->gc_timer, jiffies + msecs_to_jiffies(GC_TIME_MSECS));
}
@@ -398,42 +462,34 @@ static int pblk_gc_writer_ts(void *data)
return 0;
}
-static void pblk_gc_start(struct pblk *pblk)
+static int pblk_gc_reader_ts(void *data)
{
- pblk->gc.gc_active = 1;
+ struct pblk *pblk = data;
- pr_debug("pblk: gc start\n");
+ while (!kthread_should_stop()) {
+ if (!pblk_gc_read(pblk))
+ continue;
+ set_current_state(TASK_INTERRUPTIBLE);
+ io_schedule();
+ }
+
+ return 0;
}
-int pblk_gc_status(struct pblk *pblk)
+static void pblk_gc_start(struct pblk *pblk)
{
- struct pblk_gc *gc = &pblk->gc;
- int ret;
-
- spin_lock(&gc->lock);
- ret = gc->gc_active;
- spin_unlock(&gc->lock);
-
- return ret;
+ pblk->gc.gc_active = 1;
+ pr_debug("pblk: gc start\n");
}
-static void __pblk_gc_should_start(struct pblk *pblk)
+void pblk_gc_should_start(struct pblk *pblk)
{
struct pblk_gc *gc = &pblk->gc;
- lockdep_assert_held(&gc->lock);
-
if (gc->gc_enabled && !gc->gc_active)
pblk_gc_start(pblk);
-}
-void pblk_gc_should_start(struct pblk *pblk)
-{
- struct pblk_gc *gc = &pblk->gc;
-
- spin_lock(&gc->lock);
- __pblk_gc_should_start(pblk);
- spin_unlock(&gc->lock);
+ pblk_gc_kick(pblk);
}
/*
@@ -442,10 +498,7 @@ void pblk_gc_should_start(struct pblk *pblk)
*/
static void pblk_gc_stop(struct pblk *pblk, int flush_wq)
{
- spin_lock(&pblk->gc.lock);
pblk->gc.gc_active = 0;
- spin_unlock(&pblk->gc.lock);
-
pr_debug("pblk: gc stop\n");
}
@@ -468,20 +521,25 @@ void pblk_gc_sysfs_state_show(struct pblk *pblk, int *gc_enabled,
spin_unlock(&gc->lock);
}
-void pblk_gc_sysfs_force(struct pblk *pblk, int force)
+int pblk_gc_sysfs_force(struct pblk *pblk, int force)
{
struct pblk_gc *gc = &pblk->gc;
- int rsv = 0;
+
+ if (force < 0 || force > 1)
+ return -EINVAL;
spin_lock(&gc->lock);
- if (force) {
- gc->gc_enabled = 1;
- rsv = 64;
- }
- pblk_rl_set_gc_rsc(&pblk->rl, rsv);
gc->gc_forced = force;
- __pblk_gc_should_start(pblk);
+
+ if (force)
+ gc->gc_enabled = 1;
+ else
+ gc->gc_enabled = 0;
spin_unlock(&gc->lock);
+
+ pblk_gc_should_start(pblk);
+
+ return 0;
}
int pblk_gc_init(struct pblk *pblk)
@@ -503,30 +561,58 @@ int pblk_gc_init(struct pblk *pblk)
goto fail_free_main_kthread;
}
+ gc->gc_reader_ts = kthread_create(pblk_gc_reader_ts, pblk,
+ "pblk-gc-reader-ts");
+ if (IS_ERR(gc->gc_reader_ts)) {
+ pr_err("pblk: could not allocate GC reader kthread\n");
+ ret = PTR_ERR(gc->gc_reader_ts);
+ goto fail_free_writer_kthread;
+ }
+
setup_timer(&gc->gc_timer, pblk_gc_timer, (unsigned long)pblk);
mod_timer(&gc->gc_timer, jiffies + msecs_to_jiffies(GC_TIME_MSECS));
gc->gc_active = 0;
gc->gc_forced = 0;
gc->gc_enabled = 1;
- gc->gc_jobs_active = 8;
gc->w_entries = 0;
atomic_set(&gc->inflight_gc, 0);
- gc->gc_reader_wq = alloc_workqueue("pblk-gc-reader-wq",
- WQ_MEM_RECLAIM | WQ_UNBOUND, gc->gc_jobs_active);
+ /* Workqueue that reads valid sectors from a line and submit them to the
+ * GC writer to be recycled.
+ */
+ gc->gc_line_reader_wq = alloc_workqueue("pblk-gc-line-reader-wq",
+ WQ_MEM_RECLAIM | WQ_UNBOUND, PBLK_GC_MAX_READERS);
+ if (!gc->gc_line_reader_wq) {
+ pr_err("pblk: could not allocate GC line reader workqueue\n");
+ ret = -ENOMEM;
+ goto fail_free_reader_kthread;
+ }
+
+ /* Workqueue that prepare lines for GC */
+ gc->gc_reader_wq = alloc_workqueue("pblk-gc-line_wq",
+ WQ_MEM_RECLAIM | WQ_UNBOUND, 1);
if (!gc->gc_reader_wq) {
pr_err("pblk: could not allocate GC reader workqueue\n");
ret = -ENOMEM;
- goto fail_free_writer_kthread;
+ goto fail_free_reader_line_wq;
}
spin_lock_init(&gc->lock);
spin_lock_init(&gc->w_lock);
+ spin_lock_init(&gc->r_lock);
+
+ sema_init(&gc->gc_sem, 128);
+
INIT_LIST_HEAD(&gc->w_list);
+ INIT_LIST_HEAD(&gc->r_list);
return 0;
+fail_free_reader_line_wq:
+ destroy_workqueue(gc->gc_line_reader_wq);
+fail_free_reader_kthread:
+ kthread_stop(gc->gc_reader_ts);
fail_free_writer_kthread:
kthread_stop(gc->gc_writer_ts);
fail_free_main_kthread:
@@ -540,6 +626,7 @@ void pblk_gc_exit(struct pblk *pblk)
struct pblk_gc *gc = &pblk->gc;
flush_workqueue(gc->gc_reader_wq);
+ flush_workqueue(gc->gc_line_reader_wq);
del_timer(&gc->gc_timer);
pblk_gc_stop(pblk, 1);
@@ -547,9 +634,15 @@ void pblk_gc_exit(struct pblk *pblk)
if (gc->gc_ts)
kthread_stop(gc->gc_ts);
- if (pblk->gc.gc_reader_wq)
- destroy_workqueue(pblk->gc.gc_reader_wq);
+ if (gc->gc_reader_wq)
+ destroy_workqueue(gc->gc_reader_wq);
+
+ if (gc->gc_line_reader_wq)
+ destroy_workqueue(gc->gc_line_reader_wq);
if (gc->gc_writer_ts)
kthread_stop(gc->gc_writer_ts);
+
+ if (gc->gc_reader_ts)
+ kthread_stop(gc->gc_reader_ts);
}
diff --git a/drivers/lightnvm/pblk-init.c b/drivers/lightnvm/pblk-init.c
index ae8cd6d5af8b..1b0f61233c21 100644
--- a/drivers/lightnvm/pblk-init.c
+++ b/drivers/lightnvm/pblk-init.c
@@ -20,9 +20,10 @@
#include "pblk.h"
-static struct kmem_cache *pblk_blk_ws_cache, *pblk_rec_cache, *pblk_r_rq_cache,
- *pblk_w_rq_cache, *pblk_line_meta_cache;
+static struct kmem_cache *pblk_blk_ws_cache, *pblk_rec_cache, *pblk_g_rq_cache,
+ *pblk_w_rq_cache, *pblk_line_meta_cache;
static DECLARE_RWSEM(pblk_lock);
+struct bio_set *pblk_bio_set;
static int pblk_rw_io(struct request_queue *q, struct pblk *pblk,
struct bio *bio)
@@ -33,7 +34,7 @@ static int pblk_rw_io(struct request_queue *q, struct pblk *pblk,
* constraint. Writes can be of arbitrary size.
*/
if (bio_data_dir(bio) == READ) {
- blk_queue_split(q, &bio, q->bio_split);
+ blk_queue_split(q, &bio);
ret = pblk_submit_read(pblk, bio);
if (ret == NVM_IO_DONE && bio_flagged(bio, BIO_CLONED))
bio_put(bio);
@@ -46,7 +47,7 @@ static int pblk_rw_io(struct request_queue *q, struct pblk *pblk,
* available for user I/O.
*/
if (unlikely(pblk_get_secs(bio) >= pblk_rl_sysfs_rate_show(&pblk->rl)))
- blk_queue_split(q, &bio, q->bio_split);
+ blk_queue_split(q, &bio);
return pblk_write_to_cache(pblk, bio, PBLK_IOTYPE_USER);
}
@@ -199,9 +200,9 @@ static int pblk_init_global_caches(struct pblk *pblk)
return -ENOMEM;
}
- pblk_r_rq_cache = kmem_cache_create("pblk_r_rq", pblk_r_rq_size,
+ pblk_g_rq_cache = kmem_cache_create("pblk_g_rq", pblk_g_rq_size,
0, 0, NULL);
- if (!pblk_r_rq_cache) {
+ if (!pblk_g_rq_cache) {
kmem_cache_destroy(pblk_blk_ws_cache);
kmem_cache_destroy(pblk_rec_cache);
up_write(&pblk_lock);
@@ -213,7 +214,7 @@ static int pblk_init_global_caches(struct pblk *pblk)
if (!pblk_w_rq_cache) {
kmem_cache_destroy(pblk_blk_ws_cache);
kmem_cache_destroy(pblk_rec_cache);
- kmem_cache_destroy(pblk_r_rq_cache);
+ kmem_cache_destroy(pblk_g_rq_cache);
up_write(&pblk_lock);
return -ENOMEM;
}
@@ -225,7 +226,7 @@ static int pblk_init_global_caches(struct pblk *pblk)
if (!pblk_line_meta_cache) {
kmem_cache_destroy(pblk_blk_ws_cache);
kmem_cache_destroy(pblk_rec_cache);
- kmem_cache_destroy(pblk_r_rq_cache);
+ kmem_cache_destroy(pblk_g_rq_cache);
kmem_cache_destroy(pblk_w_rq_cache);
up_write(&pblk_lock);
return -ENOMEM;
@@ -239,27 +240,10 @@ static int pblk_core_init(struct pblk *pblk)
{
struct nvm_tgt_dev *dev = pblk->dev;
struct nvm_geo *geo = &dev->geo;
- int max_write_ppas;
- int mod;
- pblk->min_write_pgs = geo->sec_per_pl * (geo->sec_size / PAGE_SIZE);
- max_write_ppas = pblk->min_write_pgs * geo->nr_luns;
- pblk->max_write_pgs = (max_write_ppas < nvm_max_phys_sects(dev)) ?
- max_write_ppas : nvm_max_phys_sects(dev);
pblk->pgs_in_buffer = NVM_MEM_PAGE_WRITE * geo->sec_per_pg *
geo->nr_planes * geo->nr_luns;
- if (pblk->max_write_pgs > PBLK_MAX_REQ_ADDRS) {
- pr_err("pblk: cannot support device max_phys_sect\n");
- return -EINVAL;
- }
-
- div_u64_rem(geo->sec_per_blk, pblk->min_write_pgs, &mod);
- if (mod) {
- pr_err("pblk: bad configuration of sectors/pages\n");
- return -EINVAL;
- }
-
if (pblk_init_global_caches(pblk))
return -ENOMEM;
@@ -267,7 +251,7 @@ static int pblk_core_init(struct pblk *pblk)
if (!pblk->page_pool)
return -ENOMEM;
- pblk->line_ws_pool = mempool_create_slab_pool(geo->nr_luns,
+ pblk->line_ws_pool = mempool_create_slab_pool(PBLK_WS_POOL_SIZE,
pblk_blk_ws_cache);
if (!pblk->line_ws_pool)
goto free_page_pool;
@@ -276,41 +260,51 @@ static int pblk_core_init(struct pblk *pblk)
if (!pblk->rec_pool)
goto free_blk_ws_pool;
- pblk->r_rq_pool = mempool_create_slab_pool(64, pblk_r_rq_cache);
- if (!pblk->r_rq_pool)
+ pblk->g_rq_pool = mempool_create_slab_pool(PBLK_READ_REQ_POOL_SIZE,
+ pblk_g_rq_cache);
+ if (!pblk->g_rq_pool)
goto free_rec_pool;
- pblk->w_rq_pool = mempool_create_slab_pool(64, pblk_w_rq_cache);
+ pblk->w_rq_pool = mempool_create_slab_pool(geo->nr_luns * 2,
+ pblk_w_rq_cache);
if (!pblk->w_rq_pool)
- goto free_r_rq_pool;
+ goto free_g_rq_pool;
pblk->line_meta_pool =
- mempool_create_slab_pool(16, pblk_line_meta_cache);
+ mempool_create_slab_pool(PBLK_META_POOL_SIZE,
+ pblk_line_meta_cache);
if (!pblk->line_meta_pool)
goto free_w_rq_pool;
- pblk->kw_wq = alloc_workqueue("pblk-aux-wq",
- WQ_MEM_RECLAIM | WQ_UNBOUND, 1);
- if (!pblk->kw_wq)
+ pblk->close_wq = alloc_workqueue("pblk-close-wq",
+ WQ_MEM_RECLAIM | WQ_UNBOUND, PBLK_NR_CLOSE_JOBS);
+ if (!pblk->close_wq)
goto free_line_meta_pool;
+ pblk->bb_wq = alloc_workqueue("pblk-bb-wq",
+ WQ_MEM_RECLAIM | WQ_UNBOUND, 0);
+ if (!pblk->bb_wq)
+ goto free_close_wq;
+
if (pblk_set_ppaf(pblk))
- goto free_kw_wq;
+ goto free_bb_wq;
if (pblk_rwb_init(pblk))
- goto free_kw_wq;
+ goto free_bb_wq;
INIT_LIST_HEAD(&pblk->compl_list);
return 0;
-free_kw_wq:
- destroy_workqueue(pblk->kw_wq);
+free_bb_wq:
+ destroy_workqueue(pblk->bb_wq);
+free_close_wq:
+ destroy_workqueue(pblk->close_wq);
free_line_meta_pool:
mempool_destroy(pblk->line_meta_pool);
free_w_rq_pool:
mempool_destroy(pblk->w_rq_pool);
-free_r_rq_pool:
- mempool_destroy(pblk->r_rq_pool);
+free_g_rq_pool:
+ mempool_destroy(pblk->g_rq_pool);
free_rec_pool:
mempool_destroy(pblk->rec_pool);
free_blk_ws_pool:
@@ -322,19 +316,22 @@ free_page_pool:
static void pblk_core_free(struct pblk *pblk)
{
- if (pblk->kw_wq)
- destroy_workqueue(pblk->kw_wq);
+ if (pblk->close_wq)
+ destroy_workqueue(pblk->close_wq);
+
+ if (pblk->bb_wq)
+ destroy_workqueue(pblk->bb_wq);
mempool_destroy(pblk->page_pool);
mempool_destroy(pblk->line_ws_pool);
mempool_destroy(pblk->rec_pool);
- mempool_destroy(pblk->r_rq_pool);
+ mempool_destroy(pblk->g_rq_pool);
mempool_destroy(pblk->w_rq_pool);
mempool_destroy(pblk->line_meta_pool);
kmem_cache_destroy(pblk_blk_ws_cache);
kmem_cache_destroy(pblk_rec_cache);
- kmem_cache_destroy(pblk_r_rq_cache);
+ kmem_cache_destroy(pblk_g_rq_cache);
kmem_cache_destroy(pblk_w_rq_cache);
kmem_cache_destroy(pblk_line_meta_cache);
}
@@ -344,6 +341,12 @@ static void pblk_luns_free(struct pblk *pblk)
kfree(pblk->luns);
}
+static void pblk_free_line_bitmaps(struct pblk_line *line)
+{
+ kfree(line->blk_bitmap);
+ kfree(line->erase_bitmap);
+}
+
static void pblk_lines_free(struct pblk *pblk)
{
struct pblk_line_mgmt *l_mg = &pblk->l_mg;
@@ -355,8 +358,7 @@ static void pblk_lines_free(struct pblk *pblk)
line = &pblk->lines[i];
pblk_line_free(pblk, line);
- kfree(line->blk_bitmap);
- kfree(line->erase_bitmap);
+ pblk_free_line_bitmaps(line);
}
spin_unlock(&l_mg->free_lock);
}
@@ -368,11 +370,15 @@ static void pblk_line_meta_free(struct pblk *pblk)
kfree(l_mg->bb_template);
kfree(l_mg->bb_aux);
+ kfree(l_mg->vsc_list);
+ spin_lock(&l_mg->free_lock);
for (i = 0; i < PBLK_DATA_LINES; i++) {
- pblk_mfree(l_mg->sline_meta[i].meta, l_mg->smeta_alloc_type);
- pblk_mfree(l_mg->eline_meta[i].meta, l_mg->emeta_alloc_type);
+ kfree(l_mg->sline_meta[i]);
+ pblk_mfree(l_mg->eline_meta[i]->buf, l_mg->emeta_alloc_type);
+ kfree(l_mg->eline_meta[i]);
}
+ spin_unlock(&l_mg->free_lock);
kfree(pblk->lines);
}
@@ -411,13 +417,31 @@ out:
return ret;
}
-static int pblk_bb_line(struct pblk *pblk, struct pblk_line *line)
+static int pblk_bb_line(struct pblk *pblk, struct pblk_line *line,
+ int blk_per_line)
{
- struct pblk_line_meta *lm = &pblk->lm;
+ struct nvm_tgt_dev *dev = pblk->dev;
+ struct nvm_geo *geo = &dev->geo;
struct pblk_lun *rlun;
int bb_cnt = 0;
int i;
+ for (i = 0; i < blk_per_line; i++) {
+ rlun = &pblk->luns[i];
+ if (rlun->bb_list[line->id] == NVM_BLK_T_FREE)
+ continue;
+
+ set_bit(pblk_ppa_to_pos(geo, rlun->bppa), line->blk_bitmap);
+ bb_cnt++;
+ }
+
+ return bb_cnt;
+}
+
+static int pblk_alloc_line_bitmaps(struct pblk *pblk, struct pblk_line *line)
+{
+ struct pblk_line_meta *lm = &pblk->lm;
+
line->blk_bitmap = kzalloc(lm->blk_bitmap_len, GFP_KERNEL);
if (!line->blk_bitmap)
return -ENOMEM;
@@ -428,16 +452,7 @@ static int pblk_bb_line(struct pblk *pblk, struct pblk_line *line)
return -ENOMEM;
}
- for (i = 0; i < lm->blk_per_line; i++) {
- rlun = &pblk->luns[i];
- if (rlun->bb_list[line->id] == NVM_BLK_T_FREE)
- continue;
-
- set_bit(i, line->blk_bitmap);
- bb_cnt++;
- }
-
- return bb_cnt;
+ return 0;
}
static int pblk_luns_init(struct pblk *pblk, struct ppa_addr *luns)
@@ -505,12 +520,32 @@ static int pblk_lines_configure(struct pblk *pblk, int flags)
}
/* See comment over struct line_emeta definition */
-static unsigned int calc_emeta_len(struct pblk *pblk, struct pblk_line_meta *lm)
+static unsigned int calc_emeta_len(struct pblk *pblk)
{
- return (sizeof(struct line_emeta) +
- ((lm->sec_per_line - lm->emeta_sec) * sizeof(u64)) +
- (pblk->l_mg.nr_lines * sizeof(u32)) +
- lm->blk_bitmap_len);
+ struct pblk_line_meta *lm = &pblk->lm;
+ struct pblk_line_mgmt *l_mg = &pblk->l_mg;
+ struct nvm_tgt_dev *dev = pblk->dev;
+ struct nvm_geo *geo = &dev->geo;
+
+ /* Round to sector size so that lba_list starts on its own sector */
+ lm->emeta_sec[1] = DIV_ROUND_UP(
+ sizeof(struct line_emeta) + lm->blk_bitmap_len,
+ geo->sec_size);
+ lm->emeta_len[1] = lm->emeta_sec[1] * geo->sec_size;
+
+ /* Round to sector size so that vsc_list starts on its own sector */
+ lm->dsec_per_line = lm->sec_per_line - lm->emeta_sec[0];
+ lm->emeta_sec[2] = DIV_ROUND_UP(lm->dsec_per_line * sizeof(u64),
+ geo->sec_size);
+ lm->emeta_len[2] = lm->emeta_sec[2] * geo->sec_size;
+
+ lm->emeta_sec[3] = DIV_ROUND_UP(l_mg->nr_lines * sizeof(u32),
+ geo->sec_size);
+ lm->emeta_len[3] = lm->emeta_sec[3] * geo->sec_size;
+
+ lm->vsc_list_len = l_mg->nr_lines * sizeof(u32);
+
+ return (lm->emeta_len[1] + lm->emeta_len[2] + lm->emeta_len[3]);
}
static void pblk_set_provision(struct pblk *pblk, long nr_free_blks)
@@ -534,6 +569,78 @@ static void pblk_set_provision(struct pblk *pblk, long nr_free_blks)
atomic_set(&pblk->rl.free_blocks, nr_free_blks);
}
+static int pblk_lines_alloc_metadata(struct pblk *pblk)
+{
+ struct pblk_line_mgmt *l_mg = &pblk->l_mg;
+ struct pblk_line_meta *lm = &pblk->lm;
+ int i;
+
+ /* smeta is always small enough to fit on a kmalloc memory allocation,
+ * emeta depends on the number of LUNs allocated to the pblk instance
+ */
+ for (i = 0; i < PBLK_DATA_LINES; i++) {
+ l_mg->sline_meta[i] = kmalloc(lm->smeta_len, GFP_KERNEL);
+ if (!l_mg->sline_meta[i])
+ goto fail_free_smeta;
+ }
+
+ /* emeta allocates three different buffers for managing metadata with
+ * in-memory and in-media layouts
+ */
+ for (i = 0; i < PBLK_DATA_LINES; i++) {
+ struct pblk_emeta *emeta;
+
+ emeta = kmalloc(sizeof(struct pblk_emeta), GFP_KERNEL);
+ if (!emeta)
+ goto fail_free_emeta;
+
+ if (lm->emeta_len[0] > KMALLOC_MAX_CACHE_SIZE) {
+ l_mg->emeta_alloc_type = PBLK_VMALLOC_META;
+
+ emeta->buf = vmalloc(lm->emeta_len[0]);
+ if (!emeta->buf) {
+ kfree(emeta);
+ goto fail_free_emeta;
+ }
+
+ emeta->nr_entries = lm->emeta_sec[0];
+ l_mg->eline_meta[i] = emeta;
+ } else {
+ l_mg->emeta_alloc_type = PBLK_KMALLOC_META;
+
+ emeta->buf = kmalloc(lm->emeta_len[0], GFP_KERNEL);
+ if (!emeta->buf) {
+ kfree(emeta);
+ goto fail_free_emeta;
+ }
+
+ emeta->nr_entries = lm->emeta_sec[0];
+ l_mg->eline_meta[i] = emeta;
+ }
+ }
+
+ l_mg->vsc_list = kcalloc(l_mg->nr_lines, sizeof(__le32), GFP_KERNEL);
+ if (!l_mg->vsc_list)
+ goto fail_free_emeta;
+
+ for (i = 0; i < l_mg->nr_lines; i++)
+ l_mg->vsc_list[i] = cpu_to_le32(EMPTY_ENTRY);
+
+ return 0;
+
+fail_free_emeta:
+ while (--i >= 0) {
+ vfree(l_mg->eline_meta[i]->buf);
+ kfree(l_mg->eline_meta[i]);
+ }
+
+fail_free_smeta:
+ for (i = 0; i < PBLK_DATA_LINES; i++)
+ kfree(l_mg->sline_meta[i]);
+
+ return -ENOMEM;
+}
+
static int pblk_lines_init(struct pblk *pblk)
{
struct nvm_tgt_dev *dev = pblk->dev;
@@ -542,10 +649,32 @@ static int pblk_lines_init(struct pblk *pblk)
struct pblk_line_meta *lm = &pblk->lm;
struct pblk_line *line;
unsigned int smeta_len, emeta_len;
- long nr_bad_blks, nr_meta_blks, nr_free_blks;
- int bb_distance;
- int i;
- int ret;
+ long nr_bad_blks, nr_free_blks;
+ int bb_distance, max_write_ppas, mod;
+ int i, ret;
+
+ pblk->min_write_pgs = geo->sec_per_pl * (geo->sec_size / PAGE_SIZE);
+ max_write_ppas = pblk->min_write_pgs * geo->nr_luns;
+ pblk->max_write_pgs = (max_write_ppas < nvm_max_phys_sects(dev)) ?
+ max_write_ppas : nvm_max_phys_sects(dev);
+ pblk_set_sec_per_write(pblk, pblk->min_write_pgs);
+
+ if (pblk->max_write_pgs > PBLK_MAX_REQ_ADDRS) {
+ pr_err("pblk: cannot support device max_phys_sect\n");
+ return -EINVAL;
+ }
+
+ div_u64_rem(geo->sec_per_blk, pblk->min_write_pgs, &mod);
+ if (mod) {
+ pr_err("pblk: bad configuration of sectors/pages\n");
+ return -EINVAL;
+ }
+
+ l_mg->nr_lines = geo->blks_per_lun;
+ l_mg->log_line = l_mg->data_line = NULL;
+ l_mg->l_seq_nr = l_mg->d_seq_nr = 0;
+ l_mg->nr_free_lines = 0;
+ bitmap_zero(&l_mg->meta_bitmap, PBLK_DATA_LINES);
lm->sec_per_line = geo->sec_per_blk * geo->nr_luns;
lm->blk_per_line = geo->nr_luns;
@@ -554,20 +683,17 @@ static int pblk_lines_init(struct pblk *pblk)
lm->lun_bitmap_len = BITS_TO_LONGS(geo->nr_luns) * sizeof(long);
lm->high_thrs = lm->sec_per_line / 2;
lm->mid_thrs = lm->sec_per_line / 4;
+ lm->meta_distance = (geo->nr_luns / 2) * pblk->min_write_pgs;
/* Calculate necessary pages for smeta. See comment over struct
* line_smeta definition
*/
- lm->smeta_len = sizeof(struct line_smeta) +
- PBLK_LINE_NR_LUN_BITMAP * lm->lun_bitmap_len;
-
i = 1;
add_smeta_page:
lm->smeta_sec = i * geo->sec_per_pl;
lm->smeta_len = lm->smeta_sec * geo->sec_size;
- smeta_len = sizeof(struct line_smeta) +
- PBLK_LINE_NR_LUN_BITMAP * lm->lun_bitmap_len;
+ smeta_len = sizeof(struct line_smeta) + lm->lun_bitmap_len;
if (smeta_len > lm->smeta_len) {
i++;
goto add_smeta_page;
@@ -578,66 +704,28 @@ add_smeta_page:
*/
i = 1;
add_emeta_page:
- lm->emeta_sec = i * geo->sec_per_pl;
- lm->emeta_len = lm->emeta_sec * geo->sec_size;
+ lm->emeta_sec[0] = i * geo->sec_per_pl;
+ lm->emeta_len[0] = lm->emeta_sec[0] * geo->sec_size;
- emeta_len = calc_emeta_len(pblk, lm);
- if (emeta_len > lm->emeta_len) {
+ emeta_len = calc_emeta_len(pblk);
+ if (emeta_len > lm->emeta_len[0]) {
i++;
goto add_emeta_page;
}
- lm->emeta_bb = geo->nr_luns - i;
-
- nr_meta_blks = (lm->smeta_sec + lm->emeta_sec +
- (geo->sec_per_blk / 2)) / geo->sec_per_blk;
- lm->min_blk_line = nr_meta_blks + 1;
-
- l_mg->nr_lines = geo->blks_per_lun;
- l_mg->log_line = l_mg->data_line = NULL;
- l_mg->l_seq_nr = l_mg->d_seq_nr = 0;
- l_mg->nr_free_lines = 0;
- bitmap_zero(&l_mg->meta_bitmap, PBLK_DATA_LINES);
- /* smeta is always small enough to fit on a kmalloc memory allocation,
- * emeta depends on the number of LUNs allocated to the pblk instance
- */
- l_mg->smeta_alloc_type = PBLK_KMALLOC_META;
- for (i = 0; i < PBLK_DATA_LINES; i++) {
- l_mg->sline_meta[i].meta = kmalloc(lm->smeta_len, GFP_KERNEL);
- if (!l_mg->sline_meta[i].meta)
- while (--i >= 0) {
- kfree(l_mg->sline_meta[i].meta);
- ret = -ENOMEM;
- goto fail;
- }
+ lm->emeta_bb = geo->nr_luns - i;
+ lm->min_blk_line = 1 + DIV_ROUND_UP(lm->smeta_sec + lm->emeta_sec[0],
+ geo->sec_per_blk);
+ if (lm->min_blk_line > lm->blk_per_line) {
+ pr_err("pblk: config. not supported. Min. LUN in line:%d\n",
+ lm->blk_per_line);
+ ret = -EINVAL;
+ goto fail;
}
- if (lm->emeta_len > KMALLOC_MAX_CACHE_SIZE) {
- l_mg->emeta_alloc_type = PBLK_VMALLOC_META;
-
- for (i = 0; i < PBLK_DATA_LINES; i++) {
- l_mg->eline_meta[i].meta = vmalloc(lm->emeta_len);
- if (!l_mg->eline_meta[i].meta)
- while (--i >= 0) {
- vfree(l_mg->eline_meta[i].meta);
- ret = -ENOMEM;
- goto fail;
- }
- }
- } else {
- l_mg->emeta_alloc_type = PBLK_KMALLOC_META;
-
- for (i = 0; i < PBLK_DATA_LINES; i++) {
- l_mg->eline_meta[i].meta =
- kmalloc(lm->emeta_len, GFP_KERNEL);
- if (!l_mg->eline_meta[i].meta)
- while (--i >= 0) {
- kfree(l_mg->eline_meta[i].meta);
- ret = -ENOMEM;
- goto fail;
- }
- }
- }
+ ret = pblk_lines_alloc_metadata(pblk);
+ if (ret)
+ goto fail;
l_mg->bb_template = kzalloc(lm->sec_bitmap_len, GFP_KERNEL);
if (!l_mg->bb_template) {
@@ -664,11 +752,14 @@ add_emeta_page:
INIT_LIST_HEAD(&l_mg->gc_low_list);
INIT_LIST_HEAD(&l_mg->gc_empty_list);
+ INIT_LIST_HEAD(&l_mg->emeta_list);
+
l_mg->gc_lists[0] = &l_mg->gc_high_list;
l_mg->gc_lists[1] = &l_mg->gc_mid_list;
l_mg->gc_lists[2] = &l_mg->gc_low_list;
spin_lock_init(&l_mg->free_lock);
+ spin_lock_init(&l_mg->close_lock);
spin_lock_init(&l_mg->gc_lock);
pblk->lines = kcalloc(l_mg->nr_lines, sizeof(struct pblk_line),
@@ -689,10 +780,16 @@ add_emeta_page:
line->type = PBLK_LINETYPE_FREE;
line->state = PBLK_LINESTATE_FREE;
line->gc_group = PBLK_LINEGC_NONE;
+ line->vsc = &l_mg->vsc_list[i];
spin_lock_init(&line->lock);
- nr_bad_blks = pblk_bb_line(pblk, line);
+ ret = pblk_alloc_line_bitmaps(pblk, line);
+ if (ret)
+ goto fail_free_lines;
+
+ nr_bad_blks = pblk_bb_line(pblk, line, lm->blk_per_line);
if (nr_bad_blks < 0 || nr_bad_blks > lm->blk_per_line) {
+ pblk_free_line_bitmaps(line);
ret = -EINVAL;
goto fail_free_lines;
}
@@ -713,24 +810,20 @@ add_emeta_page:
pblk_set_provision(pblk, nr_free_blks);
- sema_init(&pblk->erase_sem, 1);
-
/* Cleanup per-LUN bad block lists - managed within lines on run-time */
for (i = 0; i < geo->nr_luns; i++)
kfree(pblk->luns[i].bb_list);
return 0;
fail_free_lines:
- kfree(pblk->lines);
+ while (--i >= 0)
+ pblk_free_line_bitmaps(&pblk->lines[i]);
fail_free_bb_aux:
kfree(l_mg->bb_aux);
fail_free_bb_template:
kfree(l_mg->bb_template);
fail_free_meta:
- for (i = 0; i < PBLK_DATA_LINES; i++) {
- pblk_mfree(l_mg->sline_meta[i].meta, l_mg->smeta_alloc_type);
- pblk_mfree(l_mg->eline_meta[i].meta, l_mg->emeta_alloc_type);
- }
+ pblk_line_meta_free(pblk);
fail:
for (i = 0; i < geo->nr_luns; i++)
kfree(pblk->luns[i].bb_list);
@@ -754,6 +847,15 @@ static int pblk_writer_init(struct pblk *pblk)
static void pblk_writer_stop(struct pblk *pblk)
{
+ /* The pipeline must be stopped and the write buffer emptied before the
+ * write thread is stopped
+ */
+ WARN(pblk_rb_read_count(&pblk->rwb),
+ "Stopping not fully persisted write buffer\n");
+
+ WARN(pblk_rb_sync_count(&pblk->rwb),
+ "Stopping not fully synced write buffer\n");
+
if (pblk->writer_ts)
kthread_stop(pblk->writer_ts);
del_timer(&pblk->wtimer);
@@ -772,10 +874,9 @@ static void pblk_free(struct pblk *pblk)
static void pblk_tear_down(struct pblk *pblk)
{
- pblk_flush_writer(pblk);
+ pblk_pipeline_stop(pblk);
pblk_writer_stop(pblk);
pblk_rb_sync_l2p(&pblk->rwb);
- pblk_recov_pad(pblk);
pblk_rwb_free(pblk);
pblk_rl_free(&pblk->rl);
@@ -821,6 +922,7 @@ static void *pblk_init(struct nvm_tgt_dev *dev, struct gendisk *tdisk,
pblk->dev = dev;
pblk->disk = tdisk;
+ pblk->state = PBLK_STATE_RUNNING;
spin_lock_init(&pblk->trans_lock);
spin_lock_init(&pblk->lock);
@@ -836,8 +938,8 @@ static void *pblk_init(struct nvm_tgt_dev *dev, struct gendisk *tdisk,
atomic_long_set(&pblk->req_writes, 0);
atomic_long_set(&pblk->sub_writes, 0);
atomic_long_set(&pblk->sync_writes, 0);
- atomic_long_set(&pblk->compl_writes, 0);
atomic_long_set(&pblk->inflight_reads, 0);
+ atomic_long_set(&pblk->cache_reads, 0);
atomic_long_set(&pblk->sync_reads, 0);
atomic_long_set(&pblk->recov_writes, 0);
atomic_long_set(&pblk->recov_writes, 0);
@@ -946,11 +1048,20 @@ static struct nvm_tgt_type tt_pblk = {
static int __init pblk_module_init(void)
{
- return nvm_register_tgt_type(&tt_pblk);
+ int ret;
+
+ pblk_bio_set = bioset_create(BIO_POOL_SIZE, 0, 0);
+ if (!pblk_bio_set)
+ return -ENOMEM;
+ ret = nvm_register_tgt_type(&tt_pblk);
+ if (ret)
+ bioset_free(pblk_bio_set);
+ return ret;
}
static void pblk_module_exit(void)
{
+ bioset_free(pblk_bio_set);
nvm_unregister_tgt_type(&tt_pblk);
}
diff --git a/drivers/lightnvm/pblk-map.c b/drivers/lightnvm/pblk-map.c
index 17c16955284d..fddb924f6dde 100644
--- a/drivers/lightnvm/pblk-map.c
+++ b/drivers/lightnvm/pblk-map.c
@@ -25,9 +25,9 @@ static void pblk_map_page_data(struct pblk *pblk, unsigned int sentry,
unsigned int valid_secs)
{
struct pblk_line *line = pblk_line_get_data(pblk);
- struct line_emeta *emeta = line->emeta;
+ struct pblk_emeta *emeta = line->emeta;
struct pblk_w_ctx *w_ctx;
- __le64 *lba_list = pblk_line_emeta_to_lbas(emeta);
+ __le64 *lba_list = emeta_to_lbas(pblk, emeta->buf);
u64 paddr;
int nr_secs = pblk->min_write_pgs;
int i;
@@ -51,18 +51,20 @@ static void pblk_map_page_data(struct pblk *pblk, unsigned int sentry,
w_ctx->ppa = ppa_list[i];
meta_list[i].lba = cpu_to_le64(w_ctx->lba);
lba_list[paddr] = cpu_to_le64(w_ctx->lba);
- le64_add_cpu(&line->emeta->nr_valid_lbas, 1);
+ line->nr_valid_lbas++;
} else {
- meta_list[i].lba = cpu_to_le64(ADDR_EMPTY);
- lba_list[paddr] = cpu_to_le64(ADDR_EMPTY);
- pblk_map_pad_invalidate(pblk, line, paddr);
+ __le64 addr_empty = cpu_to_le64(ADDR_EMPTY);
+
+ lba_list[paddr] = meta_list[i].lba = addr_empty;
+ __pblk_map_invalidate(pblk, line, paddr);
}
}
if (pblk_line_is_full(line)) {
- line = pblk_line_replace_data(pblk);
- if (!line)
- return;
+ struct pblk_line *prev_line = line;
+
+ pblk_line_replace_data(pblk);
+ pblk_line_close_meta(pblk, prev_line);
}
pblk_down_rq(pblk, ppa_list, nr_secs, lun_bitmap);
@@ -91,8 +93,9 @@ void pblk_map_erase_rq(struct pblk *pblk, struct nvm_rq *rqd,
{
struct nvm_tgt_dev *dev = pblk->dev;
struct nvm_geo *geo = &dev->geo;
- struct pblk_line *e_line = pblk_line_get_data_next(pblk);
+ struct pblk_line_meta *lm = &pblk->lm;
struct pblk_sec_meta *meta_list = rqd->meta_list;
+ struct pblk_line *e_line, *d_line;
unsigned int map_secs;
int min = pblk->min_write_pgs;
int i, erase_lun;
@@ -102,35 +105,63 @@ void pblk_map_erase_rq(struct pblk *pblk, struct nvm_rq *rqd,
pblk_map_page_data(pblk, sentry + i, &rqd->ppa_list[i],
lun_bitmap, &meta_list[i], map_secs);
- erase_lun = rqd->ppa_list[i].g.lun * geo->nr_chnls +
- rqd->ppa_list[i].g.ch;
+ erase_lun = pblk_ppa_to_pos(geo, rqd->ppa_list[i]);
- if (!test_bit(erase_lun, e_line->erase_bitmap)) {
- if (down_trylock(&pblk->erase_sem))
- continue;
+ /* line can change after page map. We might also be writing the
+ * last line.
+ */
+ e_line = pblk_line_get_erase(pblk);
+ if (!e_line)
+ return pblk_map_rq(pblk, rqd, sentry, lun_bitmap,
+ valid_secs, i + min);
+ spin_lock(&e_line->lock);
+ if (!test_bit(erase_lun, e_line->erase_bitmap)) {
set_bit(erase_lun, e_line->erase_bitmap);
atomic_dec(&e_line->left_eblks);
+
*erase_ppa = rqd->ppa_list[i];
erase_ppa->g.blk = e_line->id;
+ spin_unlock(&e_line->lock);
+
/* Avoid evaluating e_line->left_eblks */
return pblk_map_rq(pblk, rqd, sentry, lun_bitmap,
valid_secs, i + min);
}
+ spin_unlock(&e_line->lock);
}
- /* Erase blocks that are bad in this line but might not be in next */
- if (unlikely(ppa_empty(*erase_ppa))) {
- struct pblk_line_meta *lm = &pblk->lm;
+ d_line = pblk_line_get_data(pblk);
+
+ /* line can change after page map. We might also be writing the
+ * last line.
+ */
+ e_line = pblk_line_get_erase(pblk);
+ if (!e_line)
+ return;
- i = find_first_zero_bit(e_line->erase_bitmap, lm->blk_per_line);
- if (i == lm->blk_per_line)
+ /* Erase blocks that are bad in this line but might not be in next */
+ if (unlikely(ppa_empty(*erase_ppa)) &&
+ bitmap_weight(d_line->blk_bitmap, lm->blk_per_line)) {
+ int bit = -1;
+
+retry:
+ bit = find_next_bit(d_line->blk_bitmap,
+ lm->blk_per_line, bit + 1);
+ if (bit >= lm->blk_per_line)
return;
- set_bit(i, e_line->erase_bitmap);
+ spin_lock(&e_line->lock);
+ if (test_bit(bit, e_line->erase_bitmap)) {
+ spin_unlock(&e_line->lock);
+ goto retry;
+ }
+ spin_unlock(&e_line->lock);
+
+ set_bit(bit, e_line->erase_bitmap);
atomic_dec(&e_line->left_eblks);
- *erase_ppa = pblk->luns[i].bppa; /* set ch and lun */
+ *erase_ppa = pblk->luns[bit].bppa; /* set ch and lun */
erase_ppa->g.blk = e_line->id;
}
}
diff --git a/drivers/lightnvm/pblk-rb.c b/drivers/lightnvm/pblk-rb.c
index 045384ddc1f9..5ecc154f6831 100644
--- a/drivers/lightnvm/pblk-rb.c
+++ b/drivers/lightnvm/pblk-rb.c
@@ -150,6 +150,7 @@ try:
/* Release flags on context. Protect from writes and reads */
smp_store_release(&w_ctx->flags, PBLK_WRITABLE_ENTRY);
pblk_ppa_set_empty(&w_ctx->ppa);
+ w_ctx->lba = ADDR_EMPTY;
}
#define pblk_rb_ring_count(head, tail, size) CIRC_CNT(head, tail, size)
@@ -180,6 +181,14 @@ unsigned int pblk_rb_read_count(struct pblk_rb *rb)
return pblk_rb_ring_count(mem, subm, rb->nr_entries);
}
+unsigned int pblk_rb_sync_count(struct pblk_rb *rb)
+{
+ unsigned int mem = READ_ONCE(rb->mem);
+ unsigned int sync = READ_ONCE(rb->sync);
+
+ return pblk_rb_ring_count(mem, sync, rb->nr_entries);
+}
+
unsigned int pblk_rb_read_commit(struct pblk_rb *rb, unsigned int nr_entries)
{
unsigned int subm;
@@ -199,12 +208,22 @@ static int __pblk_rb_update_l2p(struct pblk_rb *rb, unsigned int *l2p_upd,
struct pblk_line *line;
struct pblk_rb_entry *entry;
struct pblk_w_ctx *w_ctx;
+ unsigned int user_io = 0, gc_io = 0;
unsigned int i;
+ int flags;
for (i = 0; i < to_update; i++) {
entry = &rb->entries[*l2p_upd];
w_ctx = &entry->w_ctx;
+ flags = READ_ONCE(entry->w_ctx.flags);
+ if (flags & PBLK_IOTYPE_USER)
+ user_io++;
+ else if (flags & PBLK_IOTYPE_GC)
+ gc_io++;
+ else
+ WARN(1, "pblk: unknown IO type\n");
+
pblk_update_map_dev(pblk, w_ctx->lba, w_ctx->ppa,
entry->cacheline);
@@ -214,6 +233,8 @@ static int __pblk_rb_update_l2p(struct pblk_rb *rb, unsigned int *l2p_upd,
*l2p_upd = (*l2p_upd + 1) & (rb->nr_entries - 1);
}
+ pblk_rl_out(&pblk->rl, user_io, gc_io);
+
return 0;
}
@@ -357,6 +378,9 @@ static int pblk_rb_sync_point_set(struct pblk_rb *rb, struct bio *bio,
/* Protect syncs */
smp_store_release(&rb->sync_point, sync_point);
+ if (!bio)
+ return 0;
+
spin_lock_irq(&rb->s_lock);
bio_list_add(&entry->w_ctx.bios, bio);
spin_unlock_irq(&rb->s_lock);
@@ -395,6 +419,17 @@ static int pblk_rb_may_write(struct pblk_rb *rb, unsigned int nr_entries,
return 1;
}
+void pblk_rb_flush(struct pblk_rb *rb)
+{
+ struct pblk *pblk = container_of(rb, struct pblk, rwb);
+ unsigned int mem = READ_ONCE(rb->mem);
+
+ if (pblk_rb_sync_point_set(rb, NULL, mem))
+ return;
+
+ pblk_write_should_kick(pblk);
+}
+
static int pblk_rb_may_write_flush(struct pblk_rb *rb, unsigned int nr_entries,
unsigned int *pos, struct bio *bio,
int *io_ret)
@@ -431,15 +466,16 @@ int pblk_rb_may_write_user(struct pblk_rb *rb, struct bio *bio,
unsigned int nr_entries, unsigned int *pos)
{
struct pblk *pblk = container_of(rb, struct pblk, rwb);
- int flush_done;
+ int io_ret;
spin_lock(&rb->w_lock);
- if (!pblk_rl_user_may_insert(&pblk->rl, nr_entries)) {
+ io_ret = pblk_rl_user_may_insert(&pblk->rl, nr_entries);
+ if (io_ret) {
spin_unlock(&rb->w_lock);
- return NVM_IO_REQUEUE;
+ return io_ret;
}
- if (!pblk_rb_may_write_flush(rb, nr_entries, pos, bio, &flush_done)) {
+ if (!pblk_rb_may_write_flush(rb, nr_entries, pos, bio, &io_ret)) {
spin_unlock(&rb->w_lock);
return NVM_IO_REQUEUE;
}
@@ -447,7 +483,7 @@ int pblk_rb_may_write_user(struct pblk_rb *rb, struct bio *bio,
pblk_rl_user_in(&pblk->rl, nr_entries);
spin_unlock(&rb->w_lock);
- return flush_done;
+ return io_ret;
}
/*
@@ -521,20 +557,18 @@ out:
* This function is used by the write thread to form the write bio that will
* persist data on the write buffer to the media.
*/
-unsigned int pblk_rb_read_to_bio(struct pblk_rb *rb, struct bio *bio,
- struct pblk_c_ctx *c_ctx,
- unsigned int pos,
- unsigned int nr_entries,
- unsigned int count)
+unsigned int pblk_rb_read_to_bio(struct pblk_rb *rb, struct nvm_rq *rqd,
+ struct bio *bio, unsigned int pos,
+ unsigned int nr_entries, unsigned int count)
{
struct pblk *pblk = container_of(rb, struct pblk, rwb);
+ struct request_queue *q = pblk->dev->q;
+ struct pblk_c_ctx *c_ctx = nvm_rq_to_pdu(rqd);
struct pblk_rb_entry *entry;
struct page *page;
- unsigned int pad = 0, read = 0, to_read = nr_entries;
- unsigned int user_io = 0, gc_io = 0;
+ unsigned int pad = 0, to_read = nr_entries;
unsigned int i;
int flags;
- int ret;
if (count < nr_entries) {
pad = nr_entries - count;
@@ -553,15 +587,10 @@ unsigned int pblk_rb_read_to_bio(struct pblk_rb *rb, struct bio *bio,
*/
try:
flags = READ_ONCE(entry->w_ctx.flags);
- if (!(flags & PBLK_WRITTEN_DATA))
+ if (!(flags & PBLK_WRITTEN_DATA)) {
+ io_schedule();
goto try;
-
- if (flags & PBLK_IOTYPE_USER)
- user_io++;
- else if (flags & PBLK_IOTYPE_GC)
- gc_io++;
- else
- WARN(1, "pblk: unknown IO type\n");
+ }
page = virt_to_page(entry->data);
if (!page) {
@@ -570,17 +599,17 @@ try:
flags |= PBLK_SUBMITTED_ENTRY;
/* Release flags on context. Protect from writes */
smp_store_release(&entry->w_ctx.flags, flags);
- goto out;
+ return NVM_IO_ERR;
}
- ret = bio_add_page(bio, page, rb->seg_size, 0);
- if (ret != rb->seg_size) {
+ if (bio_add_pc_page(q, bio, page, rb->seg_size, 0) !=
+ rb->seg_size) {
pr_err("pblk: could not add page to write bio\n");
flags &= ~PBLK_WRITTEN_DATA;
flags |= PBLK_SUBMITTED_ENTRY;
/* Release flags on context. Protect from writes */
smp_store_release(&entry->w_ctx.flags, flags);
- goto out;
+ return NVM_IO_ERR;
}
if (flags & PBLK_FLUSH_ENTRY) {
@@ -607,14 +636,19 @@ try:
pos = (pos + 1) & (rb->nr_entries - 1);
}
- read = to_read;
- pblk_rl_out(&pblk->rl, user_io, gc_io);
+ if (pad) {
+ if (pblk_bio_add_pages(pblk, bio, GFP_KERNEL, pad)) {
+ pr_err("pblk: could not pad page in write bio\n");
+ return NVM_IO_ERR;
+ }
+ }
+
#ifdef CONFIG_NVM_DEBUG
atomic_long_add(pad, &((struct pblk *)
(container_of(rb, struct pblk, rwb)))->padded_writes);
#endif
-out:
- return read;
+
+ return NVM_IO_OK;
}
/*
@@ -623,15 +657,17 @@ out:
* be directed to disk.
*/
int pblk_rb_copy_to_bio(struct pblk_rb *rb, struct bio *bio, sector_t lba,
- u64 pos, int bio_iter)
+ struct ppa_addr ppa, int bio_iter)
{
+ struct pblk *pblk = container_of(rb, struct pblk, rwb);
struct pblk_rb_entry *entry;
struct pblk_w_ctx *w_ctx;
+ struct ppa_addr l2p_ppa;
+ u64 pos = pblk_addr_to_cacheline(ppa);
void *data;
int flags;
int ret = 1;
- spin_lock(&rb->w_lock);
#ifdef CONFIG_NVM_DEBUG
/* Caller must ensure that the access will not cause an overflow */
@@ -641,8 +677,14 @@ int pblk_rb_copy_to_bio(struct pblk_rb *rb, struct bio *bio, sector_t lba,
w_ctx = &entry->w_ctx;
flags = READ_ONCE(w_ctx->flags);
+ spin_lock(&rb->w_lock);
+ spin_lock(&pblk->trans_lock);
+ l2p_ppa = pblk_trans_map_get(pblk, lba);
+ spin_unlock(&pblk->trans_lock);
+
/* Check if the entry has been overwritten or is scheduled to be */
- if (w_ctx->lba != lba || flags & PBLK_WRITABLE_ENTRY) {
+ if (!pblk_ppa_comp(l2p_ppa, ppa) || w_ctx->lba != lba ||
+ flags & PBLK_WRITABLE_ENTRY) {
ret = 0;
goto out;
}
diff --git a/drivers/lightnvm/pblk-read.c b/drivers/lightnvm/pblk-read.c
index 4a12f14d78c6..4e5c48f3de62 100644
--- a/drivers/lightnvm/pblk-read.c
+++ b/drivers/lightnvm/pblk-read.c
@@ -34,8 +34,7 @@ static int pblk_read_from_cache(struct pblk *pblk, struct bio *bio,
BUG_ON(!pblk_addr_in_cache(ppa));
#endif
- return pblk_rb_copy_to_bio(&pblk->rwb, bio, lba,
- pblk_addr_to_cacheline(ppa), bio_iter);
+ return pblk_rb_copy_to_bio(&pblk->rwb, bio, lba, ppa, bio_iter);
}
static void pblk_read_ppalist_rq(struct pblk *pblk, struct nvm_rq *rqd,
@@ -76,6 +75,9 @@ retry:
}
WARN_ON(test_and_set_bit(i, read_bitmap));
advanced_bio = 1;
+#ifdef CONFIG_NVM_DEBUG
+ atomic_long_inc(&pblk->cache_reads);
+#endif
} else {
/* Read from media non-cached sectors */
rqd->ppa_list[j++] = p;
@@ -85,6 +87,11 @@ retry:
bio_advance(bio, PBLK_EXPOSED_PAGE_SIZE);
}
+ if (pblk_io_aligned(pblk, nr_secs))
+ rqd->flags = pblk_set_read_mode(pblk, PBLK_READ_SEQUENTIAL);
+ else
+ rqd->flags = pblk_set_read_mode(pblk, PBLK_READ_RANDOM);
+
#ifdef CONFIG_NVM_DEBUG
atomic_long_add(nr_secs, &pblk->inflight_reads);
#endif
@@ -94,8 +101,6 @@ static int pblk_submit_read_io(struct pblk *pblk, struct nvm_rq *rqd)
{
int err;
- rqd->flags = pblk_set_read_mode(pblk);
-
err = pblk_submit_io(pblk, rqd);
if (err)
return NVM_IO_ERR;
@@ -107,27 +112,27 @@ static void pblk_end_io_read(struct nvm_rq *rqd)
{
struct pblk *pblk = rqd->private;
struct nvm_tgt_dev *dev = pblk->dev;
- struct pblk_r_ctx *r_ctx = nvm_rq_to_pdu(rqd);
+ struct pblk_g_ctx *r_ctx = nvm_rq_to_pdu(rqd);
struct bio *bio = rqd->bio;
if (rqd->error)
pblk_log_read_err(pblk, rqd);
#ifdef CONFIG_NVM_DEBUG
else
- WARN_ONCE(bio->bi_error, "pblk: corrupted read error\n");
+ WARN_ONCE(bio->bi_status, "pblk: corrupted read error\n");
#endif
- if (rqd->nr_ppas > 1)
- nvm_dev_dma_free(dev->parent, rqd->ppa_list, rqd->dma_ppa_list);
+ nvm_dev_dma_free(dev->parent, rqd->meta_list, rqd->dma_meta_list);
bio_put(bio);
- if (r_ctx->orig_bio) {
+ if (r_ctx->private) {
+ struct bio *orig_bio = r_ctx->private;
+
#ifdef CONFIG_NVM_DEBUG
- WARN_ONCE(r_ctx->orig_bio->bi_error,
- "pblk: corrupted read bio\n");
+ WARN_ONCE(orig_bio->bi_status, "pblk: corrupted read bio\n");
#endif
- bio_endio(r_ctx->orig_bio);
- bio_put(r_ctx->orig_bio);
+ bio_endio(orig_bio);
+ bio_put(orig_bio);
}
#ifdef CONFIG_NVM_DEBUG
@@ -136,6 +141,7 @@ static void pblk_end_io_read(struct nvm_rq *rqd)
#endif
pblk_free_rqd(pblk, rqd, READ);
+ atomic_dec(&pblk->inflight_io);
}
static int pblk_fill_partial_read_bio(struct pblk *pblk, struct nvm_rq *rqd,
@@ -173,6 +179,7 @@ static int pblk_fill_partial_read_bio(struct pblk *pblk, struct nvm_rq *rqd,
rqd->bio = new_bio;
rqd->nr_ppas = nr_holes;
+ rqd->flags = pblk_set_read_mode(pblk, PBLK_READ_RANDOM);
rqd->end_io = NULL;
if (unlikely(nr_secs > 1 && nr_holes == 1)) {
@@ -280,9 +287,14 @@ retry:
goto retry;
}
WARN_ON(test_and_set_bit(0, read_bitmap));
+#ifdef CONFIG_NVM_DEBUG
+ atomic_long_inc(&pblk->cache_reads);
+#endif
} else {
rqd->ppa_addr = ppa;
}
+
+ rqd->flags = pblk_set_read_mode(pblk, PBLK_READ_RANDOM);
}
int pblk_submit_read(struct pblk *pblk, struct bio *bio)
@@ -316,13 +328,16 @@ int pblk_submit_read(struct pblk *pblk, struct bio *bio)
*/
bio_init_idx = pblk_get_bi_idx(bio);
+ rqd->meta_list = nvm_dev_dma_alloc(dev->parent, GFP_KERNEL,
+ &rqd->dma_meta_list);
+ if (!rqd->meta_list) {
+ pr_err("pblk: not able to allocate ppa list\n");
+ goto fail_rqd_free;
+ }
+
if (nr_secs > 1) {
- rqd->ppa_list = nvm_dev_dma_alloc(dev->parent, GFP_KERNEL,
- &rqd->dma_ppa_list);
- if (!rqd->ppa_list) {
- pr_err("pblk: not able to allocate ppa list\n");
- goto fail_rqd_free;
- }
+ rqd->ppa_list = rqd->meta_list + pblk_dma_meta_size;
+ rqd->dma_ppa_list = rqd->dma_meta_list + pblk_dma_meta_size;
pblk_read_ppalist_rq(pblk, rqd, &read_bitmap);
} else {
@@ -332,6 +347,7 @@ int pblk_submit_read(struct pblk *pblk, struct bio *bio)
bio_get(bio);
if (bitmap_full(&read_bitmap, nr_secs)) {
bio_endio(bio);
+ atomic_inc(&pblk->inflight_io);
pblk_end_io_read(rqd);
return NVM_IO_OK;
}
@@ -339,17 +355,17 @@ int pblk_submit_read(struct pblk *pblk, struct bio *bio)
/* All sectors are to be read from the device */
if (bitmap_empty(&read_bitmap, rqd->nr_ppas)) {
struct bio *int_bio = NULL;
- struct pblk_r_ctx *r_ctx = nvm_rq_to_pdu(rqd);
+ struct pblk_g_ctx *r_ctx = nvm_rq_to_pdu(rqd);
/* Clone read bio to deal with read errors internally */
- int_bio = bio_clone_bioset(bio, GFP_KERNEL, fs_bio_set);
+ int_bio = bio_clone_fast(bio, GFP_KERNEL, pblk_bio_set);
if (!int_bio) {
pr_err("pblk: could not clone read bio\n");
return NVM_IO_ERR;
}
rqd->bio = int_bio;
- r_ctx->orig_bio = bio;
+ r_ctx->private = bio;
ret = pblk_submit_read_io(pblk, rqd);
if (ret) {
@@ -445,7 +461,6 @@ int pblk_submit_read_gc(struct pblk *pblk, u64 *lba_list, void *data,
{
struct nvm_tgt_dev *dev = pblk->dev;
struct nvm_geo *geo = &dev->geo;
- struct request_queue *q = dev->q;
struct bio *bio;
struct nvm_rq rqd;
int ret, data_len;
@@ -453,22 +468,19 @@ int pblk_submit_read_gc(struct pblk *pblk, u64 *lba_list, void *data,
memset(&rqd, 0, sizeof(struct nvm_rq));
+ rqd.meta_list = nvm_dev_dma_alloc(dev->parent, GFP_KERNEL,
+ &rqd.dma_meta_list);
+ if (!rqd.meta_list)
+ return NVM_IO_ERR;
+
if (nr_secs > 1) {
- rqd.ppa_list = nvm_dev_dma_alloc(dev->parent, GFP_KERNEL,
- &rqd.dma_ppa_list);
- if (!rqd.ppa_list)
- return NVM_IO_ERR;
+ rqd.ppa_list = rqd.meta_list + pblk_dma_meta_size;
+ rqd.dma_ppa_list = rqd.dma_meta_list + pblk_dma_meta_size;
*secs_to_gc = read_ppalist_rq_gc(pblk, &rqd, line, lba_list,
nr_secs);
- if (*secs_to_gc == 1) {
- struct ppa_addr ppa;
-
- ppa = rqd.ppa_list[0];
- nvm_dev_dma_free(dev->parent, rqd.ppa_list,
- rqd.dma_ppa_list);
- rqd.ppa_addr = ppa;
- }
+ if (*secs_to_gc == 1)
+ rqd.ppa_addr = rqd.ppa_list[0];
} else {
*secs_to_gc = read_rq_gc(pblk, &rqd, line, lba_list[0]);
}
@@ -477,7 +489,8 @@ int pblk_submit_read_gc(struct pblk *pblk, u64 *lba_list, void *data,
goto out;
data_len = (*secs_to_gc) * geo->sec_size;
- bio = bio_map_kern(q, data, data_len, GFP_KERNEL);
+ bio = pblk_bio_map_addr(pblk, data, *secs_to_gc, data_len,
+ PBLK_KMALLOC_META, GFP_KERNEL);
if (IS_ERR(bio)) {
pr_err("pblk: could not allocate GC bio (%lu)\n", PTR_ERR(bio));
goto err_free_dma;
@@ -490,6 +503,7 @@ int pblk_submit_read_gc(struct pblk *pblk, u64 *lba_list, void *data,
rqd.end_io = pblk_end_io_sync;
rqd.private = &wait;
rqd.nr_ppas = *secs_to_gc;
+ rqd.flags = pblk_set_read_mode(pblk, PBLK_READ_RANDOM);
rqd.bio = bio;
ret = pblk_submit_read_io(pblk, &rqd);
@@ -503,6 +517,7 @@ int pblk_submit_read_gc(struct pblk *pblk, u64 *lba_list, void *data,
msecs_to_jiffies(PBLK_COMMAND_TIMEOUT_MS))) {
pr_err("pblk: GC read I/O timed out\n");
}
+ atomic_dec(&pblk->inflight_io);
if (rqd.error) {
atomic_long_inc(&pblk->read_failed_gc);
@@ -518,12 +533,10 @@ int pblk_submit_read_gc(struct pblk *pblk, u64 *lba_list, void *data,
#endif
out:
- if (rqd.nr_ppas > 1)
- nvm_dev_dma_free(dev->parent, rqd.ppa_list, rqd.dma_ppa_list);
+ nvm_dev_dma_free(dev->parent, rqd.meta_list, rqd.dma_meta_list);
return NVM_IO_OK;
err_free_dma:
- if (rqd.nr_ppas > 1)
- nvm_dev_dma_free(dev->parent, rqd.ppa_list, rqd.dma_ppa_list);
+ nvm_dev_dma_free(dev->parent, rqd.meta_list, rqd.dma_meta_list);
return NVM_IO_ERR;
}
diff --git a/drivers/lightnvm/pblk-recovery.c b/drivers/lightnvm/pblk-recovery.c
index f8f85087cd3c..0e48d3e4e143 100644
--- a/drivers/lightnvm/pblk-recovery.c
+++ b/drivers/lightnvm/pblk-recovery.c
@@ -120,18 +120,18 @@ int pblk_recov_setup_rq(struct pblk *pblk, struct pblk_c_ctx *c_ctx,
return 0;
}
-__le64 *pblk_recov_get_lba_list(struct pblk *pblk, struct line_emeta *emeta)
+__le64 *pblk_recov_get_lba_list(struct pblk *pblk, struct line_emeta *emeta_buf)
{
u32 crc;
- crc = pblk_calc_emeta_crc(pblk, emeta);
- if (le32_to_cpu(emeta->crc) != crc)
+ crc = pblk_calc_emeta_crc(pblk, emeta_buf);
+ if (le32_to_cpu(emeta_buf->crc) != crc)
return NULL;
- if (le32_to_cpu(emeta->header.identifier) != PBLK_MAGIC)
+ if (le32_to_cpu(emeta_buf->header.identifier) != PBLK_MAGIC)
return NULL;
- return pblk_line_emeta_to_lbas(emeta);
+ return emeta_to_lbas(pblk, emeta_buf);
}
static int pblk_recov_l2p_from_emeta(struct pblk *pblk, struct pblk_line *line)
@@ -139,19 +139,20 @@ static int pblk_recov_l2p_from_emeta(struct pblk *pblk, struct pblk_line *line)
struct nvm_tgt_dev *dev = pblk->dev;
struct nvm_geo *geo = &dev->geo;
struct pblk_line_meta *lm = &pblk->lm;
- struct line_emeta *emeta = line->emeta;
+ struct pblk_emeta *emeta = line->emeta;
+ struct line_emeta *emeta_buf = emeta->buf;
__le64 *lba_list;
int data_start;
int nr_data_lbas, nr_valid_lbas, nr_lbas = 0;
int i;
- lba_list = pblk_recov_get_lba_list(pblk, emeta);
+ lba_list = pblk_recov_get_lba_list(pblk, emeta_buf);
if (!lba_list)
return 1;
data_start = pblk_line_smeta_start(pblk, line) + lm->smeta_sec;
- nr_data_lbas = lm->sec_per_line - lm->emeta_sec;
- nr_valid_lbas = le64_to_cpu(emeta->nr_valid_lbas);
+ nr_data_lbas = lm->sec_per_line - lm->emeta_sec[0];
+ nr_valid_lbas = le64_to_cpu(emeta_buf->nr_valid_lbas);
for (i = data_start; i < nr_data_lbas && nr_lbas < nr_valid_lbas; i++) {
struct ppa_addr ppa;
@@ -169,7 +170,7 @@ static int pblk_recov_l2p_from_emeta(struct pblk *pblk, struct pblk_line *line)
if (test_and_set_bit(i, line->invalid_bitmap))
WARN_ONCE(1, "pblk: rec. double invalidate:\n");
else
- line->vsc--;
+ le32_add_cpu(line->vsc, -1);
spin_unlock(&line->lock);
continue;
@@ -181,7 +182,7 @@ static int pblk_recov_l2p_from_emeta(struct pblk *pblk, struct pblk_line *line)
if (nr_valid_lbas != nr_lbas)
pr_err("pblk: line %d - inconsistent lba list(%llu/%d)\n",
- line->id, line->emeta->nr_valid_lbas, nr_lbas);
+ line->id, emeta_buf->nr_valid_lbas, nr_lbas);
line->left_msecs = 0;
@@ -195,7 +196,7 @@ static int pblk_calc_sec_in_line(struct pblk *pblk, struct pblk_line *line)
struct pblk_line_meta *lm = &pblk->lm;
int nr_bb = bitmap_weight(line->blk_bitmap, lm->blk_per_line);
- return lm->sec_per_line - lm->smeta_sec - lm->emeta_sec -
+ return lm->sec_per_line - lm->smeta_sec - lm->emeta_sec[0] -
nr_bb * geo->sec_per_blk;
}
@@ -240,7 +241,7 @@ static int pblk_recov_read_oob(struct pblk *pblk, struct pblk_line *line,
r_ptr_int = r_ptr;
next_read_rq:
- memset(rqd, 0, pblk_r_rq_size);
+ memset(rqd, 0, pblk_g_rq_size);
rq_ppas = pblk_calc_secs(pblk, left_ppas, 0);
if (!rq_ppas)
@@ -256,7 +257,6 @@ next_read_rq:
rqd->bio = bio;
rqd->opcode = NVM_OP_PREAD;
- rqd->flags = pblk_set_read_mode(pblk);
rqd->meta_list = meta_list;
rqd->nr_ppas = rq_ppas;
rqd->ppa_list = ppa_list;
@@ -265,6 +265,11 @@ next_read_rq:
rqd->end_io = pblk_end_io_sync;
rqd->private = &wait;
+ if (pblk_io_aligned(pblk, rq_ppas))
+ rqd->flags = pblk_set_read_mode(pblk, PBLK_READ_SEQUENTIAL);
+ else
+ rqd->flags = pblk_set_read_mode(pblk, PBLK_READ_RANDOM);
+
for (i = 0; i < rqd->nr_ppas; ) {
struct ppa_addr ppa;
int pos;
@@ -295,7 +300,7 @@ next_read_rq:
pr_err("pblk: L2P recovery read timed out\n");
return -EINTR;
}
-
+ atomic_dec(&pblk->inflight_io);
reinit_completion(&wait);
/* At this point, the read should not fail. If it does, it is a problem
@@ -322,47 +327,94 @@ next_read_rq:
return 0;
}
+static void pblk_recov_complete(struct kref *ref)
+{
+ struct pblk_pad_rq *pad_rq = container_of(ref, struct pblk_pad_rq, ref);
+
+ complete(&pad_rq->wait);
+}
+
+static void pblk_end_io_recov(struct nvm_rq *rqd)
+{
+ struct pblk_pad_rq *pad_rq = rqd->private;
+ struct pblk *pblk = pad_rq->pblk;
+ struct nvm_tgt_dev *dev = pblk->dev;
+
+ kref_put(&pad_rq->ref, pblk_recov_complete);
+ nvm_dev_dma_free(dev->parent, rqd->meta_list, rqd->dma_meta_list);
+ pblk_free_rqd(pblk, rqd, WRITE);
+}
+
static int pblk_recov_pad_oob(struct pblk *pblk, struct pblk_line *line,
- struct pblk_recov_alloc p, int left_ppas)
+ int left_ppas)
{
struct nvm_tgt_dev *dev = pblk->dev;
struct nvm_geo *geo = &dev->geo;
struct ppa_addr *ppa_list;
struct pblk_sec_meta *meta_list;
+ struct pblk_pad_rq *pad_rq;
struct nvm_rq *rqd;
struct bio *bio;
void *data;
dma_addr_t dma_ppa_list, dma_meta_list;
- __le64 *lba_list = pblk_line_emeta_to_lbas(line->emeta);
+ __le64 *lba_list = emeta_to_lbas(pblk, line->emeta->buf);
u64 w_ptr = line->cur_sec;
- int left_line_ppas = line->left_msecs;
- int rq_ppas, rq_len;
+ int left_line_ppas, rq_ppas, rq_len;
int i, j;
int ret = 0;
- DECLARE_COMPLETION_ONSTACK(wait);
- ppa_list = p.ppa_list;
- meta_list = p.meta_list;
- rqd = p.rqd;
- data = p.data;
- dma_ppa_list = p.dma_ppa_list;
- dma_meta_list = p.dma_meta_list;
+ spin_lock(&line->lock);
+ left_line_ppas = line->left_msecs;
+ spin_unlock(&line->lock);
+
+ pad_rq = kmalloc(sizeof(struct pblk_pad_rq), GFP_KERNEL);
+ if (!pad_rq)
+ return -ENOMEM;
+
+ data = vzalloc(pblk->max_write_pgs * geo->sec_size);
+ if (!data) {
+ ret = -ENOMEM;
+ goto free_rq;
+ }
+
+ pad_rq->pblk = pblk;
+ init_completion(&pad_rq->wait);
+ kref_init(&pad_rq->ref);
next_pad_rq:
rq_ppas = pblk_calc_secs(pblk, left_ppas, 0);
- if (!rq_ppas)
- rq_ppas = pblk->min_write_pgs;
+ if (rq_ppas < pblk->min_write_pgs) {
+ pr_err("pblk: corrupted pad line %d\n", line->id);
+ goto free_rq;
+ }
+
rq_len = rq_ppas * geo->sec_size;
+ meta_list = nvm_dev_dma_alloc(dev->parent, GFP_KERNEL, &dma_meta_list);
+ if (!meta_list) {
+ ret = -ENOMEM;
+ goto free_data;
+ }
+
+ ppa_list = (void *)(meta_list) + pblk_dma_meta_size;
+ dma_ppa_list = dma_meta_list + pblk_dma_meta_size;
+
+ rqd = pblk_alloc_rqd(pblk, WRITE);
+ if (IS_ERR(rqd)) {
+ ret = PTR_ERR(rqd);
+ goto fail_free_meta;
+ }
+ memset(rqd, 0, pblk_w_rq_size);
+
bio = bio_map_kern(dev->q, data, rq_len, GFP_KERNEL);
- if (IS_ERR(bio))
- return PTR_ERR(bio);
+ if (IS_ERR(bio)) {
+ ret = PTR_ERR(bio);
+ goto fail_free_rqd;
+ }
bio->bi_iter.bi_sector = 0; /* internal bio */
bio_set_op_attrs(bio, REQ_OP_WRITE, 0);
- memset(rqd, 0, pblk_r_rq_size);
-
rqd->bio = bio;
rqd->opcode = NVM_OP_PWRITE;
rqd->flags = pblk_set_progr_mode(pblk, WRITE);
@@ -371,8 +423,8 @@ next_pad_rq:
rqd->ppa_list = ppa_list;
rqd->dma_ppa_list = dma_ppa_list;
rqd->dma_meta_list = dma_meta_list;
- rqd->end_io = pblk_end_io_sync;
- rqd->private = &wait;
+ rqd->end_io = pblk_end_io_recov;
+ rqd->private = pad_rq;
for (i = 0; i < rqd->nr_ppas; ) {
struct ppa_addr ppa;
@@ -390,34 +442,51 @@ next_pad_rq:
for (j = 0; j < pblk->min_write_pgs; j++, i++, w_ptr++) {
struct ppa_addr dev_ppa;
+ __le64 addr_empty = cpu_to_le64(ADDR_EMPTY);
dev_ppa = addr_to_gen_ppa(pblk, w_ptr, line->id);
pblk_map_invalidate(pblk, dev_ppa);
- meta_list[i].lba = cpu_to_le64(ADDR_EMPTY);
- lba_list[w_ptr] = cpu_to_le64(ADDR_EMPTY);
+ lba_list[w_ptr] = meta_list[i].lba = addr_empty;
rqd->ppa_list[i] = dev_ppa;
}
}
+ kref_get(&pad_rq->ref);
+
ret = pblk_submit_io(pblk, rqd);
if (ret) {
pr_err("pblk: I/O submission failed: %d\n", ret);
- return ret;
+ goto free_data;
}
- if (!wait_for_completion_io_timeout(&wait,
- msecs_to_jiffies(PBLK_COMMAND_TIMEOUT_MS))) {
- pr_err("pblk: L2P recovery write timed out\n");
- }
- reinit_completion(&wait);
+ atomic_dec(&pblk->inflight_io);
left_line_ppas -= rq_ppas;
left_ppas -= rq_ppas;
- if (left_ppas > 0 && left_line_ppas)
+ if (left_ppas && left_line_ppas)
goto next_pad_rq;
- return 0;
+ kref_put(&pad_rq->ref, pblk_recov_complete);
+
+ if (!wait_for_completion_io_timeout(&pad_rq->wait,
+ msecs_to_jiffies(PBLK_COMMAND_TIMEOUT_MS))) {
+ pr_err("pblk: pad write timed out\n");
+ ret = -ETIME;
+ }
+
+free_rq:
+ kfree(pad_rq);
+free_data:
+ vfree(data);
+ return ret;
+
+fail_free_rqd:
+ pblk_free_rqd(pblk, rqd, WRITE);
+fail_free_meta:
+ nvm_dev_dma_free(dev->parent, meta_list, dma_meta_list);
+ kfree(pad_rq);
+ return ret;
}
/* When this function is called, it means that not all upper pages have been
@@ -456,7 +525,7 @@ static int pblk_recov_scan_all_oob(struct pblk *pblk, struct pblk_line *line,
rec_round = 0;
next_rq:
- memset(rqd, 0, pblk_r_rq_size);
+ memset(rqd, 0, pblk_g_rq_size);
rq_ppas = pblk_calc_secs(pblk, left_ppas, 0);
if (!rq_ppas)
@@ -472,7 +541,6 @@ next_rq:
rqd->bio = bio;
rqd->opcode = NVM_OP_PREAD;
- rqd->flags = pblk_set_read_mode(pblk);
rqd->meta_list = meta_list;
rqd->nr_ppas = rq_ppas;
rqd->ppa_list = ppa_list;
@@ -481,6 +549,11 @@ next_rq:
rqd->end_io = pblk_end_io_sync;
rqd->private = &wait;
+ if (pblk_io_aligned(pblk, rq_ppas))
+ rqd->flags = pblk_set_read_mode(pblk, PBLK_READ_SEQUENTIAL);
+ else
+ rqd->flags = pblk_set_read_mode(pblk, PBLK_READ_RANDOM);
+
for (i = 0; i < rqd->nr_ppas; ) {
struct ppa_addr ppa;
int pos;
@@ -510,6 +583,7 @@ next_rq:
msecs_to_jiffies(PBLK_COMMAND_TIMEOUT_MS))) {
pr_err("pblk: L2P recovery read timed out\n");
}
+ atomic_dec(&pblk->inflight_io);
reinit_completion(&wait);
/* This should not happen since the read failed during normal recovery,
@@ -544,7 +618,7 @@ next_rq:
if (pad_secs > line->left_msecs)
pad_secs = line->left_msecs;
- ret = pblk_recov_pad_oob(pblk, line, p, pad_secs);
+ ret = pblk_recov_pad_oob(pblk, line, pad_secs);
if (ret)
pr_err("pblk: OOB padding failed (err:%d)\n", ret);
@@ -552,7 +626,6 @@ next_rq:
if (ret)
pr_err("pblk: OOB read failed (err:%d)\n", ret);
- line->left_ssecs = line->left_msecs;
left_ppas = 0;
}
@@ -591,7 +664,7 @@ static int pblk_recov_scan_oob(struct pblk *pblk, struct pblk_line *line,
*done = 1;
next_rq:
- memset(rqd, 0, pblk_r_rq_size);
+ memset(rqd, 0, pblk_g_rq_size);
rq_ppas = pblk_calc_secs(pblk, left_ppas, 0);
if (!rq_ppas)
@@ -607,7 +680,6 @@ next_rq:
rqd->bio = bio;
rqd->opcode = NVM_OP_PREAD;
- rqd->flags = pblk_set_read_mode(pblk);
rqd->meta_list = meta_list;
rqd->nr_ppas = rq_ppas;
rqd->ppa_list = ppa_list;
@@ -616,6 +688,11 @@ next_rq:
rqd->end_io = pblk_end_io_sync;
rqd->private = &wait;
+ if (pblk_io_aligned(pblk, rq_ppas))
+ rqd->flags = pblk_set_read_mode(pblk, PBLK_READ_SEQUENTIAL);
+ else
+ rqd->flags = pblk_set_read_mode(pblk, PBLK_READ_RANDOM);
+
for (i = 0; i < rqd->nr_ppas; ) {
struct ppa_addr ppa;
int pos;
@@ -646,6 +723,7 @@ next_rq:
msecs_to_jiffies(PBLK_COMMAND_TIMEOUT_MS))) {
pr_err("pblk: L2P recovery read timed out\n");
}
+ atomic_dec(&pblk->inflight_io);
reinit_completion(&wait);
/* Reached the end of the written line */
@@ -658,7 +736,6 @@ next_rq:
/* Roll back failed sectors */
line->cur_sec -= nr_error_bits;
line->left_msecs += nr_error_bits;
- line->left_ssecs = line->left_msecs;
bitmap_clear(line->map_bitmap, line->cur_sec, nr_error_bits);
left_ppas = 0;
@@ -770,8 +847,9 @@ struct pblk_line *pblk_recov_l2p(struct pblk *pblk)
struct pblk_line_meta *lm = &pblk->lm;
struct pblk_line_mgmt *l_mg = &pblk->l_mg;
struct pblk_line *line, *tline, *data_line = NULL;
- struct line_smeta *smeta;
- struct line_emeta *emeta;
+ struct pblk_smeta *smeta;
+ struct pblk_emeta *emeta;
+ struct line_smeta *smeta_buf;
int found_lines = 0, recovered_lines = 0, open_lines = 0;
int is_next = 0;
int meta_line;
@@ -784,8 +862,9 @@ struct pblk_line *pblk_recov_l2p(struct pblk *pblk)
spin_lock(&l_mg->free_lock);
meta_line = find_first_zero_bit(&l_mg->meta_bitmap, PBLK_DATA_LINES);
set_bit(meta_line, &l_mg->meta_bitmap);
- smeta = l_mg->sline_meta[meta_line].meta;
- emeta = l_mg->eline_meta[meta_line].meta;
+ smeta = l_mg->sline_meta[meta_line];
+ emeta = l_mg->eline_meta[meta_line];
+ smeta_buf = (struct line_smeta *)smeta;
spin_unlock(&l_mg->free_lock);
/* Order data lines using their sequence number */
@@ -796,33 +875,33 @@ struct pblk_line *pblk_recov_l2p(struct pblk *pblk)
memset(smeta, 0, lm->smeta_len);
line->smeta = smeta;
- line->lun_bitmap = ((void *)(smeta)) +
+ line->lun_bitmap = ((void *)(smeta_buf)) +
sizeof(struct line_smeta);
/* Lines that cannot be read are assumed as not written here */
if (pblk_line_read_smeta(pblk, line))
continue;
- crc = pblk_calc_smeta_crc(pblk, smeta);
- if (le32_to_cpu(smeta->crc) != crc)
+ crc = pblk_calc_smeta_crc(pblk, smeta_buf);
+ if (le32_to_cpu(smeta_buf->crc) != crc)
continue;
- if (le32_to_cpu(smeta->header.identifier) != PBLK_MAGIC)
+ if (le32_to_cpu(smeta_buf->header.identifier) != PBLK_MAGIC)
continue;
- if (le16_to_cpu(smeta->header.version) != 1) {
+ if (le16_to_cpu(smeta_buf->header.version) != 1) {
pr_err("pblk: found incompatible line version %u\n",
- smeta->header.version);
+ smeta_buf->header.version);
return ERR_PTR(-EINVAL);
}
/* The first valid instance uuid is used for initialization */
if (!valid_uuid) {
- memcpy(pblk->instance_uuid, smeta->header.uuid, 16);
+ memcpy(pblk->instance_uuid, smeta_buf->header.uuid, 16);
valid_uuid = 1;
}
- if (memcmp(pblk->instance_uuid, smeta->header.uuid, 16)) {
+ if (memcmp(pblk->instance_uuid, smeta_buf->header.uuid, 16)) {
pr_debug("pblk: ignore line %u due to uuid mismatch\n",
i);
continue;
@@ -830,9 +909,9 @@ struct pblk_line *pblk_recov_l2p(struct pblk *pblk)
/* Update line metadata */
spin_lock(&line->lock);
- line->id = le32_to_cpu(line->smeta->header.id);
- line->type = le16_to_cpu(line->smeta->header.type);
- line->seq_nr = le64_to_cpu(line->smeta->seq_nr);
+ line->id = le32_to_cpu(smeta_buf->header.id);
+ line->type = le16_to_cpu(smeta_buf->header.type);
+ line->seq_nr = le64_to_cpu(smeta_buf->seq_nr);
spin_unlock(&line->lock);
/* Update general metadata */
@@ -848,7 +927,7 @@ struct pblk_line *pblk_recov_l2p(struct pblk *pblk)
pblk_recov_line_add_ordered(&recov_list, line);
found_lines++;
pr_debug("pblk: recovering data line %d, seq:%llu\n",
- line->id, smeta->seq_nr);
+ line->id, smeta_buf->seq_nr);
}
if (!found_lines) {
@@ -868,15 +947,15 @@ struct pblk_line *pblk_recov_l2p(struct pblk *pblk)
recovered_lines++;
/* Calculate where emeta starts based on the line bb */
- off = lm->sec_per_line - lm->emeta_sec;
+ off = lm->sec_per_line - lm->emeta_sec[0];
nr_bb = bitmap_weight(line->blk_bitmap, lm->blk_per_line);
off -= nr_bb * geo->sec_per_pl;
- memset(emeta, 0, lm->emeta_len);
- line->emeta = emeta;
line->emeta_ssec = off;
+ line->emeta = emeta;
+ memset(line->emeta->buf, 0, lm->emeta_len[0]);
- if (pblk_line_read_emeta(pblk, line)) {
+ if (pblk_line_read_emeta(pblk, line, line->emeta->buf)) {
pblk_recov_l2p_from_oob(pblk, line);
goto next;
}
@@ -941,58 +1020,26 @@ out:
}
/*
- * Pad until smeta can be read on current data line
+ * Pad current line
*/
-void pblk_recov_pad(struct pblk *pblk)
+int pblk_recov_pad(struct pblk *pblk)
{
- struct nvm_tgt_dev *dev = pblk->dev;
- struct nvm_geo *geo = &dev->geo;
struct pblk_line *line;
struct pblk_line_mgmt *l_mg = &pblk->l_mg;
- struct nvm_rq *rqd;
- struct pblk_recov_alloc p;
- struct ppa_addr *ppa_list;
- struct pblk_sec_meta *meta_list;
- void *data;
- dma_addr_t dma_ppa_list, dma_meta_list;
+ int left_msecs;
+ int ret = 0;
spin_lock(&l_mg->free_lock);
line = l_mg->data_line;
+ left_msecs = line->left_msecs;
spin_unlock(&l_mg->free_lock);
- rqd = pblk_alloc_rqd(pblk, READ);
- if (IS_ERR(rqd))
- return;
-
- meta_list = nvm_dev_dma_alloc(dev->parent, GFP_KERNEL, &dma_meta_list);
- if (!meta_list)
- goto free_rqd;
-
- ppa_list = (void *)(meta_list) + pblk_dma_meta_size;
- dma_ppa_list = dma_meta_list + pblk_dma_meta_size;
-
- data = kcalloc(pblk->max_write_pgs, geo->sec_size, GFP_KERNEL);
- if (!data)
- goto free_meta_list;
-
- p.ppa_list = ppa_list;
- p.meta_list = meta_list;
- p.rqd = rqd;
- p.data = data;
- p.dma_ppa_list = dma_ppa_list;
- p.dma_meta_list = dma_meta_list;
-
- if (pblk_recov_pad_oob(pblk, line, p, line->left_msecs)) {
- pr_err("pblk: Tear down padding failed\n");
- goto free_data;
+ ret = pblk_recov_pad_oob(pblk, line, left_msecs);
+ if (ret) {
+ pr_err("pblk: Tear down padding failed (%d)\n", ret);
+ return ret;
}
- pblk_line_close(pblk, line);
-
-free_data:
- kfree(data);
-free_meta_list:
- nvm_dev_dma_free(dev->parent, meta_list, dma_meta_list);
-free_rqd:
- pblk_free_rqd(pblk, rqd, READ);
+ pblk_line_close_meta(pblk, line);
+ return ret;
}
diff --git a/drivers/lightnvm/pblk-rl.c b/drivers/lightnvm/pblk-rl.c
index ab7cbb144f3f..2e6a5361baf0 100644
--- a/drivers/lightnvm/pblk-rl.c
+++ b/drivers/lightnvm/pblk-rl.c
@@ -23,11 +23,35 @@ static void pblk_rl_kick_u_timer(struct pblk_rl *rl)
mod_timer(&rl->u_timer, jiffies + msecs_to_jiffies(5000));
}
+int pblk_rl_is_limit(struct pblk_rl *rl)
+{
+ int rb_space;
+
+ rb_space = atomic_read(&rl->rb_space);
+
+ return (rb_space == 0);
+}
+
int pblk_rl_user_may_insert(struct pblk_rl *rl, int nr_entries)
{
int rb_user_cnt = atomic_read(&rl->rb_user_cnt);
+ int rb_space = atomic_read(&rl->rb_space);
- return (!(rb_user_cnt + nr_entries > rl->rb_user_max));
+ if (unlikely(rb_space >= 0) && (rb_space - nr_entries < 0))
+ return NVM_IO_ERR;
+
+ if (rb_user_cnt >= rl->rb_user_max)
+ return NVM_IO_REQUEUE;
+
+ return NVM_IO_OK;
+}
+
+void pblk_rl_inserted(struct pblk_rl *rl, int nr_entries)
+{
+ int rb_space = atomic_read(&rl->rb_space);
+
+ if (unlikely(rb_space >= 0))
+ atomic_sub(nr_entries, &rl->rb_space);
}
int pblk_rl_gc_may_insert(struct pblk_rl *rl, int nr_entries)
@@ -37,7 +61,7 @@ int pblk_rl_gc_may_insert(struct pblk_rl *rl, int nr_entries)
/* If there is no user I/O let GC take over space on the write buffer */
rb_user_active = READ_ONCE(rl->rb_user_active);
- return (!(rb_gc_cnt + nr_entries > rl->rb_gc_max && rb_user_active));
+ return (!(rb_gc_cnt >= rl->rb_gc_max && rb_user_active));
}
void pblk_rl_user_in(struct pblk_rl *rl, int nr_entries)
@@ -77,33 +101,32 @@ static int pblk_rl_update_rates(struct pblk_rl *rl, unsigned long max)
unsigned long free_blocks = pblk_rl_nr_free_blks(rl);
if (free_blocks >= rl->high) {
- rl->rb_user_max = max - rl->rb_gc_rsv;
- rl->rb_gc_max = rl->rb_gc_rsv;
+ rl->rb_user_max = max;
+ rl->rb_gc_max = 0;
rl->rb_state = PBLK_RL_HIGH;
} else if (free_blocks < rl->high) {
int shift = rl->high_pw - rl->rb_windows_pw;
int user_windows = free_blocks >> shift;
int user_max = user_windows << PBLK_MAX_REQ_ADDRS_PW;
- int gc_max;
rl->rb_user_max = user_max;
- gc_max = max - rl->rb_user_max;
- rl->rb_gc_max = max(gc_max, rl->rb_gc_rsv);
-
- if (free_blocks > rl->low)
- rl->rb_state = PBLK_RL_MID;
- else
- rl->rb_state = PBLK_RL_LOW;
+ rl->rb_gc_max = max - user_max;
+
+ if (free_blocks <= rl->rsv_blocks) {
+ rl->rb_user_max = 0;
+ rl->rb_gc_max = max;
+ }
+
+ /* In the worst case, we will need to GC lines in the low list
+ * (high valid sector count). If there are lines to GC on high
+ * or mid lists, these will be prioritized
+ */
+ rl->rb_state = PBLK_RL_LOW;
}
return rl->rb_state;
}
-void pblk_rl_set_gc_rsc(struct pblk_rl *rl, int rsv)
-{
- rl->rb_gc_rsv = rl->rb_gc_max = rsv;
-}
-
void pblk_rl_free_lines_inc(struct pblk_rl *rl, struct pblk_line *line)
{
struct pblk *pblk = container_of(rl, struct pblk, rl);
@@ -122,11 +145,15 @@ void pblk_rl_free_lines_inc(struct pblk_rl *rl, struct pblk_line *line)
void pblk_rl_free_lines_dec(struct pblk_rl *rl, struct pblk_line *line)
{
- struct pblk *pblk = container_of(rl, struct pblk, rl);
int blk_in_line = atomic_read(&line->blk_in_line);
- int ret;
atomic_sub(blk_in_line, &rl->free_blocks);
+}
+
+void pblk_gc_should_kick(struct pblk *pblk)
+{
+ struct pblk_rl *rl = &pblk->rl;
+ int ret;
/* Rates will not change that often - no need to lock update */
ret = pblk_rl_update_rates(rl, rl->rb_budget);
@@ -136,11 +163,16 @@ void pblk_rl_free_lines_dec(struct pblk_rl *rl, struct pblk_line *line)
pblk_gc_should_stop(pblk);
}
-int pblk_rl_gc_thrs(struct pblk_rl *rl)
+int pblk_rl_high_thrs(struct pblk_rl *rl)
{
return rl->high;
}
+int pblk_rl_low_thrs(struct pblk_rl *rl)
+{
+ return rl->low;
+}
+
int pblk_rl_sysfs_rate_show(struct pblk_rl *rl)
{
return rl->rb_user_max;
@@ -161,24 +193,36 @@ void pblk_rl_free(struct pblk_rl *rl)
void pblk_rl_init(struct pblk_rl *rl, int budget)
{
+ struct pblk *pblk = container_of(rl, struct pblk, rl);
+ struct pblk_line_meta *lm = &pblk->lm;
+ int min_blocks = lm->blk_per_line * PBLK_GC_RSV_LINE;
unsigned int rb_windows;
rl->high = rl->total_blocks / PBLK_USER_HIGH_THRS;
- rl->low = rl->total_blocks / PBLK_USER_LOW_THRS;
rl->high_pw = get_count_order(rl->high);
+ rl->low = rl->total_blocks / PBLK_USER_LOW_THRS;
+ if (rl->low < min_blocks)
+ rl->low = min_blocks;
+
+ rl->rsv_blocks = min_blocks;
+
/* This will always be a power-of-2 */
rb_windows = budget / PBLK_MAX_REQ_ADDRS;
- rl->rb_windows_pw = get_count_order(rb_windows) + 1;
+ rl->rb_windows_pw = get_count_order(rb_windows);
/* To start with, all buffer is available to user I/O writers */
rl->rb_budget = budget;
rl->rb_user_max = budget;
- atomic_set(&rl->rb_user_cnt, 0);
rl->rb_gc_max = 0;
rl->rb_state = PBLK_RL_HIGH;
+
+ atomic_set(&rl->rb_user_cnt, 0);
atomic_set(&rl->rb_gc_cnt, 0);
+ atomic_set(&rl->rb_space, -1);
setup_timer(&rl->u_timer, pblk_rl_u_timer, (unsigned long)rl);
+
rl->rb_user_active = 0;
+ rl->rb_gc_active = 0;
}
diff --git a/drivers/lightnvm/pblk-sysfs.c b/drivers/lightnvm/pblk-sysfs.c
index f0af1d1ceeff..95fb434e2f01 100644
--- a/drivers/lightnvm/pblk-sysfs.c
+++ b/drivers/lightnvm/pblk-sysfs.c
@@ -49,30 +49,26 @@ static ssize_t pblk_sysfs_luns_show(struct pblk *pblk, char *page)
static ssize_t pblk_sysfs_rate_limiter(struct pblk *pblk, char *page)
{
- struct nvm_tgt_dev *dev = pblk->dev;
- struct nvm_geo *geo = &dev->geo;
int free_blocks, total_blocks;
int rb_user_max, rb_user_cnt;
- int rb_gc_max, rb_gc_rsv, rb_gc_cnt, rb_budget, rb_state;
+ int rb_gc_max, rb_gc_cnt, rb_budget, rb_state;
free_blocks = atomic_read(&pblk->rl.free_blocks);
rb_user_max = pblk->rl.rb_user_max;
rb_user_cnt = atomic_read(&pblk->rl.rb_user_cnt);
rb_gc_max = pblk->rl.rb_gc_max;
- rb_gc_rsv = pblk->rl.rb_gc_rsv;
rb_gc_cnt = atomic_read(&pblk->rl.rb_gc_cnt);
rb_budget = pblk->rl.rb_budget;
rb_state = pblk->rl.rb_state;
- total_blocks = geo->blks_per_lun * geo->nr_luns;
+ total_blocks = pblk->rl.total_blocks;
return snprintf(page, PAGE_SIZE,
- "u:%u/%u,gc:%u/%u/%u(%u/%u)(stop:<%u,full:>%u,free:%d/%d)-%d\n",
+ "u:%u/%u,gc:%u/%u(%u/%u)(stop:<%u,full:>%u,free:%d/%d)-%d\n",
rb_user_cnt,
rb_user_max,
rb_gc_cnt,
rb_gc_max,
- rb_gc_rsv,
rb_state,
rb_budget,
pblk->rl.low,
@@ -150,11 +146,11 @@ static ssize_t pblk_sysfs_lines(struct pblk *pblk, char *page)
ssize_t sz = 0;
int nr_free_lines;
int cur_data, cur_log;
- int free_line_cnt = 0, closed_line_cnt = 0;
+ int free_line_cnt = 0, closed_line_cnt = 0, emeta_line_cnt = 0;
int d_line_cnt = 0, l_line_cnt = 0;
int gc_full = 0, gc_high = 0, gc_mid = 0, gc_low = 0, gc_empty = 0;
- int free = 0, bad = 0, cor = 0;
- int msecs = 0, ssecs = 0, cur_sec = 0, vsc = 0, sec_in_line = 0;
+ int bad = 0, cor = 0;
+ int msecs = 0, cur_sec = 0, vsc = 0, sec_in_line = 0;
int map_weight = 0, meta_weight = 0;
spin_lock(&l_mg->free_lock);
@@ -166,6 +162,11 @@ static ssize_t pblk_sysfs_lines(struct pblk *pblk, char *page)
free_line_cnt++;
spin_unlock(&l_mg->free_lock);
+ spin_lock(&l_mg->close_lock);
+ list_for_each_entry(line, &l_mg->emeta_list, list)
+ emeta_line_cnt++;
+ spin_unlock(&l_mg->close_lock);
+
spin_lock(&l_mg->gc_lock);
list_for_each_entry(line, &l_mg->gc_full_list, list) {
if (line->type == PBLK_LINETYPE_DATA)
@@ -212,8 +213,6 @@ static ssize_t pblk_sysfs_lines(struct pblk *pblk, char *page)
gc_empty++;
}
- list_for_each_entry(line, &l_mg->free_list, list)
- free++;
list_for_each_entry(line, &l_mg->bad_list, list)
bad++;
list_for_each_entry(line, &l_mg->corrupt_list, list)
@@ -224,8 +223,7 @@ static ssize_t pblk_sysfs_lines(struct pblk *pblk, char *page)
if (l_mg->data_line) {
cur_sec = l_mg->data_line->cur_sec;
msecs = l_mg->data_line->left_msecs;
- ssecs = l_mg->data_line->left_ssecs;
- vsc = l_mg->data_line->vsc;
+ vsc = le32_to_cpu(*l_mg->data_line->vsc);
sec_in_line = l_mg->data_line->sec_in_line;
meta_weight = bitmap_weight(&l_mg->meta_bitmap,
PBLK_DATA_LINES);
@@ -235,17 +233,20 @@ static ssize_t pblk_sysfs_lines(struct pblk *pblk, char *page)
spin_unlock(&l_mg->free_lock);
if (nr_free_lines != free_line_cnt)
- pr_err("pblk: corrupted free line list\n");
+ pr_err("pblk: corrupted free line list:%d/%d\n",
+ nr_free_lines, free_line_cnt);
sz = snprintf(page, PAGE_SIZE - sz,
"line: nluns:%d, nblks:%d, nsecs:%d\n",
geo->nr_luns, lm->blk_per_line, lm->sec_per_line);
sz += snprintf(page + sz, PAGE_SIZE - sz,
- "lines:d:%d,l:%d-f:%d(%d),b:%d,co:%d,c:%d(d:%d,l:%d)t:%d\n",
+ "lines:d:%d,l:%d-f:%d,m:%d/%d,c:%d,b:%d,co:%d(d:%d,l:%d)t:%d\n",
cur_data, cur_log,
- free, nr_free_lines, bad, cor,
+ nr_free_lines,
+ emeta_line_cnt, meta_weight,
closed_line_cnt,
+ bad, cor,
d_line_cnt, l_line_cnt,
l_mg->nr_lines);
@@ -255,9 +256,10 @@ static ssize_t pblk_sysfs_lines(struct pblk *pblk, char *page)
atomic_read(&pblk->gc.inflight_gc));
sz += snprintf(page + sz, PAGE_SIZE - sz,
- "data (%d) cur:%d, left:%d/%d, vsc:%d, s:%d, map:%d/%d (%d)\n",
- cur_data, cur_sec, msecs, ssecs, vsc, sec_in_line,
- map_weight, lm->sec_per_line, meta_weight);
+ "data (%d) cur:%d, left:%d, vsc:%d, s:%d, map:%d/%d (%d)\n",
+ cur_data, cur_sec, msecs, vsc, sec_in_line,
+ map_weight, lm->sec_per_line,
+ atomic_read(&pblk->inflight_io));
return sz;
}
@@ -274,7 +276,7 @@ static ssize_t pblk_sysfs_lines_info(struct pblk *pblk, char *page)
lm->smeta_len, lm->smeta_sec);
sz += snprintf(page + sz, PAGE_SIZE - sz,
"emeta - len:%d, sec:%d, bb_start:%d\n",
- lm->emeta_len, lm->emeta_sec,
+ lm->emeta_len[0], lm->emeta_sec[0],
lm->emeta_bb);
sz += snprintf(page + sz, PAGE_SIZE - sz,
"bitmap lengths: sec:%d, blk:%d, lun:%d\n",
@@ -290,6 +292,11 @@ static ssize_t pblk_sysfs_lines_info(struct pblk *pblk, char *page)
return sz;
}
+static ssize_t pblk_sysfs_get_sec_per_write(struct pblk *pblk, char *page)
+{
+ return snprintf(page, PAGE_SIZE, "%d\n", pblk->sec_per_write);
+}
+
#ifdef CONFIG_NVM_DEBUG
static ssize_t pblk_sysfs_stats_debug(struct pblk *pblk, char *page)
{
@@ -303,52 +310,51 @@ static ssize_t pblk_sysfs_stats_debug(struct pblk *pblk, char *page)
atomic_long_read(&pblk->padded_wb),
atomic_long_read(&pblk->sub_writes),
atomic_long_read(&pblk->sync_writes),
- atomic_long_read(&pblk->compl_writes),
atomic_long_read(&pblk->recov_writes),
atomic_long_read(&pblk->recov_gc_writes),
atomic_long_read(&pblk->recov_gc_reads),
+ atomic_long_read(&pblk->cache_reads),
atomic_long_read(&pblk->sync_reads));
}
#endif
-static ssize_t pblk_sysfs_rate_store(struct pblk *pblk, const char *page,
- size_t len)
+static ssize_t pblk_sysfs_gc_force(struct pblk *pblk, const char *page,
+ size_t len)
{
- struct pblk_gc *gc = &pblk->gc;
size_t c_len;
- int value;
+ int force;
c_len = strcspn(page, "\n");
if (c_len >= len)
return -EINVAL;
- if (kstrtouint(page, 0, &value))
+ if (kstrtouint(page, 0, &force))
return -EINVAL;
- spin_lock(&gc->lock);
- pblk_rl_set_gc_rsc(&pblk->rl, value);
- spin_unlock(&gc->lock);
+ pblk_gc_sysfs_force(pblk, force);
return len;
}
-static ssize_t pblk_sysfs_gc_force(struct pblk *pblk, const char *page,
- size_t len)
+static ssize_t pblk_sysfs_set_sec_per_write(struct pblk *pblk,
+ const char *page, size_t len)
{
size_t c_len;
- int force;
+ int sec_per_write;
c_len = strcspn(page, "\n");
if (c_len >= len)
return -EINVAL;
- if (kstrtouint(page, 0, &force))
+ if (kstrtouint(page, 0, &sec_per_write))
return -EINVAL;
- if (force < 0 || force > 1)
+ if (sec_per_write < pblk->min_write_pgs
+ || sec_per_write > pblk->max_write_pgs
+ || sec_per_write % pblk->min_write_pgs != 0)
return -EINVAL;
- pblk_gc_sysfs_force(pblk, force);
+ pblk_set_sec_per_write(pblk, sec_per_write);
return len;
}
@@ -398,9 +404,9 @@ static struct attribute sys_gc_force = {
.mode = 0200,
};
-static struct attribute sys_gc_rl_max = {
- .name = "gc_rl_max",
- .mode = 0200,
+static struct attribute sys_max_sec_per_write = {
+ .name = "max_sec_per_write",
+ .mode = 0644,
};
#ifdef CONFIG_NVM_DEBUG
@@ -416,7 +422,7 @@ static struct attribute *pblk_attrs[] = {
&sys_errors_attr,
&sys_gc_state,
&sys_gc_force,
- &sys_gc_rl_max,
+ &sys_max_sec_per_write,
&sys_rb_attr,
&sys_stats_ppaf_attr,
&sys_lines_attr,
@@ -448,6 +454,8 @@ static ssize_t pblk_sysfs_show(struct kobject *kobj, struct attribute *attr,
return pblk_sysfs_lines(pblk, buf);
else if (strcmp(attr->name, "lines_info") == 0)
return pblk_sysfs_lines_info(pblk, buf);
+ else if (strcmp(attr->name, "max_sec_per_write") == 0)
+ return pblk_sysfs_get_sec_per_write(pblk, buf);
#ifdef CONFIG_NVM_DEBUG
else if (strcmp(attr->name, "stats") == 0)
return pblk_sysfs_stats_debug(pblk, buf);
@@ -460,10 +468,10 @@ static ssize_t pblk_sysfs_store(struct kobject *kobj, struct attribute *attr,
{
struct pblk *pblk = container_of(kobj, struct pblk, kobj);
- if (strcmp(attr->name, "gc_rl_max") == 0)
- return pblk_sysfs_rate_store(pblk, buf, len);
- else if (strcmp(attr->name, "gc_force") == 0)
+ if (strcmp(attr->name, "gc_force") == 0)
return pblk_sysfs_gc_force(pblk, buf, len);
+ else if (strcmp(attr->name, "max_sec_per_write") == 0)
+ return pblk_sysfs_set_sec_per_write(pblk, buf, len);
return 0;
}
diff --git a/drivers/lightnvm/pblk-write.c b/drivers/lightnvm/pblk-write.c
index aef6fd7c4a0c..d62a8f4faaf4 100644
--- a/drivers/lightnvm/pblk-write.c
+++ b/drivers/lightnvm/pblk-write.c
@@ -17,18 +17,6 @@
#include "pblk.h"
-static void pblk_sync_line(struct pblk *pblk, struct pblk_line *line)
-{
-#ifdef CONFIG_NVM_DEBUG
- atomic_long_inc(&pblk->sync_writes);
-#endif
-
- /* Counter protected by rb sync lock */
- line->left_ssecs--;
- if (!line->left_ssecs)
- pblk_line_run_ws(pblk, line, NULL, pblk_line_close_ws);
-}
-
static unsigned long pblk_end_w_bio(struct pblk *pblk, struct nvm_rq *rqd,
struct pblk_c_ctx *c_ctx)
{
@@ -39,21 +27,14 @@ static unsigned long pblk_end_w_bio(struct pblk *pblk, struct nvm_rq *rqd,
for (i = 0; i < c_ctx->nr_valid; i++) {
struct pblk_w_ctx *w_ctx;
- struct ppa_addr p;
- struct pblk_line *line;
w_ctx = pblk_rb_w_ctx(&pblk->rwb, c_ctx->sentry + i);
-
- p = rqd->ppa_list[i];
- line = &pblk->lines[pblk_dev_ppa_to_line(p)];
- pblk_sync_line(pblk, line);
-
while ((original_bio = bio_list_pop(&w_ctx->bios)))
bio_endio(original_bio);
}
#ifdef CONFIG_NVM_DEBUG
- atomic_long_add(c_ctx->nr_valid, &pblk->compl_writes);
+ atomic_long_add(c_ctx->nr_valid, &pblk->sync_writes);
#endif
ret = pblk_rb_sync_advance(&pblk->rwb, c_ctx->nr_valid);
@@ -169,7 +150,7 @@ static void pblk_end_w_fail(struct pblk *pblk, struct nvm_rq *rqd)
}
INIT_WORK(&recovery->ws_rec, pblk_submit_rec);
- queue_work(pblk->kw_wq, &recovery->ws_rec);
+ queue_work(pblk->close_wq, &recovery->ws_rec);
out:
pblk_complete_write(pblk, rqd, c_ctx);
@@ -186,14 +167,50 @@ static void pblk_end_io_write(struct nvm_rq *rqd)
}
#ifdef CONFIG_NVM_DEBUG
else
- WARN_ONCE(rqd->bio->bi_error, "pblk: corrupted write error\n");
+ WARN_ONCE(rqd->bio->bi_status, "pblk: corrupted write error\n");
#endif
pblk_complete_write(pblk, rqd, c_ctx);
+ atomic_dec(&pblk->inflight_io);
+}
+
+static void pblk_end_io_write_meta(struct nvm_rq *rqd)
+{
+ struct pblk *pblk = rqd->private;
+ struct nvm_tgt_dev *dev = pblk->dev;
+ struct nvm_geo *geo = &dev->geo;
+ struct pblk_g_ctx *m_ctx = nvm_rq_to_pdu(rqd);
+ struct pblk_line *line = m_ctx->private;
+ struct pblk_emeta *emeta = line->emeta;
+ int pos = pblk_ppa_to_pos(geo, rqd->ppa_list[0]);
+ struct pblk_lun *rlun = &pblk->luns[pos];
+ int sync;
+
+ up(&rlun->wr_sem);
+
+ if (rqd->error) {
+ pblk_log_write_err(pblk, rqd);
+ pr_err("pblk: metadata I/O failed. Line %d\n", line->id);
+ }
+#ifdef CONFIG_NVM_DEBUG
+ else
+ WARN_ONCE(rqd->bio->bi_status, "pblk: corrupted write error\n");
+#endif
+
+ sync = atomic_add_return(rqd->nr_ppas, &emeta->sync);
+ if (sync == emeta->nr_entries)
+ pblk_line_run_ws(pblk, line, NULL, pblk_line_close_ws,
+ pblk->close_wq);
+
+ bio_put(rqd->bio);
+ pblk_free_rqd(pblk, rqd, READ);
+
+ atomic_dec(&pblk->inflight_io);
}
static int pblk_alloc_w_rq(struct pblk *pblk, struct nvm_rq *rqd,
- unsigned int nr_secs)
+ unsigned int nr_secs,
+ nvm_end_io_fn(*end_io))
{
struct nvm_tgt_dev *dev = pblk->dev;
@@ -202,7 +219,7 @@ static int pblk_alloc_w_rq(struct pblk *pblk, struct nvm_rq *rqd,
rqd->nr_ppas = nr_secs;
rqd->flags = pblk_set_progr_mode(pblk, WRITE);
rqd->private = pblk;
- rqd->end_io = pblk_end_io_write;
+ rqd->end_io = end_io;
rqd->meta_list = nvm_dev_dma_alloc(dev->parent, GFP_KERNEL,
&rqd->dma_meta_list);
@@ -219,11 +236,10 @@ static int pblk_alloc_w_rq(struct pblk *pblk, struct nvm_rq *rqd,
}
static int pblk_setup_w_rq(struct pblk *pblk, struct nvm_rq *rqd,
- struct pblk_c_ctx *c_ctx)
+ struct pblk_c_ctx *c_ctx, struct ppa_addr *erase_ppa)
{
struct pblk_line_meta *lm = &pblk->lm;
- struct pblk_line *e_line = pblk_line_get_data_next(pblk);
- struct ppa_addr erase_ppa;
+ struct pblk_line *e_line = pblk_line_get_erase(pblk);
unsigned int valid = c_ctx->nr_valid;
unsigned int padded = c_ctx->nr_padded;
unsigned int nr_secs = valid + padded;
@@ -231,40 +247,23 @@ static int pblk_setup_w_rq(struct pblk *pblk, struct nvm_rq *rqd,
int ret = 0;
lun_bitmap = kzalloc(lm->lun_bitmap_len, GFP_KERNEL);
- if (!lun_bitmap) {
- ret = -ENOMEM;
- goto out;
- }
+ if (!lun_bitmap)
+ return -ENOMEM;
c_ctx->lun_bitmap = lun_bitmap;
- ret = pblk_alloc_w_rq(pblk, rqd, nr_secs);
+ ret = pblk_alloc_w_rq(pblk, rqd, nr_secs, pblk_end_io_write);
if (ret) {
kfree(lun_bitmap);
- goto out;
+ return ret;
}
- ppa_set_empty(&erase_ppa);
if (likely(!e_line || !atomic_read(&e_line->left_eblks)))
pblk_map_rq(pblk, rqd, c_ctx->sentry, lun_bitmap, valid, 0);
else
pblk_map_erase_rq(pblk, rqd, c_ctx->sentry, lun_bitmap,
- valid, &erase_ppa);
-
-out:
- if (unlikely(e_line && !ppa_empty(erase_ppa))) {
- if (pblk_blk_erase_async(pblk, erase_ppa)) {
- struct nvm_tgt_dev *dev = pblk->dev;
- struct nvm_geo *geo = &dev->geo;
- int bit;
-
- atomic_inc(&e_line->left_eblks);
- bit = erase_ppa.g.lun * geo->nr_chnls + erase_ppa.g.ch;
- WARN_ON(!test_and_clear_bit(bit, e_line->erase_bitmap));
- up(&pblk->erase_sem);
- }
- }
+ valid, erase_ppa);
- return ret;
+ return 0;
}
int pblk_setup_w_rec_rq(struct pblk *pblk, struct nvm_rq *rqd,
@@ -280,7 +279,7 @@ int pblk_setup_w_rec_rq(struct pblk *pblk, struct nvm_rq *rqd,
c_ctx->lun_bitmap = lun_bitmap;
- ret = pblk_alloc_w_rq(pblk, rqd, rqd->nr_ppas);
+ ret = pblk_alloc_w_rq(pblk, rqd, rqd->nr_ppas, pblk_end_io_write);
if (ret)
return ret;
@@ -311,16 +310,237 @@ static int pblk_calc_secs_to_sync(struct pblk *pblk, unsigned int secs_avail,
return secs_to_sync;
}
+static inline int pblk_valid_meta_ppa(struct pblk *pblk,
+ struct pblk_line *meta_line,
+ struct ppa_addr *ppa_list, int nr_ppas)
+{
+ struct nvm_tgt_dev *dev = pblk->dev;
+ struct nvm_geo *geo = &dev->geo;
+ struct pblk_line *data_line;
+ struct ppa_addr ppa, ppa_opt;
+ u64 paddr;
+ int i;
+
+ data_line = &pblk->lines[pblk_dev_ppa_to_line(ppa_list[0])];
+ paddr = pblk_lookup_page(pblk, meta_line);
+ ppa = addr_to_gen_ppa(pblk, paddr, 0);
+
+ if (test_bit(pblk_ppa_to_pos(geo, ppa), data_line->blk_bitmap))
+ return 1;
+
+ /* Schedule a metadata I/O that is half the distance from the data I/O
+ * with regards to the number of LUNs forming the pblk instance. This
+ * balances LUN conflicts across every I/O.
+ *
+ * When the LUN configuration changes (e.g., due to GC), this distance
+ * can align, which would result on a LUN deadlock. In this case, modify
+ * the distance to not be optimal, but allow metadata I/Os to succeed.
+ */
+ ppa_opt = addr_to_gen_ppa(pblk, paddr + data_line->meta_distance, 0);
+ if (unlikely(ppa_opt.ppa == ppa.ppa)) {
+ data_line->meta_distance--;
+ return 0;
+ }
+
+ for (i = 0; i < nr_ppas; i += pblk->min_write_pgs)
+ if (ppa_list[i].g.ch == ppa_opt.g.ch &&
+ ppa_list[i].g.lun == ppa_opt.g.lun)
+ return 1;
+
+ if (test_bit(pblk_ppa_to_pos(geo, ppa_opt), data_line->blk_bitmap)) {
+ for (i = 0; i < nr_ppas; i += pblk->min_write_pgs)
+ if (ppa_list[i].g.ch == ppa.g.ch &&
+ ppa_list[i].g.lun == ppa.g.lun)
+ return 0;
+
+ return 1;
+ }
+
+ return 0;
+}
+
+int pblk_submit_meta_io(struct pblk *pblk, struct pblk_line *meta_line)
+{
+ struct nvm_tgt_dev *dev = pblk->dev;
+ struct nvm_geo *geo = &dev->geo;
+ struct pblk_line_mgmt *l_mg = &pblk->l_mg;
+ struct pblk_line_meta *lm = &pblk->lm;
+ struct pblk_emeta *emeta = meta_line->emeta;
+ struct pblk_g_ctx *m_ctx;
+ struct pblk_lun *rlun;
+ struct bio *bio;
+ struct nvm_rq *rqd;
+ void *data;
+ u64 paddr;
+ int rq_ppas = pblk->min_write_pgs;
+ int id = meta_line->id;
+ int rq_len;
+ int i, j;
+ int ret;
+
+ rqd = pblk_alloc_rqd(pblk, READ);
+ if (IS_ERR(rqd)) {
+ pr_err("pblk: cannot allocate write req.\n");
+ return PTR_ERR(rqd);
+ }
+ m_ctx = nvm_rq_to_pdu(rqd);
+ m_ctx->private = meta_line;
+
+ rq_len = rq_ppas * geo->sec_size;
+ data = ((void *)emeta->buf) + emeta->mem;
+
+ bio = pblk_bio_map_addr(pblk, data, rq_ppas, rq_len,
+ l_mg->emeta_alloc_type, GFP_KERNEL);
+ if (IS_ERR(bio)) {
+ ret = PTR_ERR(bio);
+ goto fail_free_rqd;
+ }
+ bio->bi_iter.bi_sector = 0; /* internal bio */
+ bio_set_op_attrs(bio, REQ_OP_WRITE, 0);
+ rqd->bio = bio;
+
+ ret = pblk_alloc_w_rq(pblk, rqd, rq_ppas, pblk_end_io_write_meta);
+ if (ret)
+ goto fail_free_bio;
+
+ for (i = 0; i < rqd->nr_ppas; ) {
+ spin_lock(&meta_line->lock);
+ paddr = __pblk_alloc_page(pblk, meta_line, rq_ppas);
+ spin_unlock(&meta_line->lock);
+ for (j = 0; j < rq_ppas; j++, i++, paddr++)
+ rqd->ppa_list[i] = addr_to_gen_ppa(pblk, paddr, id);
+ }
+
+ rlun = &pblk->luns[pblk_ppa_to_pos(geo, rqd->ppa_list[0])];
+ ret = down_timeout(&rlun->wr_sem, msecs_to_jiffies(5000));
+ if (ret) {
+ pr_err("pblk: lun semaphore timed out (%d)\n", ret);
+ goto fail_free_bio;
+ }
+
+ emeta->mem += rq_len;
+ if (emeta->mem >= lm->emeta_len[0]) {
+ spin_lock(&l_mg->close_lock);
+ list_del(&meta_line->list);
+ WARN(!bitmap_full(meta_line->map_bitmap, lm->sec_per_line),
+ "pblk: corrupt meta line %d\n", meta_line->id);
+ spin_unlock(&l_mg->close_lock);
+ }
+
+ ret = pblk_submit_io(pblk, rqd);
+ if (ret) {
+ pr_err("pblk: emeta I/O submission failed: %d\n", ret);
+ goto fail_rollback;
+ }
+
+ return NVM_IO_OK;
+
+fail_rollback:
+ spin_lock(&l_mg->close_lock);
+ pblk_dealloc_page(pblk, meta_line, rq_ppas);
+ list_add(&meta_line->list, &meta_line->list);
+ spin_unlock(&l_mg->close_lock);
+fail_free_bio:
+ if (likely(l_mg->emeta_alloc_type == PBLK_VMALLOC_META))
+ bio_put(bio);
+fail_free_rqd:
+ pblk_free_rqd(pblk, rqd, READ);
+ return ret;
+}
+
+static int pblk_sched_meta_io(struct pblk *pblk, struct ppa_addr *prev_list,
+ int prev_n)
+{
+ struct pblk_line_meta *lm = &pblk->lm;
+ struct pblk_line_mgmt *l_mg = &pblk->l_mg;
+ struct pblk_line *meta_line;
+
+ spin_lock(&l_mg->close_lock);
+retry:
+ if (list_empty(&l_mg->emeta_list)) {
+ spin_unlock(&l_mg->close_lock);
+ return 0;
+ }
+ meta_line = list_first_entry(&l_mg->emeta_list, struct pblk_line, list);
+ if (bitmap_full(meta_line->map_bitmap, lm->sec_per_line))
+ goto retry;
+ spin_unlock(&l_mg->close_lock);
+
+ if (!pblk_valid_meta_ppa(pblk, meta_line, prev_list, prev_n))
+ return 0;
+
+ return pblk_submit_meta_io(pblk, meta_line);
+}
+
+static int pblk_submit_io_set(struct pblk *pblk, struct nvm_rq *rqd)
+{
+ struct pblk_c_ctx *c_ctx = nvm_rq_to_pdu(rqd);
+ struct ppa_addr erase_ppa;
+ int err;
+
+ ppa_set_empty(&erase_ppa);
+
+ /* Assign lbas to ppas and populate request structure */
+ err = pblk_setup_w_rq(pblk, rqd, c_ctx, &erase_ppa);
+ if (err) {
+ pr_err("pblk: could not setup write request: %d\n", err);
+ return NVM_IO_ERR;
+ }
+
+ if (likely(ppa_empty(erase_ppa))) {
+ /* Submit metadata write for previous data line */
+ err = pblk_sched_meta_io(pblk, rqd->ppa_list, rqd->nr_ppas);
+ if (err) {
+ pr_err("pblk: metadata I/O submission failed: %d", err);
+ return NVM_IO_ERR;
+ }
+
+ /* Submit data write for current data line */
+ err = pblk_submit_io(pblk, rqd);
+ if (err) {
+ pr_err("pblk: data I/O submission failed: %d\n", err);
+ return NVM_IO_ERR;
+ }
+ } else {
+ /* Submit data write for current data line */
+ err = pblk_submit_io(pblk, rqd);
+ if (err) {
+ pr_err("pblk: data I/O submission failed: %d\n", err);
+ return NVM_IO_ERR;
+ }
+
+ /* Submit available erase for next data line */
+ if (pblk_blk_erase_async(pblk, erase_ppa)) {
+ struct pblk_line *e_line = pblk_line_get_erase(pblk);
+ struct nvm_tgt_dev *dev = pblk->dev;
+ struct nvm_geo *geo = &dev->geo;
+ int bit;
+
+ atomic_inc(&e_line->left_eblks);
+ bit = pblk_ppa_to_pos(geo, erase_ppa);
+ WARN_ON(!test_and_clear_bit(bit, e_line->erase_bitmap));
+ }
+ }
+
+ return NVM_IO_OK;
+}
+
+static void pblk_free_write_rqd(struct pblk *pblk, struct nvm_rq *rqd)
+{
+ struct pblk_c_ctx *c_ctx = nvm_rq_to_pdu(rqd);
+ struct bio *bio = rqd->bio;
+
+ if (c_ctx->nr_padded)
+ pblk_bio_free_pages(pblk, bio, rqd->nr_ppas, c_ctx->nr_padded);
+}
+
static int pblk_submit_write(struct pblk *pblk)
{
struct bio *bio;
struct nvm_rq *rqd;
- struct pblk_c_ctx *c_ctx;
- unsigned int pgs_read;
unsigned int secs_avail, secs_to_sync, secs_to_com;
unsigned int secs_to_flush;
unsigned long pos;
- int err;
/* If there are no sectors in the cache, flushes (bios without data)
* will be cleared on the cache threads
@@ -338,7 +558,6 @@ static int pblk_submit_write(struct pblk *pblk)
pr_err("pblk: cannot allocate write req.\n");
return 1;
}
- c_ctx = nvm_rq_to_pdu(rqd);
bio = bio_alloc(GFP_KERNEL, pblk->max_write_pgs);
if (!bio) {
@@ -358,29 +577,14 @@ static int pblk_submit_write(struct pblk *pblk)
secs_to_com = (secs_to_sync > secs_avail) ? secs_avail : secs_to_sync;
pos = pblk_rb_read_commit(&pblk->rwb, secs_to_com);
- pgs_read = pblk_rb_read_to_bio(&pblk->rwb, bio, c_ctx, pos,
- secs_to_sync, secs_avail);
- if (!pgs_read) {
+ if (pblk_rb_read_to_bio(&pblk->rwb, rqd, bio, pos, secs_to_sync,
+ secs_avail)) {
pr_err("pblk: corrupted write bio\n");
goto fail_put_bio;
}
- if (c_ctx->nr_padded)
- if (pblk_bio_add_pages(pblk, bio, GFP_KERNEL, c_ctx->nr_padded))
- goto fail_put_bio;
-
- /* Assign lbas to ppas and populate request structure */
- err = pblk_setup_w_rq(pblk, rqd, c_ctx);
- if (err) {
- pr_err("pblk: could not setup write request\n");
- goto fail_free_bio;
- }
-
- err = pblk_submit_io(pblk, rqd);
- if (err) {
- pr_err("pblk: I/O submission failed: %d\n", err);
+ if (pblk_submit_io_set(pblk, rqd))
goto fail_free_bio;
- }
#ifdef CONFIG_NVM_DEBUG
atomic_long_add(secs_to_sync, &pblk->sub_writes);
@@ -389,8 +593,7 @@ static int pblk_submit_write(struct pblk *pblk)
return 0;
fail_free_bio:
- if (c_ctx->nr_padded)
- pblk_bio_free_pages(pblk, bio, secs_to_sync, c_ctx->nr_padded);
+ pblk_free_write_rqd(pblk, rqd);
fail_put_bio:
bio_put(bio);
fail_free_rqd:
diff --git a/drivers/lightnvm/pblk.h b/drivers/lightnvm/pblk.h
index 99f3186b5288..15931381348c 100644
--- a/drivers/lightnvm/pblk.h
+++ b/drivers/lightnvm/pblk.h
@@ -40,6 +40,12 @@
#define PBLK_MAX_REQ_ADDRS (64)
#define PBLK_MAX_REQ_ADDRS_PW (6)
+#define PBLK_WS_POOL_SIZE (128)
+#define PBLK_META_POOL_SIZE (128)
+#define PBLK_READ_REQ_POOL_SIZE (1024)
+
+#define PBLK_NR_CLOSE_JOBS (4)
+
#define PBLK_CACHE_NAME_LEN (DISK_NAME_LEN + 16)
#define PBLK_COMMAND_TIMEOUT_MS 30000
@@ -72,11 +78,15 @@ enum {
PBLK_BLK_ST_CLOSED = 0x2,
};
+struct pblk_sec_meta {
+ u64 reserved;
+ __le64 lba;
+};
+
/* The number of GC lists and the rate-limiter states go together. This way the
* rate-limiter can dictate how much GC is needed based on resource utilization.
*/
-#define PBLK_NR_GC_LISTS 3
-#define PBLK_MAX_GC_JOBS 32
+#define PBLK_GC_NR_LISTS 3
enum {
PBLK_RL_HIGH = 1,
@@ -84,14 +94,9 @@ enum {
PBLK_RL_LOW = 3,
};
-struct pblk_sec_meta {
- u64 reserved;
- __le64 lba;
-};
-
#define pblk_dma_meta_size (sizeof(struct pblk_sec_meta) * PBLK_MAX_REQ_ADDRS)
-/* write completion context */
+/* write buffer completion context */
struct pblk_c_ctx {
struct list_head list; /* Head for out-of-order completion */
@@ -101,9 +106,16 @@ struct pblk_c_ctx {
unsigned int nr_padded;
};
-/* Read context */
-struct pblk_r_ctx {
- struct bio *orig_bio;
+/* generic context */
+struct pblk_g_ctx {
+ void *private;
+};
+
+/* Pad context */
+struct pblk_pad_rq {
+ struct pblk *pblk;
+ struct completion wait;
+ struct kref ref;
};
/* Recovery context */
@@ -195,29 +207,39 @@ struct pblk_lun {
struct pblk_gc_rq {
struct pblk_line *line;
void *data;
- u64 *lba_list;
+ u64 lba_list[PBLK_MAX_REQ_ADDRS];
int nr_secs;
int secs_to_gc;
struct list_head list;
};
struct pblk_gc {
+ /* These states are not protected by a lock since (i) they are in the
+ * fast path, and (ii) they are not critical.
+ */
int gc_active;
int gc_enabled;
int gc_forced;
- int gc_jobs_active;
- atomic_t inflight_gc;
struct task_struct *gc_ts;
struct task_struct *gc_writer_ts;
+ struct task_struct *gc_reader_ts;
+
+ struct workqueue_struct *gc_line_reader_wq;
struct workqueue_struct *gc_reader_wq;
+
struct timer_list gc_timer;
+ struct semaphore gc_sem;
+ atomic_t inflight_gc;
int w_entries;
+
struct list_head w_list;
+ struct list_head r_list;
spinlock_t lock;
spinlock_t w_lock;
+ spinlock_t r_lock;
};
struct pblk_rl {
@@ -229,10 +251,8 @@ struct pblk_rl {
*/
unsigned int high_pw; /* High rounded up as a power of 2 */
-#define PBLK_USER_HIGH_THRS 2 /* Begin write limit at 50 percent
- * available blks
- */
-#define PBLK_USER_LOW_THRS 20 /* Aggressive GC at 5% available blocks */
+#define PBLK_USER_HIGH_THRS 8 /* Begin write limit at 12% available blks */
+#define PBLK_USER_LOW_THRS 10 /* Aggressive GC at 10% available blocks */
int rb_windows_pw; /* Number of rate windows in the write buffer
* given as a power-of-2. This guarantees that
@@ -244,13 +264,19 @@ struct pblk_rl {
*/
int rb_budget; /* Total number of entries available for I/O */
int rb_user_max; /* Max buffer entries available for user I/O */
- atomic_t rb_user_cnt; /* User I/O buffer counter */
int rb_gc_max; /* Max buffer entries available for GC I/O */
int rb_gc_rsv; /* Reserved buffer entries for GC I/O */
int rb_state; /* Rate-limiter current state */
+
+ atomic_t rb_user_cnt; /* User I/O buffer counter */
atomic_t rb_gc_cnt; /* GC I/O buffer counter */
+ atomic_t rb_space; /* Space limit in case of reaching capacity */
+
+ int rsv_blocks; /* Reserved blocks for GC */
int rb_user_active;
+ int rb_gc_active;
+
struct timer_list u_timer;
unsigned long long nr_secs;
@@ -258,8 +284,6 @@ struct pblk_rl {
atomic_t free_blocks;
};
-#define PBLK_LINE_NR_LUN_BITMAP 2
-#define PBLK_LINE_NR_SEC_BITMAP 2
#define PBLK_LINE_EMPTY (~0U)
enum {
@@ -310,16 +334,19 @@ struct line_smeta {
__le32 window_wr_lun; /* Number of parallel LUNs to write */
__le32 rsvd[2];
+
+ __le64 lun_bitmap[];
};
/*
- * Metadata Layout:
- * 1. struct pblk_emeta
- * 2. nr_lbas u64 forming lba list
- * 3. nr_lines (all) u32 valid sector count (vsc) (~0U: non-alloc line)
- * 4. nr_luns bits (u64 format) forming line bad block bitmap
- *
- * 3. and 4. will be part of FTL log
+ * Metadata layout in media:
+ * First sector:
+ * 1. struct line_emeta
+ * 2. bad block bitmap (u64 * window_wr_lun)
+ * Mid sectors (start at lbas_sector):
+ * 3. nr_lbas (u64) forming lba list
+ * Last sectors (start at vsc_sector):
+ * 4. u32 valid sector count (vsc) for all lines (~0U: free line)
*/
struct line_emeta {
struct line_header header;
@@ -339,6 +366,23 @@ struct line_emeta {
__le32 next_id; /* Line id for next line */
__le64 nr_lbas; /* Number of lbas mapped in line */
__le64 nr_valid_lbas; /* Number of valid lbas mapped in line */
+ __le64 bb_bitmap[]; /* Updated bad block bitmap for line */
+};
+
+struct pblk_emeta {
+ struct line_emeta *buf; /* emeta buffer in media format */
+ int mem; /* Write offset - points to next
+ * writable entry in memory
+ */
+ atomic_t sync; /* Synced - backpointer that signals the
+ * last entry that has been successfully
+ * persisted to media
+ */
+ unsigned int nr_entries; /* Number of emeta entries */
+};
+
+struct pblk_smeta {
+ struct line_smeta *buf; /* smeta buffer in persistent format */
};
struct pblk_line {
@@ -355,9 +399,12 @@ struct pblk_line {
unsigned long *lun_bitmap; /* Bitmap for LUNs mapped in line */
- struct line_smeta *smeta; /* Start metadata */
- struct line_emeta *emeta; /* End metadata */
+ struct pblk_smeta *smeta; /* Start metadata */
+ struct pblk_emeta *emeta; /* End medatada */
+
int meta_line; /* Metadata line id */
+ int meta_distance; /* Distance between data and metadata */
+
u64 smeta_ssec; /* Sector where smeta starts */
u64 emeta_ssec; /* Sector where emeta starts */
@@ -374,9 +421,10 @@ struct pblk_line {
atomic_t left_seblks; /* Blocks left for sync erasing */
int left_msecs; /* Sectors left for mapping */
- int left_ssecs; /* Sectors left to sync */
unsigned int cur_sec; /* Sector map pointer */
- unsigned int vsc; /* Valid sector count in line */
+ unsigned int nr_valid_lbas; /* Number of valid lbas in line */
+
+ __le32 *vsc; /* Valid sector count in line */
struct kref ref; /* Write buffer L2P references */
@@ -385,13 +433,15 @@ struct pblk_line {
#define PBLK_DATA_LINES 4
-enum{
+enum {
PBLK_KMALLOC_META = 1,
PBLK_VMALLOC_META = 2,
};
-struct pblk_line_metadata {
- void *meta;
+enum {
+ PBLK_EMETA_TYPE_HEADER = 1, /* struct line_emeta first sector */
+ PBLK_EMETA_TYPE_LLBA = 2, /* lba list - type: __le64 */
+ PBLK_EMETA_TYPE_VSC = 3, /* vsc list - type: __le32 */
};
struct pblk_line_mgmt {
@@ -404,7 +454,7 @@ struct pblk_line_mgmt {
struct list_head bad_list; /* Full lines bad */
/* GC lists - use gc_lock */
- struct list_head *gc_lists[PBLK_NR_GC_LISTS];
+ struct list_head *gc_lists[PBLK_GC_NR_LISTS];
struct list_head gc_high_list; /* Full lines ready to GC, high isc */
struct list_head gc_mid_list; /* Full lines ready to GC, mid isc */
struct list_head gc_low_list; /* Full lines ready to GC, low isc */
@@ -417,13 +467,16 @@ struct pblk_line_mgmt {
struct pblk_line *log_next; /* Next FTL log line */
struct pblk_line *data_next; /* Next data line */
+ struct list_head emeta_list; /* Lines queued to schedule emeta */
+
+ __le32 *vsc_list; /* Valid sector counts for all lines */
+
/* Metadata allocation type: VMALLOC | KMALLOC */
- int smeta_alloc_type;
int emeta_alloc_type;
/* Pre-allocated metadata for data lines */
- struct pblk_line_metadata sline_meta[PBLK_DATA_LINES];
- struct pblk_line_metadata eline_meta[PBLK_DATA_LINES];
+ struct pblk_smeta *sline_meta[PBLK_DATA_LINES];
+ struct pblk_emeta *eline_meta[PBLK_DATA_LINES];
unsigned long meta_bitmap;
/* Helpers for fast bitmap calculations */
@@ -434,25 +487,40 @@ struct pblk_line_mgmt {
unsigned long l_seq_nr; /* Log line unique sequence number */
spinlock_t free_lock;
+ spinlock_t close_lock;
spinlock_t gc_lock;
};
struct pblk_line_meta {
unsigned int smeta_len; /* Total length for smeta */
- unsigned int smeta_sec; /* Sectors needed for smeta*/
- unsigned int emeta_len; /* Total length for emeta */
- unsigned int emeta_sec; /* Sectors needed for emeta*/
+ unsigned int smeta_sec; /* Sectors needed for smeta */
+
+ unsigned int emeta_len[4]; /* Lengths for emeta:
+ * [0]: Total length
+ * [1]: struct line_emeta length
+ * [2]: L2P portion length
+ * [3]: vsc list length
+ */
+ unsigned int emeta_sec[4]; /* Sectors needed for emeta. Same layout
+ * as emeta_len
+ */
+
unsigned int emeta_bb; /* Boundary for bb that affects emeta */
+
+ unsigned int vsc_list_len; /* Length for vsc list */
unsigned int sec_bitmap_len; /* Length for sector bitmap in line */
unsigned int blk_bitmap_len; /* Length for block bitmap in line */
unsigned int lun_bitmap_len; /* Length for lun bitmap in line */
unsigned int blk_per_line; /* Number of blocks in a full line */
unsigned int sec_per_line; /* Number of sectors in a line */
+ unsigned int dsec_per_line; /* Number of data sectors in a line */
unsigned int min_blk_line; /* Min. number of good blocks in line */
unsigned int mid_thrs; /* Threshold for GC mid list */
unsigned int high_thrs; /* Threshold for GC high list */
+
+ unsigned int meta_distance; /* Distance between data and metadata */
};
struct pblk_addr_format {
@@ -470,6 +538,13 @@ struct pblk_addr_format {
u8 sec_offset;
};
+enum {
+ PBLK_STATE_RUNNING = 0,
+ PBLK_STATE_STOPPING = 1,
+ PBLK_STATE_RECOVERING = 2,
+ PBLK_STATE_STOPPED = 3,
+};
+
struct pblk {
struct nvm_tgt_dev *dev;
struct gendisk *disk;
@@ -487,6 +562,8 @@ struct pblk {
struct pblk_rb rwb;
+ int state; /* pblk line state */
+
int min_write_pgs; /* Minimum amount of pages required by controller */
int max_write_pgs; /* Maximum amount of pages supported by controller */
int pgs_in_buffer; /* Number of pages that need to be held in buffer to
@@ -499,7 +576,7 @@ struct pblk {
/* pblk provisioning values. Used by rate limiter */
struct pblk_rl rl;
- struct semaphore erase_sem;
+ int sec_per_write;
unsigned char instance_uuid[16];
#ifdef CONFIG_NVM_DEBUG
@@ -511,8 +588,8 @@ struct pblk {
atomic_long_t req_writes; /* Sectors stored on write buffer */
atomic_long_t sub_writes; /* Sectors submitted from buffer */
atomic_long_t sync_writes; /* Sectors synced to media */
- atomic_long_t compl_writes; /* Sectors completed in write bio */
atomic_long_t inflight_reads; /* Inflight sector read requests */
+ atomic_long_t cache_reads; /* Read requests that hit the cache */
atomic_long_t sync_reads; /* Completed sector read requests */
atomic_long_t recov_writes; /* Sectors submitted from recovery */
atomic_long_t recov_gc_writes; /* Sectors submitted from write GC */
@@ -528,6 +605,8 @@ struct pblk {
atomic_long_t write_failed;
atomic_long_t erase_failed;
+ atomic_t inflight_io; /* General inflight I/O counter */
+
struct task_struct *writer_ts;
/* Simple translation map of logical addresses to physical addresses.
@@ -542,11 +621,13 @@ struct pblk {
mempool_t *page_pool;
mempool_t *line_ws_pool;
mempool_t *rec_pool;
- mempool_t *r_rq_pool;
+ mempool_t *g_rq_pool;
mempool_t *w_rq_pool;
mempool_t *line_meta_pool;
- struct workqueue_struct *kw_wq;
+ struct workqueue_struct *close_wq;
+ struct workqueue_struct *bb_wq;
+
struct timer_list wtimer;
struct pblk_gc gc;
@@ -559,7 +640,7 @@ struct pblk_line_ws {
struct work_struct ws;
};
-#define pblk_r_rq_size (sizeof(struct nvm_rq) + sizeof(struct pblk_r_ctx))
+#define pblk_g_rq_size (sizeof(struct nvm_rq) + sizeof(struct pblk_g_ctx))
#define pblk_w_rq_size (sizeof(struct nvm_rq) + sizeof(struct pblk_c_ctx))
/*
@@ -579,18 +660,17 @@ void pblk_rb_write_entry_gc(struct pblk_rb *rb, void *data,
struct pblk_w_ctx w_ctx, struct pblk_line *gc_line,
unsigned int pos);
struct pblk_w_ctx *pblk_rb_w_ctx(struct pblk_rb *rb, unsigned int pos);
+void pblk_rb_flush(struct pblk_rb *rb);
void pblk_rb_sync_l2p(struct pblk_rb *rb);
-unsigned int pblk_rb_read_to_bio(struct pblk_rb *rb, struct bio *bio,
- struct pblk_c_ctx *c_ctx,
- unsigned int pos,
- unsigned int nr_entries,
- unsigned int count);
+unsigned int pblk_rb_read_to_bio(struct pblk_rb *rb, struct nvm_rq *rqd,
+ struct bio *bio, unsigned int pos,
+ unsigned int nr_entries, unsigned int count);
unsigned int pblk_rb_read_to_bio_list(struct pblk_rb *rb, struct bio *bio,
struct list_head *list,
unsigned int max);
int pblk_rb_copy_to_bio(struct pblk_rb *rb, struct bio *bio, sector_t lba,
- u64 pos, int bio_iter);
+ struct ppa_addr ppa, int bio_iter);
unsigned int pblk_rb_read_commit(struct pblk_rb *rb, unsigned int entries);
unsigned int pblk_rb_sync_init(struct pblk_rb *rb, unsigned long *flags);
@@ -601,6 +681,7 @@ void pblk_rb_sync_end(struct pblk_rb *rb, unsigned long *flags);
unsigned int pblk_rb_sync_point_count(struct pblk_rb *rb);
unsigned int pblk_rb_read_count(struct pblk_rb *rb);
+unsigned int pblk_rb_sync_count(struct pblk_rb *rb);
unsigned int pblk_rb_wrap_pos(struct pblk_rb *rb, unsigned int pos);
int pblk_rb_tear_down_check(struct pblk_rb *rb);
@@ -612,40 +693,50 @@ ssize_t pblk_rb_sysfs(struct pblk_rb *rb, char *buf);
* pblk core
*/
struct nvm_rq *pblk_alloc_rqd(struct pblk *pblk, int rw);
+void pblk_set_sec_per_write(struct pblk *pblk, int sec_per_write);
int pblk_setup_w_rec_rq(struct pblk *pblk, struct nvm_rq *rqd,
struct pblk_c_ctx *c_ctx);
void pblk_free_rqd(struct pblk *pblk, struct nvm_rq *rqd, int rw);
-void pblk_flush_writer(struct pblk *pblk);
+void pblk_wait_for_meta(struct pblk *pblk);
struct ppa_addr pblk_get_lba_map(struct pblk *pblk, sector_t lba);
void pblk_discard(struct pblk *pblk, struct bio *bio);
void pblk_log_write_err(struct pblk *pblk, struct nvm_rq *rqd);
void pblk_log_read_err(struct pblk *pblk, struct nvm_rq *rqd);
int pblk_submit_io(struct pblk *pblk, struct nvm_rq *rqd);
+int pblk_submit_meta_io(struct pblk *pblk, struct pblk_line *meta_line);
struct bio *pblk_bio_map_addr(struct pblk *pblk, void *data,
unsigned int nr_secs, unsigned int len,
- gfp_t gfp_mask);
+ int alloc_type, gfp_t gfp_mask);
struct pblk_line *pblk_line_get(struct pblk *pblk);
struct pblk_line *pblk_line_get_first_data(struct pblk *pblk);
-struct pblk_line *pblk_line_replace_data(struct pblk *pblk);
+void pblk_line_replace_data(struct pblk *pblk);
int pblk_line_recov_alloc(struct pblk *pblk, struct pblk_line *line);
void pblk_line_recov_close(struct pblk *pblk, struct pblk_line *line);
struct pblk_line *pblk_line_get_data(struct pblk *pblk);
-struct pblk_line *pblk_line_get_data_next(struct pblk *pblk);
+struct pblk_line *pblk_line_get_erase(struct pblk *pblk);
int pblk_line_erase(struct pblk *pblk, struct pblk_line *line);
int pblk_line_is_full(struct pblk_line *line);
void pblk_line_free(struct pblk *pblk, struct pblk_line *line);
-void pblk_line_close_ws(struct work_struct *work);
+void pblk_line_close_meta(struct pblk *pblk, struct pblk_line *line);
void pblk_line_close(struct pblk *pblk, struct pblk_line *line);
+void pblk_line_close_meta_sync(struct pblk *pblk);
+void pblk_line_close_ws(struct work_struct *work);
+void pblk_pipeline_stop(struct pblk *pblk);
void pblk_line_mark_bb(struct work_struct *work);
void pblk_line_run_ws(struct pblk *pblk, struct pblk_line *line, void *priv,
- void (*work)(struct work_struct *));
+ void (*work)(struct work_struct *),
+ struct workqueue_struct *wq);
u64 pblk_line_smeta_start(struct pblk *pblk, struct pblk_line *line);
int pblk_line_read_smeta(struct pblk *pblk, struct pblk_line *line);
-int pblk_line_read_emeta(struct pblk *pblk, struct pblk_line *line);
+int pblk_line_read_emeta(struct pblk *pblk, struct pblk_line *line,
+ void *emeta_buf);
int pblk_blk_erase_async(struct pblk *pblk, struct ppa_addr erase_ppa);
void pblk_line_put(struct kref *ref);
struct list_head *pblk_line_gc_list(struct pblk *pblk, struct pblk_line *line);
+u64 pblk_lookup_page(struct pblk *pblk, struct pblk_line *line);
+void pblk_dealloc_page(struct pblk *pblk, struct pblk_line *line, int nr_secs);
u64 pblk_alloc_page(struct pblk *pblk, struct pblk_line *line, int nr_secs);
+u64 __pblk_alloc_page(struct pblk *pblk, struct pblk_line *line, int nr_secs);
int pblk_calc_secs(struct pblk *pblk, unsigned long secs_avail,
unsigned long secs_to_flush);
void pblk_down_rq(struct pblk *pblk, struct ppa_addr *ppa_list, int nr_ppas,
@@ -656,11 +747,11 @@ void pblk_end_bio_sync(struct bio *bio);
void pblk_end_io_sync(struct nvm_rq *rqd);
int pblk_bio_add_pages(struct pblk *pblk, struct bio *bio, gfp_t flags,
int nr_pages);
-void pblk_map_pad_invalidate(struct pblk *pblk, struct pblk_line *line,
- u64 paddr);
void pblk_bio_free_pages(struct pblk *pblk, struct bio *bio, int off,
int nr_pages);
void pblk_map_invalidate(struct pblk *pblk, struct ppa_addr ppa);
+void __pblk_map_invalidate(struct pblk *pblk, struct pblk_line *line,
+ u64 paddr);
void pblk_update_map(struct pblk *pblk, sector_t lba, struct ppa_addr ppa);
void pblk_update_map_cache(struct pblk *pblk, sector_t lba,
struct ppa_addr ppa);
@@ -702,6 +793,7 @@ void pblk_write_should_kick(struct pblk *pblk);
/*
* pblk read path
*/
+extern struct bio_set *pblk_bio_set;
int pblk_submit_read(struct pblk *pblk, struct bio *bio);
int pblk_submit_read_gc(struct pblk *pblk, u64 *lba_list, void *data,
unsigned int nr_secs, unsigned int *secs_to_gc,
@@ -711,7 +803,7 @@ int pblk_submit_read_gc(struct pblk *pblk, u64 *lba_list, void *data,
*/
void pblk_submit_rec(struct work_struct *work);
struct pblk_line *pblk_recov_l2p(struct pblk *pblk);
-void pblk_recov_pad(struct pblk *pblk);
+int pblk_recov_pad(struct pblk *pblk);
__le64 *pblk_recov_get_lba_list(struct pblk *pblk, struct line_emeta *emeta);
int pblk_recov_setup_rq(struct pblk *pblk, struct pblk_c_ctx *c_ctx,
struct pblk_rec_ctx *recovery, u64 *comp_bits,
@@ -720,33 +812,40 @@ int pblk_recov_setup_rq(struct pblk *pblk, struct pblk_c_ctx *c_ctx,
/*
* pblk gc
*/
-#define PBLK_GC_TRIES 3
+#define PBLK_GC_MAX_READERS 8 /* Max number of outstanding GC reader jobs */
+#define PBLK_GC_W_QD 128 /* Queue depth for inflight GC write I/Os */
+#define PBLK_GC_L_QD 4 /* Queue depth for inflight GC lines */
+#define PBLK_GC_RSV_LINE 1 /* Reserved lines for GC */
int pblk_gc_init(struct pblk *pblk);
void pblk_gc_exit(struct pblk *pblk);
void pblk_gc_should_start(struct pblk *pblk);
void pblk_gc_should_stop(struct pblk *pblk);
-int pblk_gc_status(struct pblk *pblk);
+void pblk_gc_should_kick(struct pblk *pblk);
+void pblk_gc_kick(struct pblk *pblk);
void pblk_gc_sysfs_state_show(struct pblk *pblk, int *gc_enabled,
int *gc_active);
-void pblk_gc_sysfs_force(struct pblk *pblk, int force);
+int pblk_gc_sysfs_force(struct pblk *pblk, int force);
/*
* pblk rate limiter
*/
void pblk_rl_init(struct pblk_rl *rl, int budget);
void pblk_rl_free(struct pblk_rl *rl);
-int pblk_rl_gc_thrs(struct pblk_rl *rl);
+int pblk_rl_high_thrs(struct pblk_rl *rl);
+int pblk_rl_low_thrs(struct pblk_rl *rl);
unsigned long pblk_rl_nr_free_blks(struct pblk_rl *rl);
int pblk_rl_user_may_insert(struct pblk_rl *rl, int nr_entries);
+void pblk_rl_inserted(struct pblk_rl *rl, int nr_entries);
void pblk_rl_user_in(struct pblk_rl *rl, int nr_entries);
int pblk_rl_gc_may_insert(struct pblk_rl *rl, int nr_entries);
void pblk_rl_gc_in(struct pblk_rl *rl, int nr_entries);
void pblk_rl_out(struct pblk_rl *rl, int nr_user, int nr_gc);
-void pblk_rl_set_gc_rsc(struct pblk_rl *rl, int rsv);
int pblk_rl_sysfs_rate_show(struct pblk_rl *rl);
void pblk_rl_free_lines_inc(struct pblk_rl *rl, struct pblk_line *line);
void pblk_rl_free_lines_dec(struct pblk_rl *rl, struct pblk_line *line);
+void pblk_rl_set_space_limit(struct pblk_rl *rl, int entries_left);
+int pblk_rl_is_limit(struct pblk_rl *rl);
/*
* pblk sysfs
@@ -774,9 +873,30 @@ static inline struct nvm_rq *nvm_rq_from_c_ctx(void *c_ctx)
return c_ctx - sizeof(struct nvm_rq);
}
-static inline void *pblk_line_emeta_to_lbas(struct line_emeta *emeta)
+static inline void *emeta_to_bb(struct line_emeta *emeta)
+{
+ return emeta->bb_bitmap;
+}
+
+static inline void *emeta_to_lbas(struct pblk *pblk, struct line_emeta *emeta)
+{
+ return ((void *)emeta + pblk->lm.emeta_len[1]);
+}
+
+static inline void *emeta_to_vsc(struct pblk *pblk, struct line_emeta *emeta)
{
- return (emeta) + 1;
+ return (emeta_to_lbas(pblk, emeta) + pblk->lm.emeta_len[2]);
+}
+
+static inline int pblk_line_vsc(struct pblk_line *line)
+{
+ int vsc;
+
+ spin_lock(&line->lock);
+ vsc = le32_to_cpu(*line->vsc);
+ spin_unlock(&line->lock);
+
+ return vsc;
}
#define NVM_MEM_PAGE_WRITE (8)
@@ -917,6 +1037,14 @@ static inline void pblk_ppa_set_empty(struct ppa_addr *ppa_addr)
ppa_addr->ppa = ADDR_EMPTY;
}
+static inline bool pblk_ppa_comp(struct ppa_addr lppa, struct ppa_addr rppa)
+{
+ if (lppa.ppa == rppa.ppa)
+ return true;
+
+ return false;
+}
+
static inline int pblk_addr_in_cache(struct ppa_addr ppa)
{
return (ppa.ppa != ADDR_EMPTY && ppa.c.is_cached);
@@ -964,11 +1092,11 @@ static inline struct ppa_addr addr_to_pblk_ppa(struct pblk *pblk, u64 paddr,
}
static inline u32 pblk_calc_meta_header_crc(struct pblk *pblk,
- struct line_smeta *smeta)
+ struct line_header *header)
{
u32 crc = ~(u32)0;
- crc = crc32_le(crc, (unsigned char *)smeta + sizeof(crc),
+ crc = crc32_le(crc, (unsigned char *)header + sizeof(crc),
sizeof(struct line_header) - sizeof(crc));
return crc;
@@ -996,7 +1124,7 @@ static inline u32 pblk_calc_emeta_crc(struct pblk *pblk,
crc = crc32_le(crc, (unsigned char *)emeta +
sizeof(struct line_header) + sizeof(crc),
- lm->emeta_len -
+ lm->emeta_len[0] -
sizeof(struct line_header) - sizeof(crc));
return crc;
@@ -1016,9 +1144,27 @@ static inline int pblk_set_progr_mode(struct pblk *pblk, int type)
return flags;
}
-static inline int pblk_set_read_mode(struct pblk *pblk)
+enum {
+ PBLK_READ_RANDOM = 0,
+ PBLK_READ_SEQUENTIAL = 1,
+};
+
+static inline int pblk_set_read_mode(struct pblk *pblk, int type)
+{
+ struct nvm_tgt_dev *dev = pblk->dev;
+ struct nvm_geo *geo = &dev->geo;
+ int flags;
+
+ flags = NVM_IO_SUSPEND | NVM_IO_SCRAMBLE_ENABLE;
+ if (type == PBLK_READ_SEQUENTIAL)
+ flags |= geo->plane_mode >> 1;
+
+ return flags;
+}
+
+static inline int pblk_io_aligned(struct pblk *pblk, int nr_secs)
{
- return NVM_IO_SNGL_ACCESS | NVM_IO_SUSPEND | NVM_IO_SCRAMBLE_ENABLE;
+ return !(nr_secs % pblk->min_write_pgs);
}
#ifdef CONFIG_NVM_DEBUG
diff --git a/drivers/lightnvm/rrpc.c b/drivers/lightnvm/rrpc.c
index cf0e28a0ff61..267f01ae87e4 100644
--- a/drivers/lightnvm/rrpc.c
+++ b/drivers/lightnvm/rrpc.c
@@ -279,8 +279,8 @@ static void rrpc_end_sync_bio(struct bio *bio)
{
struct completion *waiting = bio->bi_private;
- if (bio->bi_error)
- pr_err("nvm: gc request failed (%u).\n", bio->bi_error);
+ if (bio->bi_status)
+ pr_err("nvm: gc request failed (%u).\n", bio->bi_status);
complete(waiting);
}
@@ -359,7 +359,7 @@ try:
goto finished;
}
wait_for_completion_io(&wait);
- if (bio->bi_error) {
+ if (bio->bi_status) {
rrpc_inflight_laddr_release(rrpc, rqd);
goto finished;
}
@@ -385,7 +385,7 @@ try:
wait_for_completion_io(&wait);
rrpc_inflight_laddr_release(rrpc, rqd);
- if (bio->bi_error)
+ if (bio->bi_status)
goto finished;
bio_reset(bio);
@@ -994,7 +994,7 @@ static blk_qc_t rrpc_make_rq(struct request_queue *q, struct bio *bio)
struct nvm_rq *rqd;
int err;
- blk_queue_split(q, &bio, q->bio_split);
+ blk_queue_split(q, &bio);
if (bio_op(bio) == REQ_OP_DISCARD) {
rrpc_discard(rrpc, bio);
diff --git a/drivers/md/bcache/bcache.h b/drivers/md/bcache/bcache.h
index c3ea03c9a1a8..dee542fff68e 100644
--- a/drivers/md/bcache/bcache.h
+++ b/drivers/md/bcache/bcache.h
@@ -849,10 +849,11 @@ static inline void wake_up_allocators(struct cache_set *c)
/* Forward declarations */
-void bch_count_io_errors(struct cache *, int, const char *);
+void bch_count_io_errors(struct cache *, blk_status_t, const char *);
void bch_bbio_count_io_errors(struct cache_set *, struct bio *,
- int, const char *);
-void bch_bbio_endio(struct cache_set *, struct bio *, int, const char *);
+ blk_status_t, const char *);
+void bch_bbio_endio(struct cache_set *, struct bio *, blk_status_t,
+ const char *);
void bch_bbio_free(struct bio *, struct cache_set *);
struct bio *bch_bbio_alloc(struct cache_set *);
diff --git a/drivers/md/bcache/btree.c b/drivers/md/bcache/btree.c
index 450d0e848ae4..866dcf78ff8e 100644
--- a/drivers/md/bcache/btree.c
+++ b/drivers/md/bcache/btree.c
@@ -307,7 +307,7 @@ static void bch_btree_node_read(struct btree *b)
bch_submit_bbio(bio, b->c, &b->key, 0);
closure_sync(&cl);
- if (bio->bi_error)
+ if (bio->bi_status)
set_btree_node_io_error(b);
bch_bbio_free(bio, b->c);
@@ -374,10 +374,10 @@ static void btree_node_write_endio(struct bio *bio)
struct closure *cl = bio->bi_private;
struct btree *b = container_of(cl, struct btree, io);
- if (bio->bi_error)
+ if (bio->bi_status)
set_btree_node_io_error(b);
- bch_bbio_count_io_errors(b->c, bio, bio->bi_error, "writing btree");
+ bch_bbio_count_io_errors(b->c, bio, bio->bi_status, "writing btree");
closure_put(cl);
}
diff --git a/drivers/md/bcache/btree.h b/drivers/md/bcache/btree.h
index 9b80417cd547..73da1f5626cb 100644
--- a/drivers/md/bcache/btree.h
+++ b/drivers/md/bcache/btree.h
@@ -207,7 +207,7 @@ void bkey_put(struct cache_set *c, struct bkey *k);
struct btree_op {
/* for waiting on btree reserve in btree_split() */
- wait_queue_t wait;
+ wait_queue_entry_t wait;
/* Btree level at which we start taking write locks */
short lock;
diff --git a/drivers/md/bcache/debug.c b/drivers/md/bcache/debug.c
index 06f55056aaae..35a5a7210e51 100644
--- a/drivers/md/bcache/debug.c
+++ b/drivers/md/bcache/debug.c
@@ -110,7 +110,7 @@ void bch_data_verify(struct cached_dev *dc, struct bio *bio)
struct bio_vec bv, cbv;
struct bvec_iter iter, citer = { 0 };
- check = bio_clone(bio, GFP_NOIO);
+ check = bio_clone_kmalloc(bio, GFP_NOIO);
if (!check)
return;
check->bi_opf = REQ_OP_READ;
diff --git a/drivers/md/bcache/io.c b/drivers/md/bcache/io.c
index db45a88c0ce9..6a9b85095e7b 100644
--- a/drivers/md/bcache/io.c
+++ b/drivers/md/bcache/io.c
@@ -50,7 +50,7 @@ void bch_submit_bbio(struct bio *bio, struct cache_set *c,
/* IO errors */
-void bch_count_io_errors(struct cache *ca, int error, const char *m)
+void bch_count_io_errors(struct cache *ca, blk_status_t error, const char *m)
{
/*
* The halflife of an error is:
@@ -103,7 +103,7 @@ void bch_count_io_errors(struct cache *ca, int error, const char *m)
}
void bch_bbio_count_io_errors(struct cache_set *c, struct bio *bio,
- int error, const char *m)
+ blk_status_t error, const char *m)
{
struct bbio *b = container_of(bio, struct bbio, bio);
struct cache *ca = PTR_CACHE(c, &b->key, 0);
@@ -132,7 +132,7 @@ void bch_bbio_count_io_errors(struct cache_set *c, struct bio *bio,
}
void bch_bbio_endio(struct cache_set *c, struct bio *bio,
- int error, const char *m)
+ blk_status_t error, const char *m)
{
struct closure *cl = bio->bi_private;
diff --git a/drivers/md/bcache/journal.c b/drivers/md/bcache/journal.c
index 1198e53d5670..0352d05e495c 100644
--- a/drivers/md/bcache/journal.c
+++ b/drivers/md/bcache/journal.c
@@ -549,7 +549,7 @@ static void journal_write_endio(struct bio *bio)
{
struct journal_write *w = bio->bi_private;
- cache_set_err_on(bio->bi_error, w->c, "journal io error");
+ cache_set_err_on(bio->bi_status, w->c, "journal io error");
closure_put(&w->c->journal.io);
}
diff --git a/drivers/md/bcache/movinggc.c b/drivers/md/bcache/movinggc.c
index 13b8a907006d..f633b30c962e 100644
--- a/drivers/md/bcache/movinggc.c
+++ b/drivers/md/bcache/movinggc.c
@@ -63,14 +63,14 @@ static void read_moving_endio(struct bio *bio)
struct moving_io *io = container_of(bio->bi_private,
struct moving_io, cl);
- if (bio->bi_error)
- io->op.error = bio->bi_error;
+ if (bio->bi_status)
+ io->op.status = bio->bi_status;
else if (!KEY_DIRTY(&b->key) &&
ptr_stale(io->op.c, &b->key, 0)) {
- io->op.error = -EINTR;
+ io->op.status = BLK_STS_IOERR;
}
- bch_bbio_endio(io->op.c, bio, bio->bi_error, "reading data to move");
+ bch_bbio_endio(io->op.c, bio, bio->bi_status, "reading data to move");
}
static void moving_init(struct moving_io *io)
@@ -92,7 +92,7 @@ static void write_moving(struct closure *cl)
struct moving_io *io = container_of(cl, struct moving_io, cl);
struct data_insert_op *op = &io->op;
- if (!op->error) {
+ if (!op->status) {
moving_init(io);
io->bio.bio.bi_iter.bi_sector = KEY_START(&io->w->key);
diff --git a/drivers/md/bcache/request.c b/drivers/md/bcache/request.c
index 709c9cc34369..019b3df9f1c6 100644
--- a/drivers/md/bcache/request.c
+++ b/drivers/md/bcache/request.c
@@ -81,7 +81,7 @@ static void bch_data_insert_keys(struct closure *cl)
if (ret == -ESRCH) {
op->replace_collision = true;
} else if (ret) {
- op->error = -ENOMEM;
+ op->status = BLK_STS_RESOURCE;
op->insert_data_done = true;
}
@@ -178,17 +178,17 @@ static void bch_data_insert_endio(struct bio *bio)
struct closure *cl = bio->bi_private;
struct data_insert_op *op = container_of(cl, struct data_insert_op, cl);
- if (bio->bi_error) {
+ if (bio->bi_status) {
/* TODO: We could try to recover from this. */
if (op->writeback)
- op->error = bio->bi_error;
+ op->status = bio->bi_status;
else if (!op->replace)
set_closure_fn(cl, bch_data_insert_error, op->wq);
else
set_closure_fn(cl, NULL, NULL);
}
- bch_bbio_endio(op->c, bio, bio->bi_error, "writing data to cache");
+ bch_bbio_endio(op->c, bio, bio->bi_status, "writing data to cache");
}
static void bch_data_insert_start(struct closure *cl)
@@ -488,15 +488,15 @@ static void bch_cache_read_endio(struct bio *bio)
* from the backing device.
*/
- if (bio->bi_error)
- s->iop.error = bio->bi_error;
+ if (bio->bi_status)
+ s->iop.status = bio->bi_status;
else if (!KEY_DIRTY(&b->key) &&
ptr_stale(s->iop.c, &b->key, 0)) {
atomic_long_inc(&s->iop.c->cache_read_races);
- s->iop.error = -EINTR;
+ s->iop.status = BLK_STS_IOERR;
}
- bch_bbio_endio(s->iop.c, bio, bio->bi_error, "reading from cache");
+ bch_bbio_endio(s->iop.c, bio, bio->bi_status, "reading from cache");
}
/*
@@ -593,9 +593,9 @@ static void request_endio(struct bio *bio)
{
struct closure *cl = bio->bi_private;
- if (bio->bi_error) {
+ if (bio->bi_status) {
struct search *s = container_of(cl, struct search, cl);
- s->iop.error = bio->bi_error;
+ s->iop.status = bio->bi_status;
/* Only cache read errors are recoverable */
s->recoverable = false;
}
@@ -611,7 +611,7 @@ static void bio_complete(struct search *s)
&s->d->disk->part0, s->start_time);
trace_bcache_request_end(s->d, s->orig_bio);
- s->orig_bio->bi_error = s->iop.error;
+ s->orig_bio->bi_status = s->iop.status;
bio_endio(s->orig_bio);
s->orig_bio = NULL;
}
@@ -664,7 +664,7 @@ static inline struct search *search_alloc(struct bio *bio,
s->iop.inode = d->id;
s->iop.write_point = hash_long((unsigned long) current, 16);
s->iop.write_prio = 0;
- s->iop.error = 0;
+ s->iop.status = 0;
s->iop.flags = 0;
s->iop.flush_journal = op_is_flush(bio->bi_opf);
s->iop.wq = bcache_wq;
@@ -707,7 +707,7 @@ static void cached_dev_read_error(struct closure *cl)
/* Retry from the backing device: */
trace_bcache_read_retry(s->orig_bio);
- s->iop.error = 0;
+ s->iop.status = 0;
do_bio_hook(s, s->orig_bio);
/* XXX: invalidate cache */
@@ -767,7 +767,7 @@ static void cached_dev_read_done_bh(struct closure *cl)
!s->cache_miss, s->iop.bypass);
trace_bcache_read(s->orig_bio, !s->cache_miss, s->iop.bypass);
- if (s->iop.error)
+ if (s->iop.status)
continue_at_nobarrier(cl, cached_dev_read_error, bcache_wq);
else if (s->iop.bio || verify(dc, &s->bio.bio))
continue_at_nobarrier(cl, cached_dev_read_done, bcache_wq);
diff --git a/drivers/md/bcache/request.h b/drivers/md/bcache/request.h
index 1ff36875c2b3..7689176951ce 100644
--- a/drivers/md/bcache/request.h
+++ b/drivers/md/bcache/request.h
@@ -10,7 +10,7 @@ struct data_insert_op {
unsigned inode;
uint16_t write_point;
uint16_t write_prio;
- short error;
+ blk_status_t status;
union {
uint16_t flags;
diff --git a/drivers/md/bcache/super.c b/drivers/md/bcache/super.c
index e57353e39168..8352fad765f6 100644
--- a/drivers/md/bcache/super.c
+++ b/drivers/md/bcache/super.c
@@ -271,7 +271,7 @@ static void write_super_endio(struct bio *bio)
{
struct cache *ca = bio->bi_private;
- bch_count_io_errors(ca, bio->bi_error, "writing superblock");
+ bch_count_io_errors(ca, bio->bi_status, "writing superblock");
closure_put(&ca->set->sb_write);
}
@@ -321,7 +321,7 @@ static void uuid_endio(struct bio *bio)
struct closure *cl = bio->bi_private;
struct cache_set *c = container_of(cl, struct cache_set, uuid_write);
- cache_set_err_on(bio->bi_error, c, "accessing uuids");
+ cache_set_err_on(bio->bi_status, c, "accessing uuids");
bch_bbio_free(bio, c);
closure_put(cl);
}
@@ -494,7 +494,7 @@ static void prio_endio(struct bio *bio)
{
struct cache *ca = bio->bi_private;
- cache_set_err_on(bio->bi_error, ca->set, "accessing priorities");
+ cache_set_err_on(bio->bi_status, ca->set, "accessing priorities");
bch_bbio_free(bio, ca->set);
closure_put(&ca->prio);
}
@@ -782,7 +782,9 @@ static int bcache_device_init(struct bcache_device *d, unsigned block_size,
minor *= BCACHE_MINORS;
- if (!(d->bio_split = bioset_create(4, offsetof(struct bbio, bio))) ||
+ if (!(d->bio_split = bioset_create(4, offsetof(struct bbio, bio),
+ BIOSET_NEED_BVECS |
+ BIOSET_NEED_RESCUER)) ||
!(d->disk = alloc_disk(BCACHE_MINORS))) {
ida_simple_remove(&bcache_minor, minor);
return -ENOMEM;
@@ -1516,7 +1518,9 @@ struct cache_set *bch_cache_set_alloc(struct cache_sb *sb)
sizeof(struct bbio) + sizeof(struct bio_vec) *
bucket_pages(c))) ||
!(c->fill_iter = mempool_create_kmalloc_pool(1, iter_size)) ||
- !(c->bio_split = bioset_create(4, offsetof(struct bbio, bio))) ||
+ !(c->bio_split = bioset_create(4, offsetof(struct bbio, bio),
+ BIOSET_NEED_BVECS |
+ BIOSET_NEED_RESCUER)) ||
!(c->uuids = alloc_bucket_pages(GFP_KERNEL, c)) ||
!(c->moving_gc_wq = alloc_workqueue("bcache_gc",
WQ_MEM_RECLAIM, 0)) ||
diff --git a/drivers/md/bcache/writeback.c b/drivers/md/bcache/writeback.c
index 6ac2e48b9235..42c66e76f05e 100644
--- a/drivers/md/bcache/writeback.c
+++ b/drivers/md/bcache/writeback.c
@@ -167,7 +167,7 @@ static void dirty_endio(struct bio *bio)
struct keybuf_key *w = bio->bi_private;
struct dirty_io *io = w->private;
- if (bio->bi_error)
+ if (bio->bi_status)
SET_KEY_DIRTY(&w->key, false);
closure_put(&io->cl);
@@ -195,7 +195,7 @@ static void read_dirty_endio(struct bio *bio)
struct dirty_io *io = w->private;
bch_count_io_errors(PTR_CACHE(io->dc->disk.c, &w->key, 0),
- bio->bi_error, "reading dirty data from cache");
+ bio->bi_status, "reading dirty data from cache");
dirty_endio(bio);
}
diff --git a/drivers/md/bitmap.c b/drivers/md/bitmap.c
index bf7419a56454..f4eace5ea184 100644
--- a/drivers/md/bitmap.c
+++ b/drivers/md/bitmap.c
@@ -485,10 +485,10 @@ void bitmap_print_sb(struct bitmap *bitmap)
pr_debug(" magic: %08x\n", le32_to_cpu(sb->magic));
pr_debug(" version: %d\n", le32_to_cpu(sb->version));
pr_debug(" uuid: %08x.%08x.%08x.%08x\n",
- *(__u32 *)(sb->uuid+0),
- *(__u32 *)(sb->uuid+4),
- *(__u32 *)(sb->uuid+8),
- *(__u32 *)(sb->uuid+12));
+ le32_to_cpu(*(__u32 *)(sb->uuid+0)),
+ le32_to_cpu(*(__u32 *)(sb->uuid+4)),
+ le32_to_cpu(*(__u32 *)(sb->uuid+8)),
+ le32_to_cpu(*(__u32 *)(sb->uuid+12)));
pr_debug(" events: %llu\n",
(unsigned long long) le64_to_cpu(sb->events));
pr_debug("events cleared: %llu\n",
diff --git a/drivers/md/dm-bio-prison-v1.c b/drivers/md/dm-bio-prison-v1.c
index ae7da2c30a57..82d27384d31f 100644
--- a/drivers/md/dm-bio-prison-v1.c
+++ b/drivers/md/dm-bio-prison-v1.c
@@ -229,7 +229,7 @@ void dm_cell_release_no_holder(struct dm_bio_prison *prison,
EXPORT_SYMBOL_GPL(dm_cell_release_no_holder);
void dm_cell_error(struct dm_bio_prison *prison,
- struct dm_bio_prison_cell *cell, int error)
+ struct dm_bio_prison_cell *cell, blk_status_t error)
{
struct bio_list bios;
struct bio *bio;
@@ -238,7 +238,7 @@ void dm_cell_error(struct dm_bio_prison *prison,
dm_cell_release(prison, cell, &bios);
while ((bio = bio_list_pop(&bios))) {
- bio->bi_error = error;
+ bio->bi_status = error;
bio_endio(bio);
}
}
diff --git a/drivers/md/dm-bio-prison-v1.h b/drivers/md/dm-bio-prison-v1.h
index cddd4ac07e2c..cec52ac5e1ae 100644
--- a/drivers/md/dm-bio-prison-v1.h
+++ b/drivers/md/dm-bio-prison-v1.h
@@ -91,7 +91,7 @@ void dm_cell_release_no_holder(struct dm_bio_prison *prison,
struct dm_bio_prison_cell *cell,
struct bio_list *inmates);
void dm_cell_error(struct dm_bio_prison *prison,
- struct dm_bio_prison_cell *cell, int error);
+ struct dm_bio_prison_cell *cell, blk_status_t error);
/*
* Visits the cell and then releases. Guarantees no new inmates are
diff --git a/drivers/md/dm-bufio.c b/drivers/md/dm-bufio.c
index cd8139593ccd..850ff6c67994 100644
--- a/drivers/md/dm-bufio.c
+++ b/drivers/md/dm-bufio.c
@@ -145,8 +145,8 @@ struct dm_buffer {
enum data_mode data_mode;
unsigned char list_mode; /* LIST_* */
unsigned hold_count;
- int read_error;
- int write_error;
+ blk_status_t read_error;
+ blk_status_t write_error;
unsigned long state;
unsigned long last_accessed;
struct dm_bufio_client *c;
@@ -555,7 +555,7 @@ static void dmio_complete(unsigned long error, void *context)
{
struct dm_buffer *b = context;
- b->bio.bi_error = error ? -EIO : 0;
+ b->bio.bi_status = error ? BLK_STS_IOERR : 0;
b->bio.bi_end_io(&b->bio);
}
@@ -588,7 +588,7 @@ static void use_dmio(struct dm_buffer *b, int rw, sector_t sector,
r = dm_io(&io_req, 1, &region, NULL);
if (r) {
- b->bio.bi_error = r;
+ b->bio.bi_status = errno_to_blk_status(r);
end_io(&b->bio);
}
}
@@ -596,7 +596,7 @@ static void use_dmio(struct dm_buffer *b, int rw, sector_t sector,
static void inline_endio(struct bio *bio)
{
bio_end_io_t *end_fn = bio->bi_private;
- int error = bio->bi_error;
+ blk_status_t status = bio->bi_status;
/*
* Reset the bio to free any attached resources
@@ -604,7 +604,7 @@ static void inline_endio(struct bio *bio)
*/
bio_reset(bio);
- bio->bi_error = error;
+ bio->bi_status = status;
end_fn(bio);
}
@@ -685,11 +685,12 @@ static void write_endio(struct bio *bio)
{
struct dm_buffer *b = container_of(bio, struct dm_buffer, bio);
- b->write_error = bio->bi_error;
- if (unlikely(bio->bi_error)) {
+ b->write_error = bio->bi_status;
+ if (unlikely(bio->bi_status)) {
struct dm_bufio_client *c = b->c;
- int error = bio->bi_error;
- (void)cmpxchg(&c->async_write_error, 0, error);
+
+ (void)cmpxchg(&c->async_write_error, 0,
+ blk_status_to_errno(bio->bi_status));
}
BUG_ON(!test_bit(B_WRITING, &b->state));
@@ -1063,7 +1064,7 @@ static void read_endio(struct bio *bio)
{
struct dm_buffer *b = container_of(bio, struct dm_buffer, bio);
- b->read_error = bio->bi_error;
+ b->read_error = bio->bi_status;
BUG_ON(!test_bit(B_READING, &b->state));
@@ -1107,7 +1108,7 @@ static void *new_read(struct dm_bufio_client *c, sector_t block,
wait_on_bit_io(&b->state, B_READING, TASK_UNINTERRUPTIBLE);
if (b->read_error) {
- int error = b->read_error;
+ int error = blk_status_to_errno(b->read_error);
dm_bufio_release(b);
@@ -1257,7 +1258,8 @@ EXPORT_SYMBOL_GPL(dm_bufio_write_dirty_buffers_async);
*/
int dm_bufio_write_dirty_buffers(struct dm_bufio_client *c)
{
- int a, f;
+ blk_status_t a;
+ int f;
unsigned long buffers_processed = 0;
struct dm_buffer *b, *tmp;
@@ -1334,7 +1336,7 @@ int dm_bufio_issue_flush(struct dm_bufio_client *c)
{
struct dm_io_request io_req = {
.bi_op = REQ_OP_WRITE,
- .bi_op_flags = REQ_PREFLUSH,
+ .bi_op_flags = REQ_PREFLUSH | REQ_SYNC,
.mem.type = DM_IO_KMEM,
.mem.ptr.addr = NULL,
.client = c->dm_io,
diff --git a/drivers/md/dm-cache-target.c b/drivers/md/dm-cache-target.c
index d682a0511381..c5ea03fc7ee1 100644
--- a/drivers/md/dm-cache-target.c
+++ b/drivers/md/dm-cache-target.c
@@ -119,7 +119,7 @@ static void iot_io_end(struct io_tracker *iot, sector_t len)
*/
struct continuation {
struct work_struct ws;
- int input;
+ blk_status_t input;
};
static inline void init_continuation(struct continuation *k,
@@ -145,7 +145,7 @@ struct batcher {
/*
* The operation that everyone is waiting for.
*/
- int (*commit_op)(void *context);
+ blk_status_t (*commit_op)(void *context);
void *commit_context;
/*
@@ -171,8 +171,7 @@ struct batcher {
static void __commit(struct work_struct *_ws)
{
struct batcher *b = container_of(_ws, struct batcher, commit_work);
-
- int r;
+ blk_status_t r;
unsigned long flags;
struct list_head work_items;
struct work_struct *ws, *tmp;
@@ -205,7 +204,7 @@ static void __commit(struct work_struct *_ws)
while ((bio = bio_list_pop(&bios))) {
if (r) {
- bio->bi_error = r;
+ bio->bi_status = r;
bio_endio(bio);
} else
b->issue_op(bio, b->issue_context);
@@ -213,7 +212,7 @@ static void __commit(struct work_struct *_ws)
}
static void batcher_init(struct batcher *b,
- int (*commit_op)(void *),
+ blk_status_t (*commit_op)(void *),
void *commit_context,
void (*issue_op)(struct bio *bio, void *),
void *issue_context,
@@ -955,7 +954,7 @@ static void writethrough_endio(struct bio *bio)
dm_unhook_bio(&pb->hook_info, bio);
- if (bio->bi_error) {
+ if (bio->bi_status) {
bio_endio(bio);
return;
}
@@ -1220,7 +1219,7 @@ static void copy_complete(int read_err, unsigned long write_err, void *context)
struct dm_cache_migration *mg = container_of(context, struct dm_cache_migration, k);
if (read_err || write_err)
- mg->k.input = -EIO;
+ mg->k.input = BLK_STS_IOERR;
queue_continuation(mg->cache->wq, &mg->k);
}
@@ -1266,8 +1265,8 @@ static void overwrite_endio(struct bio *bio)
dm_unhook_bio(&pb->hook_info, bio);
- if (bio->bi_error)
- mg->k.input = bio->bi_error;
+ if (bio->bi_status)
+ mg->k.input = bio->bi_status;
queue_continuation(mg->cache->wq, &mg->k);
}
@@ -1323,8 +1322,10 @@ static void mg_complete(struct dm_cache_migration *mg, bool success)
if (mg->overwrite_bio) {
if (success)
force_set_dirty(cache, cblock);
+ else if (mg->k.input)
+ mg->overwrite_bio->bi_status = mg->k.input;
else
- mg->overwrite_bio->bi_error = (mg->k.input ? : -EIO);
+ mg->overwrite_bio->bi_status = BLK_STS_IOERR;
bio_endio(mg->overwrite_bio);
} else {
if (success)
@@ -1504,7 +1505,7 @@ static void mg_copy(struct work_struct *ws)
r = copy(mg, is_policy_promote);
if (r) {
DMERR_LIMIT("%s: migration copy failed", cache_device_name(cache));
- mg->k.input = -EIO;
+ mg->k.input = BLK_STS_IOERR;
mg_complete(mg, false);
}
}
@@ -1907,12 +1908,12 @@ static int commit(struct cache *cache, bool clean_shutdown)
/*
* Used by the batcher.
*/
-static int commit_op(void *context)
+static blk_status_t commit_op(void *context)
{
struct cache *cache = context;
if (dm_cache_changed_this_transaction(cache->cmd))
- return commit(cache, false);
+ return errno_to_blk_status(commit(cache, false));
return 0;
}
@@ -2018,7 +2019,7 @@ static void requeue_deferred_bios(struct cache *cache)
bio_list_init(&cache->deferred_bios);
while ((bio = bio_list_pop(&bios))) {
- bio->bi_error = DM_ENDIO_REQUEUE;
+ bio->bi_status = BLK_STS_DM_REQUEUE;
bio_endio(bio);
}
}
@@ -2820,7 +2821,8 @@ static int cache_map(struct dm_target *ti, struct bio *bio)
return r;
}
-static int cache_end_io(struct dm_target *ti, struct bio *bio, int error)
+static int cache_end_io(struct dm_target *ti, struct bio *bio,
+ blk_status_t *error)
{
struct cache *cache = ti->private;
unsigned long flags;
@@ -2838,7 +2840,7 @@ static int cache_end_io(struct dm_target *ti, struct bio *bio, int error)
bio_drop_shared_lock(cache, bio);
accounted_complete(cache, bio);
- return 0;
+ return DM_ENDIO_DONE;
}
static int write_dirty_bitset(struct cache *cache)
diff --git a/drivers/md/dm-crypt.c b/drivers/md/dm-crypt.c
index ebf9e72d479b..9e1b72e8f7ef 100644
--- a/drivers/md/dm-crypt.c
+++ b/drivers/md/dm-crypt.c
@@ -71,7 +71,7 @@ struct dm_crypt_io {
struct convert_context ctx;
atomic_t io_pending;
- int error;
+ blk_status_t error;
sector_t sector;
struct rb_node rb_node;
@@ -1292,7 +1292,7 @@ static void crypt_free_req(struct crypt_config *cc, void *req, struct bio *base_
/*
* Encrypt / decrypt data from one bio to another one (can be the same one)
*/
-static int crypt_convert(struct crypt_config *cc,
+static blk_status_t crypt_convert(struct crypt_config *cc,
struct convert_context *ctx)
{
unsigned int tag_offset = 0;
@@ -1343,13 +1343,13 @@ static int crypt_convert(struct crypt_config *cc,
*/
case -EBADMSG:
atomic_dec(&ctx->cc_pending);
- return -EILSEQ;
+ return BLK_STS_PROTECTION;
/*
* There was an error while processing the request.
*/
default:
atomic_dec(&ctx->cc_pending);
- return -EIO;
+ return BLK_STS_IOERR;
}
}
@@ -1463,7 +1463,7 @@ static void crypt_dec_pending(struct dm_crypt_io *io)
{
struct crypt_config *cc = io->cc;
struct bio *base_bio = io->base_bio;
- int error = io->error;
+ blk_status_t error = io->error;
if (!atomic_dec_and_test(&io->io_pending))
return;
@@ -1476,7 +1476,7 @@ static void crypt_dec_pending(struct dm_crypt_io *io)
else
kfree(io->integrity_metadata);
- base_bio->bi_error = error;
+ base_bio->bi_status = error;
bio_endio(base_bio);
}
@@ -1502,7 +1502,7 @@ static void crypt_endio(struct bio *clone)
struct dm_crypt_io *io = clone->bi_private;
struct crypt_config *cc = io->cc;
unsigned rw = bio_data_dir(clone);
- int error;
+ blk_status_t error;
/*
* free the processed pages
@@ -1510,7 +1510,7 @@ static void crypt_endio(struct bio *clone)
if (rw == WRITE)
crypt_free_buffer_pages(cc, clone);
- error = clone->bi_error;
+ error = clone->bi_status;
bio_put(clone);
if (rw == READ && !error) {
@@ -1570,7 +1570,7 @@ static void kcryptd_io_read_work(struct work_struct *work)
crypt_inc_pending(io);
if (kcryptd_io_read(io, GFP_NOIO))
- io->error = -ENOMEM;
+ io->error = BLK_STS_RESOURCE;
crypt_dec_pending(io);
}
@@ -1656,7 +1656,7 @@ static void kcryptd_crypt_write_io_submit(struct dm_crypt_io *io, int async)
sector_t sector;
struct rb_node **rbp, *parent;
- if (unlikely(io->error < 0)) {
+ if (unlikely(io->error)) {
crypt_free_buffer_pages(cc, clone);
bio_put(clone);
crypt_dec_pending(io);
@@ -1697,7 +1697,7 @@ static void kcryptd_crypt_write_convert(struct dm_crypt_io *io)
struct bio *clone;
int crypt_finished;
sector_t sector = io->sector;
- int r;
+ blk_status_t r;
/*
* Prevent io from disappearing until this function completes.
@@ -1707,7 +1707,7 @@ static void kcryptd_crypt_write_convert(struct dm_crypt_io *io)
clone = crypt_alloc_buffer(io, io->base_bio->bi_iter.bi_size);
if (unlikely(!clone)) {
- io->error = -EIO;
+ io->error = BLK_STS_IOERR;
goto dec;
}
@@ -1718,7 +1718,7 @@ static void kcryptd_crypt_write_convert(struct dm_crypt_io *io)
crypt_inc_pending(io);
r = crypt_convert(cc, &io->ctx);
- if (r < 0)
+ if (r)
io->error = r;
crypt_finished = atomic_dec_and_test(&io->ctx.cc_pending);
@@ -1740,7 +1740,7 @@ static void kcryptd_crypt_read_done(struct dm_crypt_io *io)
static void kcryptd_crypt_read_convert(struct dm_crypt_io *io)
{
struct crypt_config *cc = io->cc;
- int r = 0;
+ blk_status_t r;
crypt_inc_pending(io);
@@ -1748,7 +1748,7 @@ static void kcryptd_crypt_read_convert(struct dm_crypt_io *io)
io->sector);
r = crypt_convert(cc, &io->ctx);
- if (r < 0)
+ if (r)
io->error = r;
if (atomic_dec_and_test(&io->ctx.cc_pending))
@@ -1781,9 +1781,9 @@ static void kcryptd_async_done(struct crypto_async_request *async_req,
if (error == -EBADMSG) {
DMERR_LIMIT("INTEGRITY AEAD ERROR, sector %llu",
(unsigned long long)le64_to_cpu(*org_sector_of_dmreq(cc, dmreq)));
- io->error = -EILSEQ;
+ io->error = BLK_STS_PROTECTION;
} else if (error < 0)
- io->error = -EIO;
+ io->error = BLK_STS_IOERR;
crypt_free_req(cc, req_of_dmreq(cc, dmreq), io->base_bio);
@@ -2677,7 +2677,8 @@ static int crypt_ctr(struct dm_target *ti, unsigned int argc, char **argv)
goto bad;
}
- cc->bs = bioset_create(MIN_IOS, 0);
+ cc->bs = bioset_create(MIN_IOS, 0, (BIOSET_NEED_BVECS |
+ BIOSET_NEED_RESCUER));
if (!cc->bs) {
ti->error = "Cannot allocate crypt bioset";
goto bad;
@@ -2795,10 +2796,10 @@ static int crypt_map(struct dm_target *ti, struct bio *bio)
* and is aligned to this size as defined in IO hints.
*/
if (unlikely((bio->bi_iter.bi_sector & ((cc->sector_size >> SECTOR_SHIFT) - 1)) != 0))
- return -EIO;
+ return DM_MAPIO_KILL;
if (unlikely(bio->bi_iter.bi_size & (cc->sector_size - 1)))
- return -EIO;
+ return DM_MAPIO_KILL;
io = dm_per_bio_data(bio, cc->per_bio_data_size);
crypt_io_init(io, cc, bio, dm_target_offset(ti, bio->bi_iter.bi_sector));
diff --git a/drivers/md/dm-flakey.c b/drivers/md/dm-flakey.c
index 13305a182611..3d04d5ce19d9 100644
--- a/drivers/md/dm-flakey.c
+++ b/drivers/md/dm-flakey.c
@@ -321,7 +321,7 @@ static int flakey_map(struct dm_target *ti, struct bio *bio)
if (bio_data_dir(bio) == READ) {
if (!fc->corrupt_bio_byte && !test_bit(DROP_WRITES, &fc->flags) &&
!test_bit(ERROR_WRITES, &fc->flags))
- return -EIO;
+ return DM_MAPIO_KILL;
goto map_bio;
}
@@ -349,7 +349,7 @@ static int flakey_map(struct dm_target *ti, struct bio *bio)
/*
* By default, error all I/O.
*/
- return -EIO;
+ return DM_MAPIO_KILL;
}
map_bio:
@@ -358,12 +358,13 @@ map_bio:
return DM_MAPIO_REMAPPED;
}
-static int flakey_end_io(struct dm_target *ti, struct bio *bio, int error)
+static int flakey_end_io(struct dm_target *ti, struct bio *bio,
+ blk_status_t *error)
{
struct flakey_c *fc = ti->private;
struct per_bio_data *pb = dm_per_bio_data(bio, sizeof(struct per_bio_data));
- if (!error && pb->bio_submitted && (bio_data_dir(bio) == READ)) {
+ if (!*error && pb->bio_submitted && (bio_data_dir(bio) == READ)) {
if (fc->corrupt_bio_byte && (fc->corrupt_bio_rw == READ) &&
all_corrupt_bio_flags_match(bio, fc)) {
/*
@@ -377,11 +378,11 @@ static int flakey_end_io(struct dm_target *ti, struct bio *bio, int error)
* Error read during the down_interval if drop_writes
* and error_writes were not configured.
*/
- return -EIO;
+ *error = BLK_STS_IOERR;
}
}
- return error;
+ return DM_ENDIO_DONE;
}
static void flakey_status(struct dm_target *ti, status_type_t type,
diff --git a/drivers/md/dm-integrity.c b/drivers/md/dm-integrity.c
index c7f7c8d76576..1b224aa9cf15 100644
--- a/drivers/md/dm-integrity.c
+++ b/drivers/md/dm-integrity.c
@@ -246,7 +246,7 @@ struct dm_integrity_io {
unsigned metadata_offset;
atomic_t in_flight;
- int bi_error;
+ blk_status_t bi_status;
struct completion *completion;
@@ -783,7 +783,8 @@ static void write_journal(struct dm_integrity_c *ic, unsigned commit_start, unsi
for (i = 0; i < commit_sections; i++)
rw_section_mac(ic, commit_start + i, true);
}
- rw_journal(ic, REQ_OP_WRITE, REQ_FUA, commit_start, commit_sections, &io_comp);
+ rw_journal(ic, REQ_OP_WRITE, REQ_FUA | REQ_SYNC, commit_start,
+ commit_sections, &io_comp);
} else {
unsigned to_end;
io_comp.in_flight = (atomic_t)ATOMIC_INIT(2);
@@ -1104,18 +1105,21 @@ static void schedule_autocommit(struct dm_integrity_c *ic)
static void submit_flush_bio(struct dm_integrity_c *ic, struct dm_integrity_io *dio)
{
struct bio *bio;
- spin_lock_irq(&ic->endio_wait.lock);
+ unsigned long flags;
+
+ spin_lock_irqsave(&ic->endio_wait.lock, flags);
bio = dm_bio_from_per_bio_data(dio, sizeof(struct dm_integrity_io));
bio_list_add(&ic->flush_bio_list, bio);
- spin_unlock_irq(&ic->endio_wait.lock);
+ spin_unlock_irqrestore(&ic->endio_wait.lock, flags);
+
queue_work(ic->commit_wq, &ic->commit_work);
}
static void do_endio(struct dm_integrity_c *ic, struct bio *bio)
{
int r = dm_integrity_failed(ic);
- if (unlikely(r) && !bio->bi_error)
- bio->bi_error = r;
+ if (unlikely(r) && !bio->bi_status)
+ bio->bi_status = errno_to_blk_status(r);
bio_endio(bio);
}
@@ -1123,7 +1127,7 @@ static void do_endio_flush(struct dm_integrity_c *ic, struct dm_integrity_io *di
{
struct bio *bio = dm_bio_from_per_bio_data(dio, sizeof(struct dm_integrity_io));
- if (unlikely(dio->fua) && likely(!bio->bi_error) && likely(!dm_integrity_failed(ic)))
+ if (unlikely(dio->fua) && likely(!bio->bi_status) && likely(!dm_integrity_failed(ic)))
submit_flush_bio(ic, dio);
else
do_endio(ic, bio);
@@ -1142,9 +1146,9 @@ static void dec_in_flight(struct dm_integrity_io *dio)
bio = dm_bio_from_per_bio_data(dio, sizeof(struct dm_integrity_io));
- if (unlikely(dio->bi_error) && !bio->bi_error)
- bio->bi_error = dio->bi_error;
- if (likely(!bio->bi_error) && unlikely(bio_sectors(bio) != dio->range.n_sectors)) {
+ if (unlikely(dio->bi_status) && !bio->bi_status)
+ bio->bi_status = dio->bi_status;
+ if (likely(!bio->bi_status) && unlikely(bio_sectors(bio) != dio->range.n_sectors)) {
dio->range.logical_sector += dio->range.n_sectors;
bio_advance(bio, dio->range.n_sectors << SECTOR_SHIFT);
INIT_WORK(&dio->work, integrity_bio_wait);
@@ -1318,7 +1322,7 @@ skip_io:
dec_in_flight(dio);
return;
error:
- dio->bi_error = r;
+ dio->bi_status = errno_to_blk_status(r);
dec_in_flight(dio);
}
@@ -1331,7 +1335,7 @@ static int dm_integrity_map(struct dm_target *ti, struct bio *bio)
sector_t area, offset;
dio->ic = ic;
- dio->bi_error = 0;
+ dio->bi_status = 0;
if (unlikely(bio->bi_opf & REQ_PREFLUSH)) {
submit_flush_bio(ic, dio);
@@ -1352,13 +1356,13 @@ static int dm_integrity_map(struct dm_target *ti, struct bio *bio)
DMERR("Too big sector number: 0x%llx + 0x%x > 0x%llx",
(unsigned long long)dio->range.logical_sector, bio_sectors(bio),
(unsigned long long)ic->provided_data_sectors);
- return -EIO;
+ return DM_MAPIO_KILL;
}
if (unlikely((dio->range.logical_sector | bio_sectors(bio)) & (unsigned)(ic->sectors_per_block - 1))) {
DMERR("Bio not aligned on %u sectors: 0x%llx, 0x%x",
ic->sectors_per_block,
(unsigned long long)dio->range.logical_sector, bio_sectors(bio));
- return -EIO;
+ return DM_MAPIO_KILL;
}
if (ic->sectors_per_block > 1) {
@@ -1368,7 +1372,7 @@ static int dm_integrity_map(struct dm_target *ti, struct bio *bio)
if (unlikely((bv.bv_offset | bv.bv_len) & ((ic->sectors_per_block << SECTOR_SHIFT) - 1))) {
DMERR("Bio vector (%u,%u) is not aligned on %u-sector boundary",
bv.bv_offset, bv.bv_len, ic->sectors_per_block);
- return -EIO;
+ return DM_MAPIO_KILL;
}
}
}
@@ -1383,18 +1387,18 @@ static int dm_integrity_map(struct dm_target *ti, struct bio *bio)
wanted_tag_size *= ic->tag_size;
if (unlikely(wanted_tag_size != bip->bip_iter.bi_size)) {
DMERR("Invalid integrity data size %u, expected %u", bip->bip_iter.bi_size, wanted_tag_size);
- return -EIO;
+ return DM_MAPIO_KILL;
}
}
} else {
if (unlikely(bip != NULL)) {
DMERR("Unexpected integrity data when using internal hash");
- return -EIO;
+ return DM_MAPIO_KILL;
}
}
if (unlikely(ic->mode == 'R') && unlikely(dio->write))
- return -EIO;
+ return DM_MAPIO_KILL;
get_area_and_offset(ic, dio->range.logical_sector, &area, &offset);
dio->metadata_block = get_metadata_sector_and_offset(ic, area, offset, &dio->metadata_offset);
@@ -2374,21 +2378,6 @@ static void dm_integrity_set(struct dm_target *ti, struct dm_integrity_c *ic)
blk_queue_max_integrity_segments(disk->queue, UINT_MAX);
}
-/* FIXME: use new kvmalloc */
-static void *dm_integrity_kvmalloc(size_t size, gfp_t gfp)
-{
- void *ptr = NULL;
-
- if (size <= PAGE_SIZE)
- ptr = kmalloc(size, GFP_KERNEL | gfp);
- if (!ptr && size <= KMALLOC_MAX_SIZE)
- ptr = kmalloc(size, GFP_KERNEL | __GFP_NOWARN | __GFP_NORETRY | gfp);
- if (!ptr)
- ptr = __vmalloc(size, GFP_KERNEL | gfp, PAGE_KERNEL);
-
- return ptr;
-}
-
static void dm_integrity_free_page_list(struct dm_integrity_c *ic, struct page_list *pl)
{
unsigned i;
@@ -2407,7 +2396,7 @@ static struct page_list *dm_integrity_alloc_page_list(struct dm_integrity_c *ic)
struct page_list *pl;
unsigned i;
- pl = dm_integrity_kvmalloc(page_list_desc_size, __GFP_ZERO);
+ pl = kvmalloc(page_list_desc_size, GFP_KERNEL | __GFP_ZERO);
if (!pl)
return NULL;
@@ -2437,7 +2426,7 @@ static struct scatterlist **dm_integrity_alloc_journal_scatterlist(struct dm_int
struct scatterlist **sl;
unsigned i;
- sl = dm_integrity_kvmalloc(ic->journal_sections * sizeof(struct scatterlist *), __GFP_ZERO);
+ sl = kvmalloc(ic->journal_sections * sizeof(struct scatterlist *), GFP_KERNEL | __GFP_ZERO);
if (!sl)
return NULL;
@@ -2453,7 +2442,7 @@ static struct scatterlist **dm_integrity_alloc_journal_scatterlist(struct dm_int
n_pages = (end_index - start_index + 1);
- s = dm_integrity_kvmalloc(n_pages * sizeof(struct scatterlist), 0);
+ s = kvmalloc(n_pages * sizeof(struct scatterlist), GFP_KERNEL);
if (!s) {
dm_integrity_free_journal_scatterlist(ic, sl);
return NULL;
@@ -2617,7 +2606,7 @@ static int create_journal(struct dm_integrity_c *ic, char **error)
goto bad;
}
- sg = dm_integrity_kvmalloc((ic->journal_pages + 1) * sizeof(struct scatterlist), 0);
+ sg = kvmalloc((ic->journal_pages + 1) * sizeof(struct scatterlist), GFP_KERNEL);
if (!sg) {
*error = "Unable to allocate sg list";
r = -ENOMEM;
@@ -2673,7 +2662,7 @@ static int create_journal(struct dm_integrity_c *ic, char **error)
r = -ENOMEM;
goto bad;
}
- ic->sk_requests = dm_integrity_kvmalloc(ic->journal_sections * sizeof(struct skcipher_request *), __GFP_ZERO);
+ ic->sk_requests = kvmalloc(ic->journal_sections * sizeof(struct skcipher_request *), GFP_KERNEL | __GFP_ZERO);
if (!ic->sk_requests) {
*error = "Unable to allocate sk requests";
r = -ENOMEM;
@@ -2740,7 +2729,7 @@ retest_commit_id:
r = -ENOMEM;
goto bad;
}
- ic->journal_tree = dm_integrity_kvmalloc(journal_tree_size, 0);
+ ic->journal_tree = kvmalloc(journal_tree_size, GFP_KERNEL);
if (!ic->journal_tree) {
*error = "Could not allocate memory for journal tree";
r = -ENOMEM;
@@ -3054,6 +3043,11 @@ static int dm_integrity_ctr(struct dm_target *ti, unsigned argc, char **argv)
ti->error = "The device is too small";
goto bad;
}
+ if (ti->len > ic->provided_data_sectors) {
+ r = -EINVAL;
+ ti->error = "Not enough provided sectors for requested mapping size";
+ goto bad;
+ }
if (!buffer_sectors)
buffer_sectors = 1;
diff --git a/drivers/md/dm-io.c b/drivers/md/dm-io.c
index 3702e502466d..25039607f3cb 100644
--- a/drivers/md/dm-io.c
+++ b/drivers/md/dm-io.c
@@ -58,7 +58,8 @@ struct dm_io_client *dm_io_client_create(void)
if (!client->pool)
goto bad;
- client->bios = bioset_create(min_ios, 0);
+ client->bios = bioset_create(min_ios, 0, (BIOSET_NEED_BVECS |
+ BIOSET_NEED_RESCUER));
if (!client->bios)
goto bad;
@@ -124,7 +125,7 @@ static void complete_io(struct io *io)
fn(error_bits, context);
}
-static void dec_count(struct io *io, unsigned int region, int error)
+static void dec_count(struct io *io, unsigned int region, blk_status_t error)
{
if (error)
set_bit(region, &io->error_bits);
@@ -137,9 +138,9 @@ static void endio(struct bio *bio)
{
struct io *io;
unsigned region;
- int error;
+ blk_status_t error;
- if (bio->bi_error && bio_data_dir(bio) == READ)
+ if (bio->bi_status && bio_data_dir(bio) == READ)
zero_fill_bio(bio);
/*
@@ -147,7 +148,7 @@ static void endio(struct bio *bio)
*/
retrieve_io_and_region_from_bio(bio, &io, &region);
- error = bio->bi_error;
+ error = bio->bi_status;
bio_put(bio);
dec_count(io, region, error);
@@ -317,9 +318,9 @@ static void do_region(int op, int op_flags, unsigned region,
else if (op == REQ_OP_WRITE_SAME)
special_cmd_max_sectors = q->limits.max_write_same_sectors;
if ((op == REQ_OP_DISCARD || op == REQ_OP_WRITE_ZEROES ||
- op == REQ_OP_WRITE_SAME) &&
- special_cmd_max_sectors == 0) {
- dec_count(io, region, -EOPNOTSUPP);
+ op == REQ_OP_WRITE_SAME) && special_cmd_max_sectors == 0) {
+ atomic_inc(&io->count);
+ dec_count(io, region, BLK_STS_NOTSUPP);
return;
}
diff --git a/drivers/md/dm-ioctl.c b/drivers/md/dm-ioctl.c
index 0555b4410e05..41852ae287a5 100644
--- a/drivers/md/dm-ioctl.c
+++ b/drivers/md/dm-ioctl.c
@@ -1710,12 +1710,13 @@ static int copy_params(struct dm_ioctl __user *user, struct dm_ioctl *param_kern
}
/*
- * Try to avoid low memory issues when a device is suspended.
+ * Use __GFP_HIGH to avoid low memory issues when a device is
+ * suspended and the ioctl is needed to resume it.
* Use kmalloc() rather than vmalloc() when we can.
*/
dmi = NULL;
noio_flag = memalloc_noio_save();
- dmi = kvmalloc(param_kernel->data_size, GFP_KERNEL);
+ dmi = kvmalloc(param_kernel->data_size, GFP_KERNEL | __GFP_HIGH);
memalloc_noio_restore(noio_flag);
if (!dmi) {
diff --git a/drivers/md/dm-log-writes.c b/drivers/md/dm-log-writes.c
index 4dfe38655a49..a1da0eb58a93 100644
--- a/drivers/md/dm-log-writes.c
+++ b/drivers/md/dm-log-writes.c
@@ -150,10 +150,10 @@ static void log_end_io(struct bio *bio)
{
struct log_writes_c *lc = bio->bi_private;
- if (bio->bi_error) {
+ if (bio->bi_status) {
unsigned long flags;
- DMERR("Error writing log block, error=%d", bio->bi_error);
+ DMERR("Error writing log block, error=%d", bio->bi_status);
spin_lock_irqsave(&lc->blocks_lock, flags);
lc->logging_enabled = false;
spin_unlock_irqrestore(&lc->blocks_lock, flags);
@@ -586,7 +586,7 @@ static int log_writes_map(struct dm_target *ti, struct bio *bio)
spin_lock_irq(&lc->blocks_lock);
lc->logging_enabled = false;
spin_unlock_irq(&lc->blocks_lock);
- return -ENOMEM;
+ return DM_MAPIO_KILL;
}
INIT_LIST_HEAD(&block->list);
pb->block = block;
@@ -639,7 +639,7 @@ static int log_writes_map(struct dm_target *ti, struct bio *bio)
spin_lock_irq(&lc->blocks_lock);
lc->logging_enabled = false;
spin_unlock_irq(&lc->blocks_lock);
- return -ENOMEM;
+ return DM_MAPIO_KILL;
}
src = kmap_atomic(bv.bv_page);
@@ -664,7 +664,8 @@ map_bio:
return DM_MAPIO_REMAPPED;
}
-static int normal_end_io(struct dm_target *ti, struct bio *bio, int error)
+static int normal_end_io(struct dm_target *ti, struct bio *bio,
+ blk_status_t *error)
{
struct log_writes_c *lc = ti->private;
struct per_bio_data *pb = dm_per_bio_data(bio, sizeof(struct per_bio_data));
@@ -686,7 +687,7 @@ static int normal_end_io(struct dm_target *ti, struct bio *bio, int error)
spin_unlock_irqrestore(&lc->blocks_lock, flags);
}
- return error;
+ return DM_ENDIO_DONE;
}
/*
diff --git a/drivers/md/dm-mpath.c b/drivers/md/dm-mpath.c
index 3df056b73b66..0e8ab5bb3575 100644
--- a/drivers/md/dm-mpath.c
+++ b/drivers/md/dm-mpath.c
@@ -559,13 +559,13 @@ static int __multipath_map_bio(struct multipath *m, struct bio *bio, struct dm_m
if (test_bit(MPATHF_QUEUE_IF_NO_PATH, &m->flags))
return DM_MAPIO_REQUEUE;
dm_report_EIO(m);
- return -EIO;
+ return DM_MAPIO_KILL;
}
mpio->pgpath = pgpath;
mpio->nr_bytes = nr_bytes;
- bio->bi_error = 0;
+ bio->bi_status = 0;
bio->bi_bdev = pgpath->path.dev->bdev;
bio->bi_opf |= REQ_FAILFAST_TRANSPORT;
@@ -621,11 +621,19 @@ static void process_queued_bios(struct work_struct *work)
blk_start_plug(&plug);
while ((bio = bio_list_pop(&bios))) {
r = __multipath_map_bio(m, bio, get_mpio_from_bio(bio));
- if (r < 0 || r == DM_MAPIO_REQUEUE) {
- bio->bi_error = r;
+ switch (r) {
+ case DM_MAPIO_KILL:
+ bio->bi_status = BLK_STS_IOERR;
+ bio_endio(bio);
+ break;
+ case DM_MAPIO_REQUEUE:
+ bio->bi_status = BLK_STS_DM_REQUEUE;
bio_endio(bio);
- } else if (r == DM_MAPIO_REMAPPED)
+ break;
+ case DM_MAPIO_REMAPPED:
generic_make_request(bio);
+ break;
+ }
}
blk_finish_plug(&plug);
}
@@ -1442,22 +1450,15 @@ static void activate_path_work(struct work_struct *work)
activate_or_offline_path(pgpath);
}
-static int noretry_error(int error)
+static int noretry_error(blk_status_t error)
{
switch (error) {
- case -EBADE:
- /*
- * EBADE signals an reservation conflict.
- * We shouldn't fail the path here as we can communicate with
- * the target. We should failover to the next path, but in
- * doing so we might be causing a ping-pong between paths.
- * So just return the reservation conflict error.
- */
- case -EOPNOTSUPP:
- case -EREMOTEIO:
- case -EILSEQ:
- case -ENODATA:
- case -ENOSPC:
+ case BLK_STS_NOTSUPP:
+ case BLK_STS_NOSPC:
+ case BLK_STS_TARGET:
+ case BLK_STS_NEXUS:
+ case BLK_STS_MEDIUM:
+ case BLK_STS_RESOURCE:
return 1;
}
@@ -1466,7 +1467,7 @@ static int noretry_error(int error)
}
static int multipath_end_io(struct dm_target *ti, struct request *clone,
- int error, union map_info *map_context)
+ blk_status_t error, union map_info *map_context)
{
struct dm_mpath_io *mpio = get_mpio(map_context);
struct pgpath *pgpath = mpio->pgpath;
@@ -1493,7 +1494,7 @@ static int multipath_end_io(struct dm_target *ti, struct request *clone,
if (atomic_read(&m->nr_valid_paths) == 0 &&
!test_bit(MPATHF_QUEUE_IF_NO_PATH, &m->flags)) {
- if (error == -EIO)
+ if (error == BLK_STS_IOERR)
dm_report_EIO(m);
/* complete with the original error */
r = DM_ENDIO_DONE;
@@ -1510,24 +1511,26 @@ static int multipath_end_io(struct dm_target *ti, struct request *clone,
return r;
}
-static int do_end_io_bio(struct multipath *m, struct bio *clone,
- int error, struct dm_mpath_io *mpio)
+static int multipath_end_io_bio(struct dm_target *ti, struct bio *clone,
+ blk_status_t *error)
{
+ struct multipath *m = ti->private;
+ struct dm_mpath_io *mpio = get_mpio_from_bio(clone);
+ struct pgpath *pgpath = mpio->pgpath;
unsigned long flags;
+ int r = DM_ENDIO_DONE;
- if (!error)
- return 0; /* I/O complete */
-
- if (noretry_error(error))
- return error;
+ if (!*error || noretry_error(*error))
+ goto done;
- if (mpio->pgpath)
- fail_path(mpio->pgpath);
+ if (pgpath)
+ fail_path(pgpath);
if (atomic_read(&m->nr_valid_paths) == 0 &&
!test_bit(MPATHF_QUEUE_IF_NO_PATH, &m->flags)) {
dm_report_EIO(m);
- return -EIO;
+ *error = BLK_STS_IOERR;
+ goto done;
}
/* Queue for the daemon to resubmit */
@@ -1539,23 +1542,11 @@ static int do_end_io_bio(struct multipath *m, struct bio *clone,
if (!test_bit(MPATHF_QUEUE_IO, &m->flags))
queue_work(kmultipathd, &m->process_queued_bios);
- return DM_ENDIO_INCOMPLETE;
-}
-
-static int multipath_end_io_bio(struct dm_target *ti, struct bio *clone, int error)
-{
- struct multipath *m = ti->private;
- struct dm_mpath_io *mpio = get_mpio_from_bio(clone);
- struct pgpath *pgpath;
- struct path_selector *ps;
- int r;
-
- BUG_ON(!mpio);
-
- r = do_end_io_bio(m, clone, error, mpio);
- pgpath = mpio->pgpath;
+ r = DM_ENDIO_INCOMPLETE;
+done:
if (pgpath) {
- ps = &pgpath->pg->ps;
+ struct path_selector *ps = &pgpath->pg->ps;
+
if (ps->type->end_io)
ps->type->end_io(ps, &pgpath->path, mpio->nr_bytes);
}
diff --git a/drivers/md/dm-raid.c b/drivers/md/dm-raid.c
index 7d893228c40f..b4b75dad816a 100644
--- a/drivers/md/dm-raid.c
+++ b/drivers/md/dm-raid.c
@@ -1927,7 +1927,7 @@ struct dm_raid_superblock {
/********************************************************************
* BELOW FOLLOW V1.9.0 EXTENSIONS TO THE PRISTINE SUPERBLOCK FORMAT!!!
*
- * FEATURE_FLAG_SUPPORTS_V190 in the features member indicates that those exist
+ * FEATURE_FLAG_SUPPORTS_V190 in the compat_features member indicates that those exist
*/
__le32 flags; /* Flags defining array states for reshaping */
@@ -2092,6 +2092,11 @@ static void super_sync(struct mddev *mddev, struct md_rdev *rdev)
sb->layout = cpu_to_le32(mddev->layout);
sb->stripe_sectors = cpu_to_le32(mddev->chunk_sectors);
+ /********************************************************************
+ * BELOW FOLLOW V1.9.0 EXTENSIONS TO THE PRISTINE SUPERBLOCK FORMAT!!!
+ *
+ * FEATURE_FLAG_SUPPORTS_V190 in the compat_features member indicates that those exist
+ */
sb->new_level = cpu_to_le32(mddev->new_level);
sb->new_layout = cpu_to_le32(mddev->new_layout);
sb->new_stripe_sectors = cpu_to_le32(mddev->new_chunk_sectors);
@@ -2438,8 +2443,14 @@ static int super_validate(struct raid_set *rs, struct md_rdev *rdev)
mddev->bitmap_info.default_offset = mddev->bitmap_info.offset;
if (!test_and_clear_bit(FirstUse, &rdev->flags)) {
- /* Retrieve device size stored in superblock to be prepared for shrink */
- rdev->sectors = le64_to_cpu(sb->sectors);
+ /*
+ * Retrieve rdev size stored in superblock to be prepared for shrink.
+ * Check extended superblock members are present otherwise the size
+ * will not be set!
+ */
+ if (le32_to_cpu(sb->compat_features) & FEATURE_FLAG_SUPPORTS_V190)
+ rdev->sectors = le64_to_cpu(sb->sectors);
+
rdev->recovery_offset = le64_to_cpu(sb->disk_recovery_offset);
if (rdev->recovery_offset == MaxSector)
set_bit(In_sync, &rdev->flags);
diff --git a/drivers/md/dm-raid1.c b/drivers/md/dm-raid1.c
index a95cbb80fb34..a4fbd911d566 100644
--- a/drivers/md/dm-raid1.c
+++ b/drivers/md/dm-raid1.c
@@ -145,6 +145,7 @@ static void dispatch_bios(void *context, struct bio_list *bio_list)
struct dm_raid1_bio_record {
struct mirror *m;
+ /* if details->bi_bdev == NULL, details were not saved */
struct dm_bio_details details;
region_t write_region;
};
@@ -260,7 +261,7 @@ static int mirror_flush(struct dm_target *ti)
struct mirror *m;
struct dm_io_request io_req = {
.bi_op = REQ_OP_WRITE,
- .bi_op_flags = REQ_PREFLUSH,
+ .bi_op_flags = REQ_PREFLUSH | REQ_SYNC,
.mem.type = DM_IO_KMEM,
.mem.ptr.addr = NULL,
.client = ms->io_client,
@@ -490,9 +491,9 @@ static void hold_bio(struct mirror_set *ms, struct bio *bio)
* If device is suspended, complete the bio.
*/
if (dm_noflush_suspending(ms->ti))
- bio->bi_error = DM_ENDIO_REQUEUE;
+ bio->bi_status = BLK_STS_DM_REQUEUE;
else
- bio->bi_error = -EIO;
+ bio->bi_status = BLK_STS_IOERR;
bio_endio(bio);
return;
@@ -626,7 +627,7 @@ static void write_callback(unsigned long error, void *context)
* degrade the array.
*/
if (bio_op(bio) == REQ_OP_DISCARD) {
- bio->bi_error = -EOPNOTSUPP;
+ bio->bi_status = BLK_STS_NOTSUPP;
bio_endio(bio);
return;
}
@@ -1198,6 +1199,8 @@ static int mirror_map(struct dm_target *ti, struct bio *bio)
struct dm_raid1_bio_record *bio_record =
dm_per_bio_data(bio, sizeof(struct dm_raid1_bio_record));
+ bio_record->details.bi_bdev = NULL;
+
if (rw == WRITE) {
/* Save region for mirror_end_io() handler */
bio_record->write_region = dm_rh_bio_to_region(ms->rh, bio);
@@ -1207,14 +1210,14 @@ static int mirror_map(struct dm_target *ti, struct bio *bio)
r = log->type->in_sync(log, dm_rh_bio_to_region(ms->rh, bio), 0);
if (r < 0 && r != -EWOULDBLOCK)
- return r;
+ return DM_MAPIO_KILL;
/*
* If region is not in-sync queue the bio.
*/
if (!r || (r == -EWOULDBLOCK)) {
if (bio->bi_opf & REQ_RAHEAD)
- return -EWOULDBLOCK;
+ return DM_MAPIO_KILL;
queue_bio(ms, bio, rw);
return DM_MAPIO_SUBMITTED;
@@ -1226,7 +1229,7 @@ static int mirror_map(struct dm_target *ti, struct bio *bio)
*/
m = choose_mirror(ms, bio->bi_iter.bi_sector);
if (unlikely(!m))
- return -EIO;
+ return DM_MAPIO_KILL;
dm_bio_record(&bio_record->details, bio);
bio_record->m = m;
@@ -1236,7 +1239,8 @@ static int mirror_map(struct dm_target *ti, struct bio *bio)
return DM_MAPIO_REMAPPED;
}
-static int mirror_end_io(struct dm_target *ti, struct bio *bio, int error)
+static int mirror_end_io(struct dm_target *ti, struct bio *bio,
+ blk_status_t *error)
{
int rw = bio_data_dir(bio);
struct mirror_set *ms = (struct mirror_set *) ti->private;
@@ -1252,16 +1256,26 @@ static int mirror_end_io(struct dm_target *ti, struct bio *bio, int error)
if (!(bio->bi_opf & REQ_PREFLUSH) &&
bio_op(bio) != REQ_OP_DISCARD)
dm_rh_dec(ms->rh, bio_record->write_region);
- return error;
+ return DM_ENDIO_DONE;
}
- if (error == -EOPNOTSUPP)
- return error;
+ if (*error == BLK_STS_NOTSUPP)
+ goto out;
+
+ if (bio->bi_opf & REQ_RAHEAD)
+ goto out;
- if ((error == -EWOULDBLOCK) && (bio->bi_opf & REQ_RAHEAD))
- return error;
+ if (unlikely(*error)) {
+ if (!bio_record->details.bi_bdev) {
+ /*
+ * There wasn't enough memory to record necessary
+ * information for a retry or there was no other
+ * mirror in-sync.
+ */
+ DMERR_LIMIT("Mirror read failed.");
+ return DM_ENDIO_DONE;
+ }
- if (unlikely(error)) {
m = bio_record->m;
DMERR("Mirror read failed from %s. Trying alternative device.",
@@ -1277,7 +1291,8 @@ static int mirror_end_io(struct dm_target *ti, struct bio *bio, int error)
bd = &bio_record->details;
dm_bio_restore(bd, bio);
- bio->bi_error = 0;
+ bio_record->details.bi_bdev = NULL;
+ bio->bi_status = 0;
queue_bio(ms, bio, rw);
return DM_ENDIO_INCOMPLETE;
@@ -1285,7 +1300,10 @@ static int mirror_end_io(struct dm_target *ti, struct bio *bio, int error)
DMERR("All replicated volumes dead, failing I/O");
}
- return error;
+out:
+ bio_record->details.bi_bdev = NULL;
+
+ return DM_ENDIO_DONE;
}
static void mirror_presuspend(struct dm_target *ti)
diff --git a/drivers/md/dm-rq.c b/drivers/md/dm-rq.c
index b639fa7246ee..c6ebc5b1e00e 100644
--- a/drivers/md/dm-rq.c
+++ b/drivers/md/dm-rq.c
@@ -71,7 +71,7 @@ static void dm_old_start_queue(struct request_queue *q)
static void dm_mq_start_queue(struct request_queue *q)
{
- blk_mq_start_stopped_hw_queues(q, true);
+ blk_mq_unquiesce_queue(q);
blk_mq_kick_requeue_list(q);
}
@@ -119,7 +119,7 @@ static void end_clone_bio(struct bio *clone)
struct dm_rq_target_io *tio = info->tio;
struct bio *bio = info->orig;
unsigned int nr_bytes = info->orig->bi_iter.bi_size;
- int error = clone->bi_error;
+ blk_status_t error = clone->bi_status;
bio_put(clone);
@@ -158,7 +158,7 @@ static void end_clone_bio(struct bio *clone)
* Do not use blk_end_request() here, because it may complete
* the original request before the clone, and break the ordering.
*/
- blk_update_request(tio->orig, 0, nr_bytes);
+ blk_update_request(tio->orig, BLK_STS_OK, nr_bytes);
}
static struct dm_rq_target_io *tio_from_request(struct request *rq)
@@ -216,7 +216,7 @@ static void rq_completed(struct mapped_device *md, int rw, bool run_queue)
* Must be called without clone's queue lock held,
* see end_clone_request() for more details.
*/
-static void dm_end_request(struct request *clone, int error)
+static void dm_end_request(struct request *clone, blk_status_t error)
{
int rw = rq_data_dir(clone);
struct dm_rq_target_io *tio = clone->end_io_data;
@@ -285,7 +285,7 @@ static void dm_requeue_original_request(struct dm_rq_target_io *tio, bool delay_
rq_completed(md, rw, false);
}
-static void dm_done(struct request *clone, int error, bool mapped)
+static void dm_done(struct request *clone, blk_status_t error, bool mapped)
{
int r = DM_ENDIO_DONE;
struct dm_rq_target_io *tio = clone->end_io_data;
@@ -298,7 +298,7 @@ static void dm_done(struct request *clone, int error, bool mapped)
r = rq_end_io(tio->ti, clone, error, &tio->info);
}
- if (unlikely(error == -EREMOTEIO)) {
+ if (unlikely(error == BLK_STS_TARGET)) {
if (req_op(clone) == REQ_OP_WRITE_SAME &&
!clone->q->limits.max_write_same_sectors)
disable_write_same(tio->md);
@@ -358,7 +358,7 @@ static void dm_softirq_done(struct request *rq)
* Complete the clone and the original request with the error status
* through softirq context.
*/
-static void dm_complete_request(struct request *rq, int error)
+static void dm_complete_request(struct request *rq, blk_status_t error)
{
struct dm_rq_target_io *tio = tio_from_request(rq);
@@ -375,7 +375,7 @@ static void dm_complete_request(struct request *rq, int error)
* Target's rq_end_io() function isn't called.
* This may be used when the target's map_rq() or clone_and_map_rq() functions fail.
*/
-static void dm_kill_unmapped_request(struct request *rq, int error)
+static void dm_kill_unmapped_request(struct request *rq, blk_status_t error)
{
rq->rq_flags |= RQF_FAILED;
dm_complete_request(rq, error);
@@ -384,7 +384,7 @@ static void dm_kill_unmapped_request(struct request *rq, int error)
/*
* Called with the clone's queue lock held (in the case of .request_fn)
*/
-static void end_clone_request(struct request *clone, int error)
+static void end_clone_request(struct request *clone, blk_status_t error)
{
struct dm_rq_target_io *tio = clone->end_io_data;
@@ -401,7 +401,7 @@ static void end_clone_request(struct request *clone, int error)
static void dm_dispatch_clone_request(struct request *clone, struct request *rq)
{
- int r;
+ blk_status_t r;
if (blk_queue_io_stat(clone->q))
clone->rq_flags |= RQF_IO_STAT;
@@ -506,7 +506,7 @@ static int map_request(struct dm_rq_target_io *tio)
break;
case DM_MAPIO_KILL:
/* The target wants to complete the I/O */
- dm_kill_unmapped_request(rq, -EIO);
+ dm_kill_unmapped_request(rq, BLK_STS_IOERR);
break;
default:
DMWARN("unimplemented target map return value: %d", r);
@@ -727,7 +727,7 @@ static int dm_mq_init_request(struct blk_mq_tag_set *set, struct request *rq,
return __dm_rq_init_rq(set->driver_data, rq);
}
-static int dm_mq_queue_rq(struct blk_mq_hw_ctx *hctx,
+static blk_status_t dm_mq_queue_rq(struct blk_mq_hw_ctx *hctx,
const struct blk_mq_queue_data *bd)
{
struct request *rq = bd->rq;
@@ -744,7 +744,7 @@ static int dm_mq_queue_rq(struct blk_mq_hw_ctx *hctx,
}
if (ti->type->busy && ti->type->busy(ti))
- return BLK_MQ_RQ_QUEUE_BUSY;
+ return BLK_STS_RESOURCE;
dm_start_request(md, rq);
@@ -762,10 +762,10 @@ static int dm_mq_queue_rq(struct blk_mq_hw_ctx *hctx,
rq_end_stats(md, rq);
rq_completed(md, rq_data_dir(rq), false);
blk_mq_delay_run_hw_queue(hctx, 100/*ms*/);
- return BLK_MQ_RQ_QUEUE_BUSY;
+ return BLK_STS_RESOURCE;
}
- return BLK_MQ_RQ_QUEUE_OK;
+ return BLK_STS_OK;
}
static const struct blk_mq_ops dm_mq_ops = {
diff --git a/drivers/md/dm-rq.h b/drivers/md/dm-rq.h
index f0020d21b95f..9813922e4fe5 100644
--- a/drivers/md/dm-rq.h
+++ b/drivers/md/dm-rq.h
@@ -24,7 +24,7 @@ struct dm_rq_target_io {
struct dm_target *ti;
struct request *orig, *clone;
struct kthread_work work;
- int error;
+ blk_status_t error;
union map_info info;
struct dm_stats_aux stats_aux;
unsigned long duration_jiffies;
diff --git a/drivers/md/dm-snap-persistent.c b/drivers/md/dm-snap-persistent.c
index b93476c3ba3f..c5534d294773 100644
--- a/drivers/md/dm-snap-persistent.c
+++ b/drivers/md/dm-snap-persistent.c
@@ -741,7 +741,8 @@ static void persistent_commit_exception(struct dm_exception_store *store,
/*
* Commit exceptions to disk.
*/
- if (ps->valid && area_io(ps, REQ_OP_WRITE, REQ_PREFLUSH | REQ_FUA))
+ if (ps->valid && area_io(ps, REQ_OP_WRITE,
+ REQ_PREFLUSH | REQ_FUA | REQ_SYNC))
ps->valid = 0;
/*
diff --git a/drivers/md/dm-snap.c b/drivers/md/dm-snap.c
index e152d9817c81..1ba41048b438 100644
--- a/drivers/md/dm-snap.c
+++ b/drivers/md/dm-snap.c
@@ -1590,7 +1590,7 @@ static void full_bio_end_io(struct bio *bio)
{
void *callback_data = bio->bi_private;
- dm_kcopyd_do_callback(callback_data, 0, bio->bi_error ? 1 : 0);
+ dm_kcopyd_do_callback(callback_data, 0, bio->bi_status ? 1 : 0);
}
static void start_full_bio(struct dm_snap_pending_exception *pe,
@@ -1690,7 +1690,7 @@ static int snapshot_map(struct dm_target *ti, struct bio *bio)
/* Full snapshots are not usable */
/* To get here the table must be live so s->active is always set. */
if (!s->valid)
- return -EIO;
+ return DM_MAPIO_KILL;
/* FIXME: should only take write lock if we need
* to copy an exception */
@@ -1698,7 +1698,7 @@ static int snapshot_map(struct dm_target *ti, struct bio *bio)
if (!s->valid || (unlikely(s->snapshot_overflowed) &&
bio_data_dir(bio) == WRITE)) {
- r = -EIO;
+ r = DM_MAPIO_KILL;
goto out_unlock;
}
@@ -1723,7 +1723,7 @@ static int snapshot_map(struct dm_target *ti, struct bio *bio)
if (!s->valid || s->snapshot_overflowed) {
free_pending_exception(pe);
- r = -EIO;
+ r = DM_MAPIO_KILL;
goto out_unlock;
}
@@ -1741,7 +1741,7 @@ static int snapshot_map(struct dm_target *ti, struct bio *bio)
DMERR("Snapshot overflowed: Unable to allocate exception.");
} else
__invalidate_snapshot(s, -ENOMEM);
- r = -EIO;
+ r = DM_MAPIO_KILL;
goto out_unlock;
}
}
@@ -1851,14 +1851,15 @@ out_unlock:
return r;
}
-static int snapshot_end_io(struct dm_target *ti, struct bio *bio, int error)
+static int snapshot_end_io(struct dm_target *ti, struct bio *bio,
+ blk_status_t *error)
{
struct dm_snapshot *s = ti->private;
if (is_bio_tracked(bio))
stop_tracking_chunk(s, bio);
- return 0;
+ return DM_ENDIO_DONE;
}
static void snapshot_merge_presuspend(struct dm_target *ti)
diff --git a/drivers/md/dm-stripe.c b/drivers/md/dm-stripe.c
index 75152482f3ad..11621a0af887 100644
--- a/drivers/md/dm-stripe.c
+++ b/drivers/md/dm-stripe.c
@@ -375,20 +375,21 @@ static void stripe_status(struct dm_target *ti, status_type_t type,
}
}
-static int stripe_end_io(struct dm_target *ti, struct bio *bio, int error)
+static int stripe_end_io(struct dm_target *ti, struct bio *bio,
+ blk_status_t *error)
{
unsigned i;
char major_minor[16];
struct stripe_c *sc = ti->private;
- if (!error)
- return 0; /* I/O complete */
+ if (!*error)
+ return DM_ENDIO_DONE; /* I/O complete */
- if ((error == -EWOULDBLOCK) && (bio->bi_opf & REQ_RAHEAD))
- return error;
+ if (bio->bi_opf & REQ_RAHEAD)
+ return DM_ENDIO_DONE;
- if (error == -EOPNOTSUPP)
- return error;
+ if (*error == BLK_STS_NOTSUPP)
+ return DM_ENDIO_DONE;
memset(major_minor, 0, sizeof(major_minor));
sprintf(major_minor, "%d:%d",
@@ -409,7 +410,7 @@ static int stripe_end_io(struct dm_target *ti, struct bio *bio, int error)
schedule_work(&sc->trigger_event);
}
- return error;
+ return DM_ENDIO_DONE;
}
static int stripe_iterate_devices(struct dm_target *ti,
diff --git a/drivers/md/dm-target.c b/drivers/md/dm-target.c
index b242b750542f..c0d7e60820c4 100644
--- a/drivers/md/dm-target.c
+++ b/drivers/md/dm-target.c
@@ -128,7 +128,7 @@ static void io_err_dtr(struct dm_target *tt)
static int io_err_map(struct dm_target *tt, struct bio *bio)
{
- return -EIO;
+ return DM_MAPIO_KILL;
}
static int io_err_clone_and_map_rq(struct dm_target *ti, struct request *rq,
diff --git a/drivers/md/dm-thin.c b/drivers/md/dm-thin.c
index 17ad50daed08..9dec2f8cc739 100644
--- a/drivers/md/dm-thin.c
+++ b/drivers/md/dm-thin.c
@@ -383,8 +383,8 @@ static void end_discard(struct discard_op *op, int r)
* Even if r is set, there could be sub discards in flight that we
* need to wait for.
*/
- if (r && !op->parent_bio->bi_error)
- op->parent_bio->bi_error = r;
+ if (r && !op->parent_bio->bi_status)
+ op->parent_bio->bi_status = errno_to_blk_status(r);
bio_endio(op->parent_bio);
}
@@ -450,22 +450,20 @@ static void cell_release_no_holder(struct pool *pool,
}
static void cell_error_with_code(struct pool *pool,
- struct dm_bio_prison_cell *cell, int error_code)
+ struct dm_bio_prison_cell *cell, blk_status_t error_code)
{
dm_cell_error(pool->prison, cell, error_code);
dm_bio_prison_free_cell(pool->prison, cell);
}
-static int get_pool_io_error_code(struct pool *pool)
+static blk_status_t get_pool_io_error_code(struct pool *pool)
{
- return pool->out_of_data_space ? -ENOSPC : -EIO;
+ return pool->out_of_data_space ? BLK_STS_NOSPC : BLK_STS_IOERR;
}
static void cell_error(struct pool *pool, struct dm_bio_prison_cell *cell)
{
- int error = get_pool_io_error_code(pool);
-
- cell_error_with_code(pool, cell, error);
+ cell_error_with_code(pool, cell, get_pool_io_error_code(pool));
}
static void cell_success(struct pool *pool, struct dm_bio_prison_cell *cell)
@@ -475,7 +473,7 @@ static void cell_success(struct pool *pool, struct dm_bio_prison_cell *cell)
static void cell_requeue(struct pool *pool, struct dm_bio_prison_cell *cell)
{
- cell_error_with_code(pool, cell, DM_ENDIO_REQUEUE);
+ cell_error_with_code(pool, cell, BLK_STS_DM_REQUEUE);
}
/*----------------------------------------------------------------*/
@@ -555,17 +553,18 @@ static void __merge_bio_list(struct bio_list *bios, struct bio_list *master)
bio_list_init(master);
}
-static void error_bio_list(struct bio_list *bios, int error)
+static void error_bio_list(struct bio_list *bios, blk_status_t error)
{
struct bio *bio;
while ((bio = bio_list_pop(bios))) {
- bio->bi_error = error;
+ bio->bi_status = error;
bio_endio(bio);
}
}
-static void error_thin_bio_list(struct thin_c *tc, struct bio_list *master, int error)
+static void error_thin_bio_list(struct thin_c *tc, struct bio_list *master,
+ blk_status_t error)
{
struct bio_list bios;
unsigned long flags;
@@ -608,11 +607,11 @@ static void requeue_io(struct thin_c *tc)
__merge_bio_list(&bios, &tc->retry_on_resume_list);
spin_unlock_irqrestore(&tc->lock, flags);
- error_bio_list(&bios, DM_ENDIO_REQUEUE);
+ error_bio_list(&bios, BLK_STS_DM_REQUEUE);
requeue_deferred_cells(tc);
}
-static void error_retry_list_with_code(struct pool *pool, int error)
+static void error_retry_list_with_code(struct pool *pool, blk_status_t error)
{
struct thin_c *tc;
@@ -624,9 +623,7 @@ static void error_retry_list_with_code(struct pool *pool, int error)
static void error_retry_list(struct pool *pool)
{
- int error = get_pool_io_error_code(pool);
-
- error_retry_list_with_code(pool, error);
+ error_retry_list_with_code(pool, get_pool_io_error_code(pool));
}
/*
@@ -774,7 +771,7 @@ struct dm_thin_new_mapping {
*/
atomic_t prepare_actions;
- int err;
+ blk_status_t status;
struct thin_c *tc;
dm_block_t virt_begin, virt_end;
dm_block_t data_block;
@@ -814,7 +811,7 @@ static void copy_complete(int read_err, unsigned long write_err, void *context)
{
struct dm_thin_new_mapping *m = context;
- m->err = read_err || write_err ? -EIO : 0;
+ m->status = read_err || write_err ? BLK_STS_IOERR : 0;
complete_mapping_preparation(m);
}
@@ -825,7 +822,7 @@ static void overwrite_endio(struct bio *bio)
bio->bi_end_io = m->saved_bi_end_io;
- m->err = bio->bi_error;
+ m->status = bio->bi_status;
complete_mapping_preparation(m);
}
@@ -925,7 +922,7 @@ static void process_prepared_mapping(struct dm_thin_new_mapping *m)
struct bio *bio = m->bio;
int r;
- if (m->err) {
+ if (m->status) {
cell_error(pool, m->cell);
goto out;
}
@@ -1094,6 +1091,19 @@ static void process_prepared_discard_passdown_pt1(struct dm_thin_new_mapping *m)
return;
}
+ /*
+ * Increment the unmapped blocks. This prevents a race between the
+ * passdown io and reallocation of freed blocks.
+ */
+ r = dm_pool_inc_data_range(pool->pmd, m->data_block, data_end);
+ if (r) {
+ metadata_operation_failed(pool, "dm_pool_inc_data_range", r);
+ bio_io_error(m->bio);
+ cell_defer_no_holder(tc, m->cell);
+ mempool_free(m, pool->mapping_pool);
+ return;
+ }
+
discard_parent = bio_alloc(GFP_NOIO, 1);
if (!discard_parent) {
DMWARN("%s: unable to allocate top level discard bio for passdown. Skipping passdown.",
@@ -1114,19 +1124,6 @@ static void process_prepared_discard_passdown_pt1(struct dm_thin_new_mapping *m)
end_discard(&op, r);
}
}
-
- /*
- * Increment the unmapped blocks. This prevents a race between the
- * passdown io and reallocation of freed blocks.
- */
- r = dm_pool_inc_data_range(pool->pmd, m->data_block, data_end);
- if (r) {
- metadata_operation_failed(pool, "dm_pool_inc_data_range", r);
- bio_io_error(m->bio);
- cell_defer_no_holder(tc, m->cell);
- mempool_free(m, pool->mapping_pool);
- return;
- }
}
static void process_prepared_discard_passdown_pt2(struct dm_thin_new_mapping *m)
@@ -1495,7 +1492,7 @@ static void retry_on_resume(struct bio *bio)
spin_unlock_irqrestore(&tc->lock, flags);
}
-static int should_error_unserviceable_bio(struct pool *pool)
+static blk_status_t should_error_unserviceable_bio(struct pool *pool)
{
enum pool_mode m = get_pool_mode(pool);
@@ -1503,27 +1500,27 @@ static int should_error_unserviceable_bio(struct pool *pool)
case PM_WRITE:
/* Shouldn't get here */
DMERR_LIMIT("bio unserviceable, yet pool is in PM_WRITE mode");
- return -EIO;
+ return BLK_STS_IOERR;
case PM_OUT_OF_DATA_SPACE:
- return pool->pf.error_if_no_space ? -ENOSPC : 0;
+ return pool->pf.error_if_no_space ? BLK_STS_NOSPC : 0;
case PM_READ_ONLY:
case PM_FAIL:
- return -EIO;
+ return BLK_STS_IOERR;
default:
/* Shouldn't get here */
DMERR_LIMIT("bio unserviceable, yet pool has an unknown mode");
- return -EIO;
+ return BLK_STS_IOERR;
}
}
static void handle_unserviceable_bio(struct pool *pool, struct bio *bio)
{
- int error = should_error_unserviceable_bio(pool);
+ blk_status_t error = should_error_unserviceable_bio(pool);
if (error) {
- bio->bi_error = error;
+ bio->bi_status = error;
bio_endio(bio);
} else
retry_on_resume(bio);
@@ -1533,7 +1530,7 @@ static void retry_bios_on_resume(struct pool *pool, struct dm_bio_prison_cell *c
{
struct bio *bio;
struct bio_list bios;
- int error;
+ blk_status_t error;
error = should_error_unserviceable_bio(pool);
if (error) {
@@ -2071,7 +2068,8 @@ static void process_thin_deferred_bios(struct thin_c *tc)
unsigned count = 0;
if (tc->requeue_mode) {
- error_thin_bio_list(tc, &tc->deferred_bio_list, DM_ENDIO_REQUEUE);
+ error_thin_bio_list(tc, &tc->deferred_bio_list,
+ BLK_STS_DM_REQUEUE);
return;
}
@@ -2322,7 +2320,7 @@ static void do_no_space_timeout(struct work_struct *ws)
if (get_pool_mode(pool) == PM_OUT_OF_DATA_SPACE && !pool->pf.error_if_no_space) {
pool->pf.error_if_no_space = true;
notify_of_pool_mode_change_to_oods(pool);
- error_retry_list_with_code(pool, -ENOSPC);
+ error_retry_list_with_code(pool, BLK_STS_NOSPC);
}
}
@@ -2624,7 +2622,7 @@ static int thin_bio_map(struct dm_target *ti, struct bio *bio)
thin_hook_bio(tc, bio);
if (tc->requeue_mode) {
- bio->bi_error = DM_ENDIO_REQUEUE;
+ bio->bi_status = BLK_STS_DM_REQUEUE;
bio_endio(bio);
return DM_MAPIO_SUBMITTED;
}
@@ -4177,7 +4175,8 @@ static int thin_map(struct dm_target *ti, struct bio *bio)
return thin_bio_map(ti, bio);
}
-static int thin_endio(struct dm_target *ti, struct bio *bio, int err)
+static int thin_endio(struct dm_target *ti, struct bio *bio,
+ blk_status_t *err)
{
unsigned long flags;
struct dm_thin_endio_hook *h = dm_per_bio_data(bio, sizeof(struct dm_thin_endio_hook));
@@ -4212,7 +4211,7 @@ static int thin_endio(struct dm_target *ti, struct bio *bio, int err)
if (h->cell)
cell_defer_no_holder(h->tc, h->cell);
- return 0;
+ return DM_ENDIO_DONE;
}
static void thin_presuspend(struct dm_target *ti)
diff --git a/drivers/md/dm-verity-target.c b/drivers/md/dm-verity-target.c
index 97de961a3bfc..b46705ebf01f 100644
--- a/drivers/md/dm-verity-target.c
+++ b/drivers/md/dm-verity-target.c
@@ -166,7 +166,7 @@ static int verity_hash_init(struct dm_verity *v, struct ahash_request *req,
return r;
}
- if (likely(v->version >= 1))
+ if (likely(v->salt_size && (v->version >= 1)))
r = verity_hash_update(v, req, v->salt, v->salt_size, res);
return r;
@@ -177,7 +177,7 @@ static int verity_hash_final(struct dm_verity *v, struct ahash_request *req,
{
int r;
- if (unlikely(!v->version)) {
+ if (unlikely(v->salt_size && (!v->version))) {
r = verity_hash_update(v, req, v->salt, v->salt_size, res);
if (r < 0) {
@@ -538,13 +538,13 @@ static int verity_verify_io(struct dm_verity_io *io)
/*
* End one "io" structure with a given error.
*/
-static void verity_finish_io(struct dm_verity_io *io, int error)
+static void verity_finish_io(struct dm_verity_io *io, blk_status_t status)
{
struct dm_verity *v = io->v;
struct bio *bio = dm_bio_from_per_bio_data(io, v->ti->per_io_data_size);
bio->bi_end_io = io->orig_bi_end_io;
- bio->bi_error = error;
+ bio->bi_status = status;
verity_fec_finish_io(io);
@@ -555,15 +555,15 @@ static void verity_work(struct work_struct *w)
{
struct dm_verity_io *io = container_of(w, struct dm_verity_io, work);
- verity_finish_io(io, verity_verify_io(io));
+ verity_finish_io(io, errno_to_blk_status(verity_verify_io(io)));
}
static void verity_end_io(struct bio *bio)
{
struct dm_verity_io *io = bio->bi_private;
- if (bio->bi_error && !verity_fec_is_enabled(io->v)) {
- verity_finish_io(io, bio->bi_error);
+ if (bio->bi_status && !verity_fec_is_enabled(io->v)) {
+ verity_finish_io(io, bio->bi_status);
return;
}
@@ -643,17 +643,17 @@ static int verity_map(struct dm_target *ti, struct bio *bio)
if (((unsigned)bio->bi_iter.bi_sector | bio_sectors(bio)) &
((1 << (v->data_dev_block_bits - SECTOR_SHIFT)) - 1)) {
DMERR_LIMIT("unaligned io");
- return -EIO;
+ return DM_MAPIO_KILL;
}
if (bio_end_sector(bio) >>
(v->data_dev_block_bits - SECTOR_SHIFT) > v->data_blocks) {
DMERR_LIMIT("io out of range");
- return -EIO;
+ return DM_MAPIO_KILL;
}
if (bio_data_dir(bio) == WRITE)
- return -EIO;
+ return DM_MAPIO_KILL;
io = dm_per_bio_data(bio, ti->per_io_data_size);
io->v = v;
diff --git a/drivers/md/dm-zero.c b/drivers/md/dm-zero.c
index b616f11d8473..b65ca8dcfbdc 100644
--- a/drivers/md/dm-zero.c
+++ b/drivers/md/dm-zero.c
@@ -39,7 +39,7 @@ static int zero_map(struct dm_target *ti, struct bio *bio)
case REQ_OP_READ:
if (bio->bi_opf & REQ_RAHEAD) {
/* readahead of null bytes only wastes buffer cache */
- return -EIO;
+ return DM_MAPIO_KILL;
}
zero_fill_bio(bio);
break;
@@ -47,7 +47,7 @@ static int zero_map(struct dm_target *ti, struct bio *bio)
/* writes get silently dropped */
break;
default:
- return -EIO;
+ return DM_MAPIO_KILL;
}
bio_endio(bio);
diff --git a/drivers/md/dm.c b/drivers/md/dm.c
index 6ef9500226c0..402946035308 100644
--- a/drivers/md/dm.c
+++ b/drivers/md/dm.c
@@ -63,7 +63,7 @@ static struct workqueue_struct *deferred_remove_workqueue;
*/
struct dm_io {
struct mapped_device *md;
- int error;
+ blk_status_t status;
atomic_t io_count;
struct bio *bio;
unsigned long start_time;
@@ -768,23 +768,24 @@ static int __noflush_suspending(struct mapped_device *md)
* Decrements the number of outstanding ios that a bio has been
* cloned into, completing the original io if necc.
*/
-static void dec_pending(struct dm_io *io, int error)
+static void dec_pending(struct dm_io *io, blk_status_t error)
{
unsigned long flags;
- int io_error;
+ blk_status_t io_error;
struct bio *bio;
struct mapped_device *md = io->md;
/* Push-back supersedes any I/O errors */
if (unlikely(error)) {
spin_lock_irqsave(&io->endio_lock, flags);
- if (!(io->error > 0 && __noflush_suspending(md)))
- io->error = error;
+ if (!(io->status == BLK_STS_DM_REQUEUE &&
+ __noflush_suspending(md)))
+ io->status = error;
spin_unlock_irqrestore(&io->endio_lock, flags);
}
if (atomic_dec_and_test(&io->io_count)) {
- if (io->error == DM_ENDIO_REQUEUE) {
+ if (io->status == BLK_STS_DM_REQUEUE) {
/*
* Target requested pushing back the I/O.
*/
@@ -793,16 +794,16 @@ static void dec_pending(struct dm_io *io, int error)
bio_list_add_head(&md->deferred, io->bio);
else
/* noflush suspend was interrupted. */
- io->error = -EIO;
+ io->status = BLK_STS_IOERR;
spin_unlock_irqrestore(&md->deferred_lock, flags);
}
- io_error = io->error;
+ io_error = io->status;
bio = io->bio;
end_io_acct(io);
free_io(md, io);
- if (io_error == DM_ENDIO_REQUEUE)
+ if (io_error == BLK_STS_DM_REQUEUE)
return;
if ((bio->bi_opf & REQ_PREFLUSH) && bio->bi_iter.bi_size) {
@@ -814,7 +815,7 @@ static void dec_pending(struct dm_io *io, int error)
queue_io(md, bio);
} else {
/* done with normal IO or empty flush */
- bio->bi_error = io_error;
+ bio->bi_status = io_error;
bio_endio(bio);
}
}
@@ -838,31 +839,13 @@ void disable_write_zeroes(struct mapped_device *md)
static void clone_endio(struct bio *bio)
{
- int error = bio->bi_error;
- int r = error;
+ blk_status_t error = bio->bi_status;
struct dm_target_io *tio = container_of(bio, struct dm_target_io, clone);
struct dm_io *io = tio->io;
struct mapped_device *md = tio->io->md;
dm_endio_fn endio = tio->ti->type->end_io;
- if (endio) {
- r = endio(tio->ti, bio, error);
- if (r < 0 || r == DM_ENDIO_REQUEUE)
- /*
- * error and requeue request are handled
- * in dec_pending().
- */
- error = r;
- else if (r == DM_ENDIO_INCOMPLETE)
- /* The target will handle the io */
- return;
- else if (r) {
- DMWARN("unimplemented target endio return value: %d", r);
- BUG();
- }
- }
-
- if (unlikely(r == -EREMOTEIO)) {
+ if (unlikely(error == BLK_STS_TARGET)) {
if (bio_op(bio) == REQ_OP_WRITE_SAME &&
!bdev_get_queue(bio->bi_bdev)->limits.max_write_same_sectors)
disable_write_same(md);
@@ -871,6 +854,23 @@ static void clone_endio(struct bio *bio)
disable_write_zeroes(md);
}
+ if (endio) {
+ int r = endio(tio->ti, bio, &error);
+ switch (r) {
+ case DM_ENDIO_REQUEUE:
+ error = BLK_STS_DM_REQUEUE;
+ /*FALLTHRU*/
+ case DM_ENDIO_DONE:
+ break;
+ case DM_ENDIO_INCOMPLETE:
+ /* The target will handle the io */
+ return;
+ default:
+ DMWARN("unimplemented target endio return value: %d", r);
+ BUG();
+ }
+ }
+
free_tio(tio);
dec_pending(io, error);
}
@@ -1036,7 +1036,8 @@ static void flush_current_bio_list(struct blk_plug_cb *cb, bool from_schedule)
while ((bio = bio_list_pop(&list))) {
struct bio_set *bs = bio->bi_pool;
- if (unlikely(!bs) || bs == fs_bio_set) {
+ if (unlikely(!bs) || bs == fs_bio_set ||
+ !bs->rescue_workqueue) {
bio_list_add(&current->bio_list[i], bio);
continue;
}
@@ -1084,18 +1085,24 @@ static void __map_bio(struct dm_target_io *tio)
r = ti->type->map(ti, clone);
dm_offload_end(&o);
- if (r == DM_MAPIO_REMAPPED) {
+ switch (r) {
+ case DM_MAPIO_SUBMITTED:
+ break;
+ case DM_MAPIO_REMAPPED:
/* the bio has been remapped so dispatch it */
-
trace_block_bio_remap(bdev_get_queue(clone->bi_bdev), clone,
tio->io->bio->bi_bdev->bd_dev, sector);
-
generic_make_request(clone);
- } else if (r < 0 || r == DM_MAPIO_REQUEUE) {
- /* error the io and bail out, or requeue it if needed */
- dec_pending(tio->io, r);
+ break;
+ case DM_MAPIO_KILL:
+ dec_pending(tio->io, BLK_STS_IOERR);
+ free_tio(tio);
+ break;
+ case DM_MAPIO_REQUEUE:
+ dec_pending(tio->io, BLK_STS_DM_REQUEUE);
free_tio(tio);
- } else if (r != DM_MAPIO_SUBMITTED) {
+ break;
+ default:
DMWARN("unimplemented target map return value: %d", r);
BUG();
}
@@ -1360,7 +1367,7 @@ static void __split_and_process_bio(struct mapped_device *md,
ci.map = map;
ci.md = md;
ci.io = alloc_io(md);
- ci.io->error = 0;
+ ci.io->status = 0;
atomic_set(&ci.io->io_count, 1);
ci.io->bio = bio;
ci.io->md = md;
@@ -1527,7 +1534,6 @@ void dm_init_normal_md_queue(struct mapped_device *md)
* Initialize aspects of queue that aren't relevant for blk-mq
*/
md->queue->backing_dev_info->congested_fn = dm_any_congested;
- blk_queue_bounce_limit(md->queue, BLK_BOUNCE_ANY);
}
static void cleanup_mapped_device(struct mapped_device *md)
@@ -1657,7 +1663,7 @@ static struct mapped_device *alloc_dev(int minor)
bio_init(&md->flush_bio, NULL, 0);
md->flush_bio.bi_bdev = md->bdev;
- md->flush_bio.bi_opf = REQ_OP_WRITE | REQ_PREFLUSH;
+ md->flush_bio.bi_opf = REQ_OP_WRITE | REQ_PREFLUSH | REQ_SYNC;
dm_stats_init(&md->stats);
@@ -2654,7 +2660,7 @@ struct dm_md_mempools *dm_alloc_md_mempools(struct mapped_device *md, enum dm_qu
BUG();
}
- pools->bs = bioset_create_nobvec(pool_size, front_pad);
+ pools->bs = bioset_create(pool_size, front_pad, BIOSET_NEED_RESCUER);
if (!pools->bs)
goto out;
diff --git a/drivers/md/md-cluster.c b/drivers/md/md-cluster.c
index 7299ce2f08a8..03082e17c65c 100644
--- a/drivers/md/md-cluster.c
+++ b/drivers/md/md-cluster.c
@@ -1311,8 +1311,10 @@ static int add_new_disk(struct mddev *mddev, struct md_rdev *rdev)
cmsg.raid_slot = cpu_to_le32(rdev->desc_nr);
lock_comm(cinfo, 1);
ret = __sendmsg(cinfo, &cmsg);
- if (ret)
+ if (ret) {
+ unlock_comm(cinfo);
return ret;
+ }
cinfo->no_new_dev_lockres->flags |= DLM_LKF_NOQUEUE;
ret = dlm_lock_sync(cinfo->no_new_dev_lockres, DLM_LOCK_EX);
cinfo->no_new_dev_lockres->flags &= ~DLM_LKF_NOQUEUE;
diff --git a/drivers/md/md.c b/drivers/md/md.c
index 10367ffe92e3..31bcbfb09fef 100644
--- a/drivers/md/md.c
+++ b/drivers/md/md.c
@@ -185,7 +185,7 @@ static int start_readonly;
static bool create_on_open = true;
/* bio_clone_mddev
- * like bio_clone, but with a local bio set
+ * like bio_clone_bioset, but with a local bio set
*/
struct bio *bio_alloc_mddev(gfp_t gfp_mask, int nr_iovecs,
@@ -265,7 +265,7 @@ static blk_qc_t md_make_request(struct request_queue *q, struct bio *bio)
unsigned int sectors;
int cpu;
- blk_queue_split(q, &bio, q->bio_split);
+ blk_queue_split(q, &bio);
if (mddev == NULL || mddev->pers == NULL) {
bio_io_error(bio);
@@ -273,7 +273,7 @@ static blk_qc_t md_make_request(struct request_queue *q, struct bio *bio)
}
if (mddev->ro == 1 && unlikely(rw == WRITE)) {
if (bio_sectors(bio) != 0)
- bio->bi_error = -EROFS;
+ bio->bi_status = BLK_STS_IOERR;
bio_endio(bio);
return BLK_QC_T_NONE;
}
@@ -719,8 +719,8 @@ static void super_written(struct bio *bio)
struct md_rdev *rdev = bio->bi_private;
struct mddev *mddev = rdev->mddev;
- if (bio->bi_error) {
- pr_err("md: super_written gets error=%d\n", bio->bi_error);
+ if (bio->bi_status) {
+ pr_err("md: super_written gets error=%d\n", bio->bi_status);
md_error(mddev, rdev);
if (!test_bit(Faulty, &rdev->flags)
&& (bio->bi_opf & MD_FAILFAST)) {
@@ -765,7 +765,7 @@ void md_super_write(struct mddev *mddev, struct md_rdev *rdev,
test_bit(FailFast, &rdev->flags) &&
!test_bit(LastDev, &rdev->flags))
ff = MD_FAILFAST;
- bio->bi_opf = REQ_OP_WRITE | REQ_PREFLUSH | REQ_FUA | ff;
+ bio->bi_opf = REQ_OP_WRITE | REQ_SYNC | REQ_PREFLUSH | REQ_FUA | ff;
atomic_inc(&mddev->pending_writes);
submit_bio(bio);
@@ -801,7 +801,7 @@ int sync_page_io(struct md_rdev *rdev, sector_t sector, int size,
submit_bio_wait(bio);
- ret = !bio->bi_error;
+ ret = !bio->bi_status;
bio_put(bio);
return ret;
}
@@ -825,7 +825,7 @@ fail:
return -EINVAL;
}
-static int uuid_equal(mdp_super_t *sb1, mdp_super_t *sb2)
+static int md_uuid_equal(mdp_super_t *sb1, mdp_super_t *sb2)
{
return sb1->set_uuid0 == sb2->set_uuid0 &&
sb1->set_uuid1 == sb2->set_uuid1 &&
@@ -833,7 +833,7 @@ static int uuid_equal(mdp_super_t *sb1, mdp_super_t *sb2)
sb1->set_uuid3 == sb2->set_uuid3;
}
-static int sb_equal(mdp_super_t *sb1, mdp_super_t *sb2)
+static int md_sb_equal(mdp_super_t *sb1, mdp_super_t *sb2)
{
int ret;
mdp_super_t *tmp1, *tmp2;
@@ -1025,12 +1025,12 @@ static int super_90_load(struct md_rdev *rdev, struct md_rdev *refdev, int minor
} else {
__u64 ev1, ev2;
mdp_super_t *refsb = page_address(refdev->sb_page);
- if (!uuid_equal(refsb, sb)) {
+ if (!md_uuid_equal(refsb, sb)) {
pr_warn("md: %s has different UUID to %s\n",
b, bdevname(refdev->bdev,b2));
goto abort;
}
- if (!sb_equal(refsb, sb)) {
+ if (!md_sb_equal(refsb, sb)) {
pr_warn("md: %s has same UUID but different superblock to %s\n",
b, bdevname(refdev->bdev, b2));
goto abort;
@@ -5174,6 +5174,18 @@ static void mddev_delayed_delete(struct work_struct *ws)
static void no_op(struct percpu_ref *r) {}
+int mddev_init_writes_pending(struct mddev *mddev)
+{
+ if (mddev->writes_pending.percpu_count_ptr)
+ return 0;
+ if (percpu_ref_init(&mddev->writes_pending, no_op, 0, GFP_KERNEL) < 0)
+ return -ENOMEM;
+ /* We want to start with the refcount at zero */
+ percpu_ref_put(&mddev->writes_pending);
+ return 0;
+}
+EXPORT_SYMBOL_GPL(mddev_init_writes_pending);
+
static int md_alloc(dev_t dev, char *name)
{
/*
@@ -5239,10 +5251,6 @@ static int md_alloc(dev_t dev, char *name)
blk_queue_make_request(mddev->queue, md_make_request);
blk_set_stacking_limits(&mddev->queue->limits);
- if (percpu_ref_init(&mddev->writes_pending, no_op, 0, GFP_KERNEL) < 0)
- goto abort;
- /* We want to start with the refcount at zero */
- percpu_ref_put(&mddev->writes_pending);
disk = alloc_disk(1 << shift);
if (!disk) {
blk_cleanup_queue(mddev->queue);
@@ -5420,7 +5428,7 @@ int md_run(struct mddev *mddev)
}
if (mddev->bio_set == NULL) {
- mddev->bio_set = bioset_create(BIO_POOL_SIZE, 0);
+ mddev->bio_set = bioset_create(BIO_POOL_SIZE, 0, BIOSET_NEED_BVECS);
if (!mddev->bio_set)
return -ENOMEM;
}
diff --git a/drivers/md/md.h b/drivers/md/md.h
index 11f15146ce51..0fa1de42c42b 100644
--- a/drivers/md/md.h
+++ b/drivers/md/md.h
@@ -648,6 +648,7 @@ extern void md_unregister_thread(struct md_thread **threadp);
extern void md_wakeup_thread(struct md_thread *thread);
extern void md_check_recovery(struct mddev *mddev);
extern void md_reap_sync_thread(struct mddev *mddev);
+extern int mddev_init_writes_pending(struct mddev *mddev);
extern void md_write_start(struct mddev *mddev, struct bio *bi);
extern void md_write_inc(struct mddev *mddev, struct bio *bi);
extern void md_write_end(struct mddev *mddev);
diff --git a/drivers/md/multipath.c b/drivers/md/multipath.c
index e95d521d93e9..68d036e64041 100644
--- a/drivers/md/multipath.c
+++ b/drivers/md/multipath.c
@@ -73,12 +73,12 @@ static void multipath_reschedule_retry (struct multipath_bh *mp_bh)
* operation and are ready to return a success/failure code to the buffer
* cache layer.
*/
-static void multipath_end_bh_io (struct multipath_bh *mp_bh, int err)
+static void multipath_end_bh_io(struct multipath_bh *mp_bh, blk_status_t status)
{
struct bio *bio = mp_bh->master_bio;
struct mpconf *conf = mp_bh->mddev->private;
- bio->bi_error = err;
+ bio->bi_status = status;
bio_endio(bio);
mempool_free(mp_bh, conf->pool);
}
@@ -89,7 +89,7 @@ static void multipath_end_request(struct bio *bio)
struct mpconf *conf = mp_bh->mddev->private;
struct md_rdev *rdev = conf->multipaths[mp_bh->path].rdev;
- if (!bio->bi_error)
+ if (!bio->bi_status)
multipath_end_bh_io(mp_bh, 0);
else if (!(bio->bi_opf & REQ_RAHEAD)) {
/*
@@ -102,7 +102,7 @@ static void multipath_end_request(struct bio *bio)
(unsigned long long)bio->bi_iter.bi_sector);
multipath_reschedule_retry(mp_bh);
} else
- multipath_end_bh_io(mp_bh, bio->bi_error);
+ multipath_end_bh_io(mp_bh, bio->bi_status);
rdev_dec_pending(rdev, conf->mddev);
}
@@ -347,7 +347,7 @@ static void multipathd(struct md_thread *thread)
pr_err("multipath: %s: unrecoverable IO read error for block %llu\n",
bdevname(bio->bi_bdev,b),
(unsigned long long)bio->bi_iter.bi_sector);
- multipath_end_bh_io(mp_bh, -EIO);
+ multipath_end_bh_io(mp_bh, BLK_STS_IOERR);
} else {
pr_err("multipath: %s: redirecting sector %llu to another IO path\n",
bdevname(bio->bi_bdev,b),
diff --git a/drivers/md/raid1.c b/drivers/md/raid1.c
index af5056d56878..98ca2c1d3226 100644
--- a/drivers/md/raid1.c
+++ b/drivers/md/raid1.c
@@ -277,7 +277,7 @@ static void call_bio_endio(struct r1bio *r1_bio)
struct r1conf *conf = r1_bio->mddev->private;
if (!test_bit(R1BIO_Uptodate, &r1_bio->state))
- bio->bi_error = -EIO;
+ bio->bi_status = BLK_STS_IOERR;
bio_endio(bio);
/*
@@ -335,7 +335,7 @@ static int find_bio_disk(struct r1bio *r1_bio, struct bio *bio)
static void raid1_end_read_request(struct bio *bio)
{
- int uptodate = !bio->bi_error;
+ int uptodate = !bio->bi_status;
struct r1bio *r1_bio = bio->bi_private;
struct r1conf *conf = r1_bio->mddev->private;
struct md_rdev *rdev = conf->mirrors[r1_bio->read_disk].rdev;
@@ -426,12 +426,12 @@ static void raid1_end_write_request(struct bio *bio)
struct md_rdev *rdev = conf->mirrors[mirror].rdev;
bool discard_error;
- discard_error = bio->bi_error && bio_op(bio) == REQ_OP_DISCARD;
+ discard_error = bio->bi_status && bio_op(bio) == REQ_OP_DISCARD;
/*
* 'one mirror IO has finished' event handler:
*/
- if (bio->bi_error && !discard_error) {
+ if (bio->bi_status && !discard_error) {
set_bit(WriteErrorSeen, &rdev->flags);
if (!test_and_set_bit(WantReplacement, &rdev->flags))
set_bit(MD_RECOVERY_NEEDED, &
@@ -802,7 +802,7 @@ static void flush_bio_list(struct r1conf *conf, struct bio *bio)
bio->bi_next = NULL;
bio->bi_bdev = rdev->bdev;
if (test_bit(Faulty, &rdev->flags)) {
- bio->bi_error = -EIO;
+ bio->bi_status = BLK_STS_IOERR;
bio_endio(bio);
} else if (unlikely((bio_op(bio) == REQ_OP_DISCARD) &&
!blk_queue_discard(bdev_get_queue(bio->bi_bdev))))
@@ -1856,7 +1856,7 @@ static void end_sync_read(struct bio *bio)
* or re-read if the read failed.
* We don't do much here, just schedule handling by raid1d
*/
- if (!bio->bi_error)
+ if (!bio->bi_status)
set_bit(R1BIO_Uptodate, &r1_bio->state);
if (atomic_dec_and_test(&r1_bio->remaining))
@@ -1865,7 +1865,7 @@ static void end_sync_read(struct bio *bio)
static void end_sync_write(struct bio *bio)
{
- int uptodate = !bio->bi_error;
+ int uptodate = !bio->bi_status;
struct r1bio *r1_bio = get_resync_r1bio(bio);
struct mddev *mddev = r1_bio->mddev;
struct r1conf *conf = mddev->private;
@@ -2058,7 +2058,7 @@ static int fix_sync_read_error(struct r1bio *r1_bio)
idx ++;
}
set_bit(R1BIO_Uptodate, &r1_bio->state);
- bio->bi_error = 0;
+ bio->bi_status = 0;
return 1;
}
@@ -2082,16 +2082,16 @@ static void process_checks(struct r1bio *r1_bio)
for (i = 0; i < conf->raid_disks * 2; i++) {
int j;
int size;
- int error;
+ blk_status_t status;
struct bio_vec *bi;
struct bio *b = r1_bio->bios[i];
struct resync_pages *rp = get_resync_pages(b);
if (b->bi_end_io != end_sync_read)
continue;
/* fixup the bio for reuse, but preserve errno */
- error = b->bi_error;
+ status = b->bi_status;
bio_reset(b);
- b->bi_error = error;
+ b->bi_status = status;
b->bi_vcnt = vcnt;
b->bi_iter.bi_size = r1_bio->sectors << 9;
b->bi_iter.bi_sector = r1_bio->sector +
@@ -2113,7 +2113,7 @@ static void process_checks(struct r1bio *r1_bio)
}
for (primary = 0; primary < conf->raid_disks * 2; primary++)
if (r1_bio->bios[primary]->bi_end_io == end_sync_read &&
- !r1_bio->bios[primary]->bi_error) {
+ !r1_bio->bios[primary]->bi_status) {
r1_bio->bios[primary]->bi_end_io = NULL;
rdev_dec_pending(conf->mirrors[primary].rdev, mddev);
break;
@@ -2123,7 +2123,7 @@ static void process_checks(struct r1bio *r1_bio)
int j;
struct bio *pbio = r1_bio->bios[primary];
struct bio *sbio = r1_bio->bios[i];
- int error = sbio->bi_error;
+ blk_status_t status = sbio->bi_status;
struct page **ppages = get_resync_pages(pbio)->pages;
struct page **spages = get_resync_pages(sbio)->pages;
struct bio_vec *bi;
@@ -2132,12 +2132,12 @@ static void process_checks(struct r1bio *r1_bio)
if (sbio->bi_end_io != end_sync_read)
continue;
/* Now we can 'fixup' the error value */
- sbio->bi_error = 0;
+ sbio->bi_status = 0;
bio_for_each_segment_all(bi, sbio, j)
page_len[j] = bi->bv_len;
- if (!error) {
+ if (!status) {
for (j = vcnt; j-- ; ) {
if (memcmp(page_address(ppages[j]),
page_address(spages[j]),
@@ -2149,7 +2149,7 @@ static void process_checks(struct r1bio *r1_bio)
if (j >= 0)
atomic64_add(r1_bio->sectors, &mddev->resync_mismatches);
if (j < 0 || (test_bit(MD_RECOVERY_CHECK, &mddev->recovery)
- && !error)) {
+ && !status)) {
/* No need to write to this device. */
sbio->bi_end_io = NULL;
rdev_dec_pending(conf->mirrors[i].rdev, mddev);
@@ -2400,11 +2400,11 @@ static void handle_sync_write_finished(struct r1conf *conf, struct r1bio *r1_bio
struct bio *bio = r1_bio->bios[m];
if (bio->bi_end_io == NULL)
continue;
- if (!bio->bi_error &&
+ if (!bio->bi_status &&
test_bit(R1BIO_MadeGood, &r1_bio->state)) {
rdev_clear_badblocks(rdev, r1_bio->sector, s, 0);
}
- if (bio->bi_error &&
+ if (bio->bi_status &&
test_bit(R1BIO_WriteError, &r1_bio->state)) {
if (!rdev_set_badblocks(rdev, r1_bio->sector, s, 0))
md_error(conf->mddev, rdev);
@@ -2955,7 +2955,7 @@ static struct r1conf *setup_conf(struct mddev *mddev)
if (!conf->r1bio_pool)
goto abort;
- conf->bio_split = bioset_create(BIO_POOL_SIZE, 0);
+ conf->bio_split = bioset_create(BIO_POOL_SIZE, 0, 0);
if (!conf->bio_split)
goto abort;
@@ -3063,6 +3063,8 @@ static int raid1_run(struct mddev *mddev)
mdname(mddev));
return -EIO;
}
+ if (mddev_init_writes_pending(mddev) < 0)
+ return -ENOMEM;
/*
* copy the already verified devices into our private RAID1
* bookkeeping area. [whatever we allocate in run(),
diff --git a/drivers/md/raid10.c b/drivers/md/raid10.c
index 4343d7ff9916..57a250fdbbcc 100644
--- a/drivers/md/raid10.c
+++ b/drivers/md/raid10.c
@@ -336,7 +336,7 @@ static void raid_end_bio_io(struct r10bio *r10_bio)
struct r10conf *conf = r10_bio->mddev->private;
if (!test_bit(R10BIO_Uptodate, &r10_bio->state))
- bio->bi_error = -EIO;
+ bio->bi_status = BLK_STS_IOERR;
bio_endio(bio);
/*
@@ -389,7 +389,7 @@ static int find_bio_disk(struct r10conf *conf, struct r10bio *r10_bio,
static void raid10_end_read_request(struct bio *bio)
{
- int uptodate = !bio->bi_error;
+ int uptodate = !bio->bi_status;
struct r10bio *r10_bio = bio->bi_private;
int slot, dev;
struct md_rdev *rdev;
@@ -477,7 +477,7 @@ static void raid10_end_write_request(struct bio *bio)
struct bio *to_put = NULL;
bool discard_error;
- discard_error = bio->bi_error && bio_op(bio) == REQ_OP_DISCARD;
+ discard_error = bio->bi_status && bio_op(bio) == REQ_OP_DISCARD;
dev = find_bio_disk(conf, r10_bio, bio, &slot, &repl);
@@ -491,7 +491,7 @@ static void raid10_end_write_request(struct bio *bio)
/*
* this branch is our 'one mirror IO has finished' event handler:
*/
- if (bio->bi_error && !discard_error) {
+ if (bio->bi_status && !discard_error) {
if (repl)
/* Never record new bad blocks to replacement,
* just fail it.
@@ -913,7 +913,7 @@ static void flush_pending_writes(struct r10conf *conf)
bio->bi_next = NULL;
bio->bi_bdev = rdev->bdev;
if (test_bit(Faulty, &rdev->flags)) {
- bio->bi_error = -EIO;
+ bio->bi_status = BLK_STS_IOERR;
bio_endio(bio);
} else if (unlikely((bio_op(bio) == REQ_OP_DISCARD) &&
!blk_queue_discard(bdev_get_queue(bio->bi_bdev))))
@@ -1098,7 +1098,7 @@ static void raid10_unplug(struct blk_plug_cb *cb, bool from_schedule)
bio->bi_next = NULL;
bio->bi_bdev = rdev->bdev;
if (test_bit(Faulty, &rdev->flags)) {
- bio->bi_error = -EIO;
+ bio->bi_status = BLK_STS_IOERR;
bio_endio(bio);
} else if (unlikely((bio_op(bio) == REQ_OP_DISCARD) &&
!blk_queue_discard(bdev_get_queue(bio->bi_bdev))))
@@ -1888,7 +1888,7 @@ static void __end_sync_read(struct r10bio *r10_bio, struct bio *bio, int d)
{
struct r10conf *conf = r10_bio->mddev->private;
- if (!bio->bi_error)
+ if (!bio->bi_status)
set_bit(R10BIO_Uptodate, &r10_bio->state);
else
/* The write handler will notice the lack of
@@ -1972,7 +1972,7 @@ static void end_sync_write(struct bio *bio)
else
rdev = conf->mirrors[d].rdev;
- if (bio->bi_error) {
+ if (bio->bi_status) {
if (repl)
md_error(mddev, rdev);
else {
@@ -2021,7 +2021,7 @@ static void sync_request_write(struct mddev *mddev, struct r10bio *r10_bio)
/* find the first device with a block */
for (i=0; i<conf->copies; i++)
- if (!r10_bio->devs[i].bio->bi_error)
+ if (!r10_bio->devs[i].bio->bi_status)
break;
if (i == conf->copies)
@@ -2050,7 +2050,7 @@ static void sync_request_write(struct mddev *mddev, struct r10bio *r10_bio)
tpages = get_resync_pages(tbio)->pages;
d = r10_bio->devs[i].devnum;
rdev = conf->mirrors[d].rdev;
- if (!r10_bio->devs[i].bio->bi_error) {
+ if (!r10_bio->devs[i].bio->bi_status) {
/* We know that the bi_io_vec layout is the same for
* both 'first' and 'i', so we just compare them.
* All vec entries are PAGE_SIZE;
@@ -2633,7 +2633,7 @@ static void handle_write_completed(struct r10conf *conf, struct r10bio *r10_bio)
rdev = conf->mirrors[dev].rdev;
if (r10_bio->devs[m].bio == NULL)
continue;
- if (!r10_bio->devs[m].bio->bi_error) {
+ if (!r10_bio->devs[m].bio->bi_status) {
rdev_clear_badblocks(
rdev,
r10_bio->devs[m].addr,
@@ -2649,7 +2649,7 @@ static void handle_write_completed(struct r10conf *conf, struct r10bio *r10_bio)
if (r10_bio->devs[m].repl_bio == NULL)
continue;
- if (!r10_bio->devs[m].repl_bio->bi_error) {
+ if (!r10_bio->devs[m].repl_bio->bi_status) {
rdev_clear_badblocks(
rdev,
r10_bio->devs[m].addr,
@@ -2675,7 +2675,7 @@ static void handle_write_completed(struct r10conf *conf, struct r10bio *r10_bio)
r10_bio->devs[m].addr,
r10_bio->sectors, 0);
rdev_dec_pending(rdev, conf->mddev);
- } else if (bio != NULL && bio->bi_error) {
+ } else if (bio != NULL && bio->bi_status) {
fail = true;
if (!narrow_write_error(r10_bio, m)) {
md_error(conf->mddev, rdev);
@@ -3267,7 +3267,7 @@ static sector_t raid10_sync_request(struct mddev *mddev, sector_t sector_nr,
r10_bio->devs[i].repl_bio->bi_end_io = NULL;
bio = r10_bio->devs[i].bio;
- bio->bi_error = -EIO;
+ bio->bi_status = BLK_STS_IOERR;
rcu_read_lock();
rdev = rcu_dereference(conf->mirrors[d].rdev);
if (rdev == NULL || test_bit(Faulty, &rdev->flags)) {
@@ -3309,7 +3309,7 @@ static sector_t raid10_sync_request(struct mddev *mddev, sector_t sector_nr,
/* Need to set up for writing to the replacement */
bio = r10_bio->devs[i].repl_bio;
- bio->bi_error = -EIO;
+ bio->bi_status = BLK_STS_IOERR;
sector = r10_bio->devs[i].addr;
bio->bi_next = biolist;
@@ -3375,7 +3375,7 @@ static sector_t raid10_sync_request(struct mddev *mddev, sector_t sector_nr,
if (bio->bi_end_io == end_sync_read) {
md_sync_acct(bio->bi_bdev, nr_sectors);
- bio->bi_error = 0;
+ bio->bi_status = 0;
generic_make_request(bio);
}
}
@@ -3552,7 +3552,7 @@ static struct r10conf *setup_conf(struct mddev *mddev)
if (!conf->r10bio_pool)
goto out;
- conf->bio_split = bioset_create(BIO_POOL_SIZE, 0);
+ conf->bio_split = bioset_create(BIO_POOL_SIZE, 0, 0);
if (!conf->bio_split)
goto out;
@@ -3611,6 +3611,9 @@ static int raid10_run(struct mddev *mddev)
int first = 1;
bool discard_supported = false;
+ if (mddev_init_writes_pending(mddev) < 0)
+ return -ENOMEM;
+
if (mddev->private == NULL) {
conf = setup_conf(mddev);
if (IS_ERR(conf))
@@ -4394,7 +4397,7 @@ read_more:
read_bio->bi_end_io = end_reshape_read;
bio_set_op_attrs(read_bio, REQ_OP_READ, 0);
read_bio->bi_flags &= (~0UL << BIO_RESET_BITS);
- read_bio->bi_error = 0;
+ read_bio->bi_status = 0;
read_bio->bi_vcnt = 0;
read_bio->bi_iter.bi_size = 0;
r10_bio->master_bio = read_bio;
@@ -4638,7 +4641,7 @@ static void end_reshape_write(struct bio *bio)
rdev = conf->mirrors[d].rdev;
}
- if (bio->bi_error) {
+ if (bio->bi_status) {
/* FIXME should record badblock */
md_error(mddev, rdev);
}
diff --git a/drivers/md/raid5-cache.c b/drivers/md/raid5-cache.c
index 4c00bc248287..bfa1e907c472 100644
--- a/drivers/md/raid5-cache.c
+++ b/drivers/md/raid5-cache.c
@@ -572,7 +572,7 @@ static void r5l_log_endio(struct bio *bio)
struct r5l_log *log = io->log;
unsigned long flags;
- if (bio->bi_error)
+ if (bio->bi_status)
md_error(log->rdev->mddev, log->rdev);
bio_put(bio);
@@ -1247,7 +1247,7 @@ static void r5l_log_flush_endio(struct bio *bio)
unsigned long flags;
struct r5l_io_unit *io;
- if (bio->bi_error)
+ if (bio->bi_status)
md_error(log->rdev->mddev, log->rdev);
spin_lock_irqsave(&log->io_list_lock, flags);
@@ -1782,7 +1782,7 @@ static int r5l_log_write_empty_meta_block(struct r5l_log *log, sector_t pos,
mb->checksum = cpu_to_le32(crc32c_le(log->uuid_checksum,
mb, PAGE_SIZE));
if (!sync_page_io(log->rdev, pos, PAGE_SIZE, page, REQ_OP_WRITE,
- REQ_FUA, false)) {
+ REQ_SYNC | REQ_FUA, false)) {
__free_page(page);
return -EIO;
}
@@ -2388,7 +2388,7 @@ r5c_recovery_rewrite_data_only_stripes(struct r5l_log *log,
mb->checksum = cpu_to_le32(crc32c_le(log->uuid_checksum,
mb, PAGE_SIZE));
sync_page_io(log->rdev, ctx->pos, PAGE_SIZE, page,
- REQ_OP_WRITE, REQ_FUA, false);
+ REQ_OP_WRITE, REQ_SYNC | REQ_FUA, false);
sh->log_start = ctx->pos;
list_add_tail(&sh->r5c, &log->stripe_in_journal_list);
atomic_inc(&log->stripe_in_journal_count);
@@ -3063,7 +3063,7 @@ int r5l_init_log(struct r5conf *conf, struct md_rdev *rdev)
if (!log->io_pool)
goto io_pool;
- log->bs = bioset_create(R5L_POOL_SIZE, 0);
+ log->bs = bioset_create(R5L_POOL_SIZE, 0, BIOSET_NEED_BVECS);
if (!log->bs)
goto io_bs;
diff --git a/drivers/md/raid5-ppl.c b/drivers/md/raid5-ppl.c
index 5d25bebf3328..77cce3573aa8 100644
--- a/drivers/md/raid5-ppl.c
+++ b/drivers/md/raid5-ppl.c
@@ -397,7 +397,7 @@ static void ppl_log_endio(struct bio *bio)
pr_debug("%s: seq: %llu\n", __func__, io->seq);
- if (bio->bi_error)
+ if (bio->bi_status)
md_error(ppl_conf->mddev, log->rdev);
list_for_each_entry_safe(sh, next, &io->stripe_list, log_list) {
@@ -907,8 +907,8 @@ static int ppl_write_empty_header(struct ppl_log *log)
pplhdr->checksum = cpu_to_le32(~crc32c_le(~0, pplhdr, PAGE_SIZE));
if (!sync_page_io(rdev, rdev->ppl.sector - rdev->data_offset,
- PPL_HEADER_SIZE, page, REQ_OP_WRITE | REQ_FUA, 0,
- false)) {
+ PPL_HEADER_SIZE, page, REQ_OP_WRITE | REQ_SYNC |
+ REQ_FUA, 0, false)) {
md_error(rdev->mddev, rdev);
ret = -EIO;
}
@@ -1150,7 +1150,7 @@ int ppl_init_log(struct r5conf *conf)
goto err;
}
- ppl_conf->bs = bioset_create(conf->raid_disks, 0);
+ ppl_conf->bs = bioset_create(conf->raid_disks, 0, 0);
if (!ppl_conf->bs) {
ret = -ENOMEM;
goto err;
diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c
index 9c4f7659f8b1..62c965be97e1 100644
--- a/drivers/md/raid5.c
+++ b/drivers/md/raid5.c
@@ -2476,7 +2476,7 @@ static void raid5_end_read_request(struct bio * bi)
pr_debug("end_read_request %llu/%d, count: %d, error %d.\n",
(unsigned long long)sh->sector, i, atomic_read(&sh->count),
- bi->bi_error);
+ bi->bi_status);
if (i == disks) {
bio_reset(bi);
BUG();
@@ -2496,7 +2496,7 @@ static void raid5_end_read_request(struct bio * bi)
s = sh->sector + rdev->new_data_offset;
else
s = sh->sector + rdev->data_offset;
- if (!bi->bi_error) {
+ if (!bi->bi_status) {
set_bit(R5_UPTODATE, &sh->dev[i].flags);
if (test_bit(R5_ReadError, &sh->dev[i].flags)) {
/* Note that this cannot happen on a
@@ -2613,7 +2613,7 @@ static void raid5_end_write_request(struct bio *bi)
}
pr_debug("end_write_request %llu/%d, count %d, error: %d.\n",
(unsigned long long)sh->sector, i, atomic_read(&sh->count),
- bi->bi_error);
+ bi->bi_status);
if (i == disks) {
bio_reset(bi);
BUG();
@@ -2621,14 +2621,14 @@ static void raid5_end_write_request(struct bio *bi)
}
if (replacement) {
- if (bi->bi_error)
+ if (bi->bi_status)
md_error(conf->mddev, rdev);
else if (is_badblock(rdev, sh->sector,
STRIPE_SECTORS,
&first_bad, &bad_sectors))
set_bit(R5_MadeGoodRepl, &sh->dev[i].flags);
} else {
- if (bi->bi_error) {
+ if (bi->bi_status) {
set_bit(STRIPE_DEGRADED, &sh->state);
set_bit(WriteErrorSeen, &rdev->flags);
set_bit(R5_WriteError, &sh->dev[i].flags);
@@ -2649,7 +2649,7 @@ static void raid5_end_write_request(struct bio *bi)
}
rdev_dec_pending(rdev, conf->mddev);
- if (sh->batch_head && bi->bi_error && !replacement)
+ if (sh->batch_head && bi->bi_status && !replacement)
set_bit(STRIPE_BATCH_ERR, &sh->batch_head->state);
bio_reset(bi);
@@ -3381,7 +3381,7 @@ handle_failed_stripe(struct r5conf *conf, struct stripe_head *sh,
sh->dev[i].sector + STRIPE_SECTORS) {
struct bio *nextbi = r5_next_bio(bi, sh->dev[i].sector);
- bi->bi_error = -EIO;
+ bi->bi_status = BLK_STS_IOERR;
md_write_end(conf->mddev);
bio_endio(bi);
bi = nextbi;
@@ -3403,7 +3403,7 @@ handle_failed_stripe(struct r5conf *conf, struct stripe_head *sh,
sh->dev[i].sector + STRIPE_SECTORS) {
struct bio *bi2 = r5_next_bio(bi, sh->dev[i].sector);
- bi->bi_error = -EIO;
+ bi->bi_status = BLK_STS_IOERR;
md_write_end(conf->mddev);
bio_endio(bi);
bi = bi2;
@@ -3429,7 +3429,7 @@ handle_failed_stripe(struct r5conf *conf, struct stripe_head *sh,
struct bio *nextbi =
r5_next_bio(bi, sh->dev[i].sector);
- bi->bi_error = -EIO;
+ bi->bi_status = BLK_STS_IOERR;
bio_endio(bi);
bi = nextbi;
}
@@ -4085,10 +4085,15 @@ static void handle_parity_checks5(struct r5conf *conf, struct stripe_head *sh,
set_bit(STRIPE_INSYNC, &sh->state);
else {
atomic64_add(STRIPE_SECTORS, &conf->mddev->resync_mismatches);
- if (test_bit(MD_RECOVERY_CHECK, &conf->mddev->recovery))
+ if (test_bit(MD_RECOVERY_CHECK, &conf->mddev->recovery)) {
/* don't try to repair!! */
set_bit(STRIPE_INSYNC, &sh->state);
- else {
+ pr_warn_ratelimited("%s: mismatch sector in range "
+ "%llu-%llu\n", mdname(conf->mddev),
+ (unsigned long long) sh->sector,
+ (unsigned long long) sh->sector +
+ STRIPE_SECTORS);
+ } else {
sh->check_state = check_state_compute_run;
set_bit(STRIPE_COMPUTE_RUN, &sh->state);
set_bit(STRIPE_OP_COMPUTE_BLK, &s->ops_request);
@@ -4237,10 +4242,15 @@ static void handle_parity_checks6(struct r5conf *conf, struct stripe_head *sh,
}
} else {
atomic64_add(STRIPE_SECTORS, &conf->mddev->resync_mismatches);
- if (test_bit(MD_RECOVERY_CHECK, &conf->mddev->recovery))
+ if (test_bit(MD_RECOVERY_CHECK, &conf->mddev->recovery)) {
/* don't try to repair!! */
set_bit(STRIPE_INSYNC, &sh->state);
- else {
+ pr_warn_ratelimited("%s: mismatch sector in range "
+ "%llu-%llu\n", mdname(conf->mddev),
+ (unsigned long long) sh->sector,
+ (unsigned long long) sh->sector +
+ STRIPE_SECTORS);
+ } else {
int *target = &sh->ops.target;
sh->ops.target = -1;
@@ -5144,7 +5154,7 @@ static void raid5_align_endio(struct bio *bi)
struct mddev *mddev;
struct r5conf *conf;
struct md_rdev *rdev;
- int error = bi->bi_error;
+ blk_status_t error = bi->bi_status;
bio_put(bi);
@@ -5721,7 +5731,7 @@ static void raid5_make_request(struct mddev *mddev, struct bio * bi)
release_stripe_plug(mddev, sh);
} else {
/* cannot get stripe for read-ahead, just give-up */
- bi->bi_error = -EIO;
+ bi->bi_status = BLK_STS_IOERR;
break;
}
}
@@ -6933,7 +6943,7 @@ static struct r5conf *setup_conf(struct mddev *mddev)
goto abort;
}
- conf->bio_split = bioset_create(BIO_POOL_SIZE, 0);
+ conf->bio_split = bioset_create(BIO_POOL_SIZE, 0, 0);
if (!conf->bio_split)
goto abort;
conf->mddev = mddev;
@@ -7108,6 +7118,9 @@ static int raid5_run(struct mddev *mddev)
long long min_offset_diff = 0;
int first = 1;
+ if (mddev_init_writes_pending(mddev) < 0)
+ return -ENOMEM;
+
if (mddev->recovery_cp != MaxSector)
pr_notice("md/raid:%s: not clean -- starting background reconstruction\n",
mdname(mddev));
diff --git a/drivers/media/Kconfig b/drivers/media/Kconfig
index b72edd27f880..55d9c2b82b7e 100644
--- a/drivers/media/Kconfig
+++ b/drivers/media/Kconfig
@@ -2,6 +2,12 @@
# Multimedia device configuration
#
+config CEC_CORE
+ tristate
+
+config CEC_NOTIFIER
+ bool
+
menuconfig MEDIA_SUPPORT
tristate "Multimedia support"
depends on HAS_IOMEM
diff --git a/drivers/media/Makefile b/drivers/media/Makefile
index 523fea3648ad..044503aa8801 100644
--- a/drivers/media/Makefile
+++ b/drivers/media/Makefile
@@ -4,8 +4,6 @@
media-objs := media-device.o media-devnode.o media-entity.o
-obj-$(CONFIG_CEC_CORE) += cec/
-
#
# I2C drivers should come before other drivers, otherwise they'll fail
# when compiled as builtin drivers
@@ -26,6 +24,8 @@ obj-$(CONFIG_DVB_CORE) += dvb-core/
# There are both core and drivers at RC subtree - merge before drivers
obj-y += rc/
+obj-$(CONFIG_CEC_CORE) += cec/
+
#
# Finally, merge the drivers that require the core
#
diff --git a/drivers/media/cec/Kconfig b/drivers/media/cec/Kconfig
index f944d93e3167..43428cec3a01 100644
--- a/drivers/media/cec/Kconfig
+++ b/drivers/media/cec/Kconfig
@@ -1,19 +1,6 @@
-config CEC_CORE
- tristate
- depends on MEDIA_CEC_SUPPORT
- default y
-
-config MEDIA_CEC_NOTIFIER
- bool
-
config MEDIA_CEC_RC
bool "HDMI CEC RC integration"
depends on CEC_CORE && RC_CORE
+ depends on CEC_CORE=m || RC_CORE=y
---help---
Pass on CEC remote control messages to the RC framework.
-
-config MEDIA_CEC_DEBUG
- bool "HDMI CEC debugfs interface"
- depends on CEC_CORE && DEBUG_FS
- ---help---
- Turns on the DebugFS interface for CEC devices.
diff --git a/drivers/media/cec/Makefile b/drivers/media/cec/Makefile
index 402a6c62a3e8..eaf408e64669 100644
--- a/drivers/media/cec/Makefile
+++ b/drivers/media/cec/Makefile
@@ -1,6 +1,6 @@
cec-objs := cec-core.o cec-adap.o cec-api.o cec-edid.o
-ifeq ($(CONFIG_MEDIA_CEC_NOTIFIER),y)
+ifeq ($(CONFIG_CEC_NOTIFIER),y)
cec-objs += cec-notifier.o
endif
diff --git a/drivers/media/cec/cec-adap.c b/drivers/media/cec/cec-adap.c
index f5fe01c9da8a..9dfc79800c71 100644
--- a/drivers/media/cec/cec-adap.c
+++ b/drivers/media/cec/cec-adap.c
@@ -1864,7 +1864,7 @@ void cec_monitor_all_cnt_dec(struct cec_adapter *adap)
WARN_ON(call_op(adap, adap_monitor_all_enable, 0));
}
-#ifdef CONFIG_MEDIA_CEC_DEBUG
+#ifdef CONFIG_DEBUG_FS
/*
* Log the current state of the CEC adapter.
* Very useful for debugging.
diff --git a/drivers/media/cec/cec-api.c b/drivers/media/cec/cec-api.c
index 0860fb458757..999926f731c8 100644
--- a/drivers/media/cec/cec-api.c
+++ b/drivers/media/cec/cec-api.c
@@ -271,16 +271,10 @@ static long cec_receive(struct cec_adapter *adap, struct cec_fh *fh,
bool block, struct cec_msg __user *parg)
{
struct cec_msg msg = {};
- long err = 0;
+ long err;
if (copy_from_user(&msg, parg, sizeof(msg)))
return -EFAULT;
- mutex_lock(&adap->lock);
- if (!adap->is_configured && fh->mode_follower < CEC_MODE_MONITOR)
- err = -ENONET;
- mutex_unlock(&adap->lock);
- if (err)
- return err;
err = cec_receive_msg(fh, &msg, block);
if (err)
diff --git a/drivers/media/cec/cec-core.c b/drivers/media/cec/cec-core.c
index f9ebff90f8eb..2f87748ba4fc 100644
--- a/drivers/media/cec/cec-core.c
+++ b/drivers/media/cec/cec-core.c
@@ -187,7 +187,7 @@ static void cec_devnode_unregister(struct cec_devnode *devnode)
put_device(&devnode->dev);
}
-#ifdef CONFIG_MEDIA_CEC_NOTIFIER
+#ifdef CONFIG_CEC_NOTIFIER
static void cec_cec_notify(struct cec_adapter *adap, u16 pa)
{
cec_s_phys_addr(adap, pa, false);
@@ -323,7 +323,7 @@ int cec_register_adapter(struct cec_adapter *adap,
}
dev_set_drvdata(&adap->devnode.dev, adap);
-#ifdef CONFIG_MEDIA_CEC_DEBUG
+#ifdef CONFIG_DEBUG_FS
if (!top_cec_dir)
return 0;
@@ -355,7 +355,7 @@ void cec_unregister_adapter(struct cec_adapter *adap)
adap->rc = NULL;
#endif
debugfs_remove_recursive(adap->cec_dir);
-#ifdef CONFIG_MEDIA_CEC_NOTIFIER
+#ifdef CONFIG_CEC_NOTIFIER
if (adap->notifier)
cec_notifier_unregister(adap->notifier);
#endif
@@ -395,7 +395,7 @@ static int __init cec_devnode_init(void)
return ret;
}
-#ifdef CONFIG_MEDIA_CEC_DEBUG
+#ifdef CONFIG_DEBUG_FS
top_cec_dir = debugfs_create_dir("cec", NULL);
if (IS_ERR_OR_NULL(top_cec_dir)) {
pr_warn("cec: Failed to create debugfs cec dir\n");
diff --git a/drivers/media/i2c/Kconfig b/drivers/media/i2c/Kconfig
index fd181c99ce11..aaa9471c7d11 100644
--- a/drivers/media/i2c/Kconfig
+++ b/drivers/media/i2c/Kconfig
@@ -220,7 +220,8 @@ config VIDEO_ADV7604
config VIDEO_ADV7604_CEC
bool "Enable Analog Devices ADV7604 CEC support"
- depends on VIDEO_ADV7604 && CEC_CORE
+ depends on VIDEO_ADV7604
+ select CEC_CORE
---help---
When selected the adv7604 will support the optional
HDMI CEC feature.
@@ -240,7 +241,8 @@ config VIDEO_ADV7842
config VIDEO_ADV7842_CEC
bool "Enable Analog Devices ADV7842 CEC support"
- depends on VIDEO_ADV7842 && CEC_CORE
+ depends on VIDEO_ADV7842
+ select CEC_CORE
---help---
When selected the adv7842 will support the optional
HDMI CEC feature.
@@ -478,7 +480,8 @@ config VIDEO_ADV7511
config VIDEO_ADV7511_CEC
bool "Enable Analog Devices ADV7511 CEC support"
- depends on VIDEO_ADV7511 && CEC_CORE
+ depends on VIDEO_ADV7511
+ select CEC_CORE
---help---
When selected the adv7511 will support the optional
HDMI CEC feature.
diff --git a/drivers/media/i2c/tc358743.c b/drivers/media/i2c/tc358743.c
index acef4eca269f..3251cba89e8f 100644
--- a/drivers/media/i2c/tc358743.c
+++ b/drivers/media/i2c/tc358743.c
@@ -223,7 +223,7 @@ static void i2c_wr8(struct v4l2_subdev *sd, u16 reg, u8 val)
static void i2c_wr8_and_or(struct v4l2_subdev *sd, u16 reg,
u8 mask, u8 val)
{
- i2c_wrreg(sd, reg, (i2c_rdreg(sd, reg, 2) & mask) | val, 2);
+ i2c_wrreg(sd, reg, (i2c_rdreg(sd, reg, 1) & mask) | val, 1);
}
static u16 i2c_rd16(struct v4l2_subdev *sd, u16 reg)
diff --git a/drivers/media/platform/Kconfig b/drivers/media/platform/Kconfig
index ac026ee1ca07..041cb80a26b1 100644
--- a/drivers/media/platform/Kconfig
+++ b/drivers/media/platform/Kconfig
@@ -501,8 +501,9 @@ if CEC_PLATFORM_DRIVERS
config VIDEO_SAMSUNG_S5P_CEC
tristate "Samsung S5P CEC driver"
- depends on CEC_CORE && (PLAT_S5P || ARCH_EXYNOS || COMPILE_TEST)
- select MEDIA_CEC_NOTIFIER
+ depends on PLAT_S5P || ARCH_EXYNOS || COMPILE_TEST
+ select CEC_CORE
+ select CEC_NOTIFIER
---help---
This is a driver for Samsung S5P HDMI CEC interface. It uses the
generic CEC framework interface.
@@ -511,8 +512,9 @@ config VIDEO_SAMSUNG_S5P_CEC
config VIDEO_STI_HDMI_CEC
tristate "STMicroelectronics STiH4xx HDMI CEC driver"
- depends on CEC_CORE && (ARCH_STI || COMPILE_TEST)
- select MEDIA_CEC_NOTIFIER
+ depends on ARCH_STI || COMPILE_TEST
+ select CEC_CORE
+ select CEC_NOTIFIER
---help---
This is a driver for STIH4xx HDMI CEC interface. It uses the
generic CEC framework interface.
diff --git a/drivers/media/platform/mtk-vcodec/vdec/vdec_h264_if.c b/drivers/media/platform/mtk-vcodec/vdec/vdec_h264_if.c
index 57a842ff3097..b7731b18ecae 100644
--- a/drivers/media/platform/mtk-vcodec/vdec/vdec_h264_if.c
+++ b/drivers/media/platform/mtk-vcodec/vdec/vdec_h264_if.c
@@ -493,10 +493,10 @@ static int vdec_h264_get_param(unsigned long h_vdec,
}
static struct vdec_common_if vdec_h264_if = {
- vdec_h264_init,
- vdec_h264_decode,
- vdec_h264_get_param,
- vdec_h264_deinit,
+ .init = vdec_h264_init,
+ .decode = vdec_h264_decode,
+ .get_param = vdec_h264_get_param,
+ .deinit = vdec_h264_deinit,
};
struct vdec_common_if *get_h264_dec_comm_if(void);
diff --git a/drivers/media/platform/mtk-vcodec/vdec/vdec_vp8_if.c b/drivers/media/platform/mtk-vcodec/vdec/vdec_vp8_if.c
index 6e7a62ae0842..b9fad6a48879 100644
--- a/drivers/media/platform/mtk-vcodec/vdec/vdec_vp8_if.c
+++ b/drivers/media/platform/mtk-vcodec/vdec/vdec_vp8_if.c
@@ -620,10 +620,10 @@ static void vdec_vp8_deinit(unsigned long h_vdec)
}
static struct vdec_common_if vdec_vp8_if = {
- vdec_vp8_init,
- vdec_vp8_decode,
- vdec_vp8_get_param,
- vdec_vp8_deinit,
+ .init = vdec_vp8_init,
+ .decode = vdec_vp8_decode,
+ .get_param = vdec_vp8_get_param,
+ .deinit = vdec_vp8_deinit,
};
struct vdec_common_if *get_vp8_dec_comm_if(void);
diff --git a/drivers/media/platform/mtk-vcodec/vdec/vdec_vp9_if.c b/drivers/media/platform/mtk-vcodec/vdec/vdec_vp9_if.c
index 5539b1853f16..1daee1207469 100644
--- a/drivers/media/platform/mtk-vcodec/vdec/vdec_vp9_if.c
+++ b/drivers/media/platform/mtk-vcodec/vdec/vdec_vp9_if.c
@@ -979,10 +979,10 @@ static int vdec_vp9_get_param(unsigned long h_vdec,
}
static struct vdec_common_if vdec_vp9_if = {
- vdec_vp9_init,
- vdec_vp9_decode,
- vdec_vp9_get_param,
- vdec_vp9_deinit,
+ .init = vdec_vp9_init,
+ .decode = vdec_vp9_decode,
+ .get_param = vdec_vp9_get_param,
+ .deinit = vdec_vp9_deinit,
};
struct vdec_common_if *get_vp9_dec_comm_if(void);
diff --git a/drivers/media/platform/vivid/Kconfig b/drivers/media/platform/vivid/Kconfig
index b36ac19dc6e4..154de92dd809 100644
--- a/drivers/media/platform/vivid/Kconfig
+++ b/drivers/media/platform/vivid/Kconfig
@@ -26,7 +26,8 @@ config VIDEO_VIVID
config VIDEO_VIVID_CEC
bool "Enable CEC emulation support"
- depends on VIDEO_VIVID && CEC_CORE
+ depends on VIDEO_VIVID
+ select CEC_CORE
---help---
When selected the vivid module will emulate the optional
HDMI CEC feature.
diff --git a/drivers/media/rc/rc-ir-raw.c b/drivers/media/rc/rc-ir-raw.c
index 90f66dc7c0d7..a2fc1a1d58b0 100644
--- a/drivers/media/rc/rc-ir-raw.c
+++ b/drivers/media/rc/rc-ir-raw.c
@@ -211,7 +211,7 @@ EXPORT_SYMBOL_GPL(ir_raw_event_set_idle);
*/
void ir_raw_event_handle(struct rc_dev *dev)
{
- if (!dev->raw)
+ if (!dev->raw || !dev->raw->thread)
return;
wake_up_process(dev->raw->thread);
@@ -490,6 +490,7 @@ int ir_raw_event_register(struct rc_dev *dev)
{
int rc;
struct ir_raw_handler *handler;
+ struct task_struct *thread;
if (!dev)
return -EINVAL;
@@ -507,13 +508,15 @@ int ir_raw_event_register(struct rc_dev *dev)
* because the event is coming from userspace
*/
if (dev->driver_type != RC_DRIVER_IR_RAW_TX) {
- dev->raw->thread = kthread_run(ir_raw_event_thread, dev->raw,
- "rc%u", dev->minor);
+ thread = kthread_run(ir_raw_event_thread, dev->raw, "rc%u",
+ dev->minor);
- if (IS_ERR(dev->raw->thread)) {
- rc = PTR_ERR(dev->raw->thread);
+ if (IS_ERR(thread)) {
+ rc = PTR_ERR(thread);
goto out;
}
+
+ dev->raw->thread = thread;
}
mutex_lock(&ir_raw_handler_lock);
diff --git a/drivers/media/rc/sir_ir.c b/drivers/media/rc/sir_ir.c
index e12ec50bf0bf..90a5f8fd5eea 100644
--- a/drivers/media/rc/sir_ir.c
+++ b/drivers/media/rc/sir_ir.c
@@ -183,9 +183,15 @@ static irqreturn_t sir_interrupt(int irq, void *dev_id)
static unsigned long delt;
unsigned long deltintr;
unsigned long flags;
+ int counter = 0;
int iir, lsr;
while ((iir = inb(io + UART_IIR) & UART_IIR_ID)) {
+ if (++counter > 256) {
+ dev_err(&sir_ir_dev->dev, "Trapped in interrupt");
+ break;
+ }
+
switch (iir & UART_IIR_ID) { /* FIXME toto treba preriedit */
case UART_IIR_MSI:
(void)inb(io + UART_MSR);
diff --git a/drivers/media/usb/pulse8-cec/Kconfig b/drivers/media/usb/pulse8-cec/Kconfig
index 8937f3986a01..18ead44824ba 100644
--- a/drivers/media/usb/pulse8-cec/Kconfig
+++ b/drivers/media/usb/pulse8-cec/Kconfig
@@ -1,6 +1,7 @@
config USB_PULSE8_CEC
tristate "Pulse Eight HDMI CEC"
- depends on USB_ACM && CEC_CORE
+ depends on USB_ACM
+ select CEC_CORE
select SERIO
select SERIO_SERPORT
---help---
diff --git a/drivers/media/usb/rainshadow-cec/Kconfig b/drivers/media/usb/rainshadow-cec/Kconfig
index 3eb86607efb8..030ef01b1ff0 100644
--- a/drivers/media/usb/rainshadow-cec/Kconfig
+++ b/drivers/media/usb/rainshadow-cec/Kconfig
@@ -1,6 +1,7 @@
config USB_RAINSHADOW_CEC
tristate "RainShadow Tech HDMI CEC"
- depends on USB_ACM && CEC_CORE
+ depends on USB_ACM
+ select CEC_CORE
select SERIO
select SERIO_SERPORT
---help---
diff --git a/drivers/media/usb/rainshadow-cec/rainshadow-cec.c b/drivers/media/usb/rainshadow-cec/rainshadow-cec.c
index 541ca543f71f..4126552c9055 100644
--- a/drivers/media/usb/rainshadow-cec/rainshadow-cec.c
+++ b/drivers/media/usb/rainshadow-cec/rainshadow-cec.c
@@ -119,7 +119,7 @@ static void rain_irq_work_handler(struct work_struct *work)
while (true) {
unsigned long flags;
- bool exit_loop;
+ bool exit_loop = false;
char data;
spin_lock_irqsave(&rain->buf_lock, flags);
@@ -336,6 +336,7 @@ static int rain_connect(struct serio *serio, struct serio_driver *drv)
serio_set_drvdata(serio, rain);
INIT_WORK(&rain->work, rain_irq_work_handler);
mutex_init(&rain->write_lock);
+ spin_lock_init(&rain->buf_lock);
err = serio_open(serio, drv);
if (err)
diff --git a/drivers/media/v4l2-core/videobuf2-core.c b/drivers/media/v4l2-core/videobuf2-core.c
index 94afbbf92807..c0175ea7e7ad 100644
--- a/drivers/media/v4l2-core/videobuf2-core.c
+++ b/drivers/media/v4l2-core/videobuf2-core.c
@@ -868,7 +868,7 @@ EXPORT_SYMBOL_GPL(vb2_core_create_bufs);
void *vb2_plane_vaddr(struct vb2_buffer *vb, unsigned int plane_no)
{
- if (plane_no > vb->num_planes || !vb->planes[plane_no].mem_priv)
+ if (plane_no >= vb->num_planes || !vb->planes[plane_no].mem_priv)
return NULL;
return call_ptr_memop(vb, vaddr, vb->planes[plane_no].mem_priv);
diff --git a/drivers/memory/atmel-ebi.c b/drivers/memory/atmel-ebi.c
index 35910f945bfa..99e644cda4d1 100644
--- a/drivers/memory/atmel-ebi.c
+++ b/drivers/memory/atmel-ebi.c
@@ -581,7 +581,7 @@ static int atmel_ebi_probe(struct platform_device *pdev)
return of_platform_populate(np, NULL, NULL, dev);
}
-static int atmel_ebi_resume(struct device *dev)
+static __maybe_unused int atmel_ebi_resume(struct device *dev)
{
struct atmel_ebi *ebi = dev_get_drvdata(dev);
struct atmel_ebi_dev *ebid;
diff --git a/drivers/memstick/core/ms_block.c b/drivers/memstick/core/ms_block.c
index 99e651c27fb7..22de7f5ed032 100644
--- a/drivers/memstick/core/ms_block.c
+++ b/drivers/memstick/core/ms_block.c
@@ -1921,12 +1921,13 @@ static void msb_io_work(struct work_struct *work)
spin_lock_irqsave(&msb->q_lock, flags);
if (len)
- if (!__blk_end_request(msb->req, 0, len))
+ if (!__blk_end_request(msb->req, BLK_STS_OK, len))
msb->req = NULL;
if (error && msb->req) {
+ blk_status_t ret = errno_to_blk_status(error);
dbg_verbose("IO: ending one sector of the request with error");
- if (!__blk_end_request(msb->req, error, msb->page_size))
+ if (!__blk_end_request(msb->req, ret, msb->page_size))
msb->req = NULL;
}
@@ -2014,7 +2015,7 @@ static void msb_submit_req(struct request_queue *q)
WARN_ON(!msb->io_queue_stopped);
while ((req = blk_fetch_request(q)) != NULL)
- __blk_end_request_all(req, -ENODEV);
+ __blk_end_request_all(req, BLK_STS_IOERR);
return;
}
diff --git a/drivers/memstick/core/mspro_block.c b/drivers/memstick/core/mspro_block.c
index c00d8a266878..8897962781bb 100644
--- a/drivers/memstick/core/mspro_block.c
+++ b/drivers/memstick/core/mspro_block.c
@@ -709,7 +709,8 @@ try_again:
msb->req_sg);
if (!msb->seg_count) {
- chunk = __blk_end_request_cur(msb->block_req, -ENOMEM);
+ chunk = __blk_end_request_cur(msb->block_req,
+ BLK_STS_RESOURCE);
continue;
}
@@ -776,7 +777,8 @@ static int mspro_block_complete_req(struct memstick_dev *card, int error)
if (error && !t_len)
t_len = blk_rq_cur_bytes(msb->block_req);
- chunk = __blk_end_request(msb->block_req, error, t_len);
+ chunk = __blk_end_request(msb->block_req,
+ errno_to_blk_status(error), t_len);
error = mspro_block_issue_req(card, chunk);
@@ -838,7 +840,7 @@ static void mspro_block_submit_req(struct request_queue *q)
if (msb->eject) {
while ((req = blk_fetch_request(q)) != NULL)
- __blk_end_request_all(req, -ENODEV);
+ __blk_end_request_all(req, BLK_STS_IOERR);
return;
}
diff --git a/drivers/mfd/arizona-core.c b/drivers/mfd/arizona-core.c
index 75488e65cd96..8d46e3ad9529 100644
--- a/drivers/mfd/arizona-core.c
+++ b/drivers/mfd/arizona-core.c
@@ -245,8 +245,7 @@ static int arizona_poll_reg(struct arizona *arizona,
int ret;
ret = regmap_read_poll_timeout(arizona->regmap,
- ARIZONA_INTERRUPT_RAW_STATUS_5, val,
- ((val & mask) == target),
+ reg, val, ((val & mask) == target),
ARIZONA_REG_POLL_DELAY_US,
timeout_ms * 1000);
if (ret)
diff --git a/drivers/misc/cxl/context.c b/drivers/misc/cxl/context.c
index 4472ce11f98d..8c32040b9c09 100644
--- a/drivers/misc/cxl/context.c
+++ b/drivers/misc/cxl/context.c
@@ -45,7 +45,7 @@ int cxl_context_init(struct cxl_context *ctx, struct cxl_afu *afu, bool master)
mutex_init(&ctx->mapping_lock);
ctx->mapping = NULL;
- if (cxl_is_psl8(afu)) {
+ if (cxl_is_power8()) {
spin_lock_init(&ctx->sste_lock);
/*
@@ -189,7 +189,7 @@ int cxl_context_iomap(struct cxl_context *ctx, struct vm_area_struct *vma)
if (start + len > ctx->afu->adapter->ps_size)
return -EINVAL;
- if (cxl_is_psl9(ctx->afu)) {
+ if (cxl_is_power9()) {
/*
* Make sure there is a valid problem state
* area space for this AFU.
@@ -324,7 +324,7 @@ static void reclaim_ctx(struct rcu_head *rcu)
{
struct cxl_context *ctx = container_of(rcu, struct cxl_context, rcu);
- if (cxl_is_psl8(ctx->afu))
+ if (cxl_is_power8())
free_page((u64)ctx->sstp);
if (ctx->ff_page)
__free_page(ctx->ff_page);
diff --git a/drivers/misc/cxl/cxl.h b/drivers/misc/cxl/cxl.h
index c8568ea7c518..a03f8e7535e5 100644
--- a/drivers/misc/cxl/cxl.h
+++ b/drivers/misc/cxl/cxl.h
@@ -357,6 +357,7 @@ static const cxl_p2n_reg_t CXL_PSL_WED_An = {0x0A0};
#define CXL_PSL9_DSISR_An_PF_RGP 0x0000000000000090ULL /* PTE not found (Radix Guest (parent)) 0b10010000 */
#define CXL_PSL9_DSISR_An_PF_HRH 0x0000000000000094ULL /* PTE not found (HPT/Radix Host) 0b10010100 */
#define CXL_PSL9_DSISR_An_PF_STEG 0x000000000000009CULL /* PTE not found (STEG VA) 0b10011100 */
+#define CXL_PSL9_DSISR_An_URTCH 0x00000000000000B4ULL /* Unsupported Radix Tree Configuration 0b10110100 */
/****** CXL_PSL_TFC_An ******************************************************/
#define CXL_PSL_TFC_An_A (1ull << (63-28)) /* Acknowledge non-translation fault */
@@ -844,24 +845,15 @@ static inline bool cxl_is_power8(void)
static inline bool cxl_is_power9(void)
{
- /* intermediate solution */
- if (!cxl_is_power8() &&
- (cpu_has_feature(CPU_FTRS_POWER9) ||
- cpu_has_feature(CPU_FTR_POWER9_DD1)))
+ if (pvr_version_is(PVR_POWER9))
return true;
return false;
}
-static inline bool cxl_is_psl8(struct cxl_afu *afu)
+static inline bool cxl_is_power9_dd1(void)
{
- if (afu->adapter->caia_major == 1)
- return true;
- return false;
-}
-
-static inline bool cxl_is_psl9(struct cxl_afu *afu)
-{
- if (afu->adapter->caia_major == 2)
+ if ((pvr_version_is(PVR_POWER9)) &&
+ cpu_has_feature(CPU_FTR_POWER9_DD1))
return true;
return false;
}
diff --git a/drivers/misc/cxl/fault.c b/drivers/misc/cxl/fault.c
index 5344448f514e..c79e39bad7a4 100644
--- a/drivers/misc/cxl/fault.c
+++ b/drivers/misc/cxl/fault.c
@@ -187,7 +187,7 @@ static struct mm_struct *get_mem_context(struct cxl_context *ctx)
static bool cxl_is_segment_miss(struct cxl_context *ctx, u64 dsisr)
{
- if ((cxl_is_psl8(ctx->afu)) && (dsisr & CXL_PSL_DSISR_An_DS))
+ if ((cxl_is_power8() && (dsisr & CXL_PSL_DSISR_An_DS)))
return true;
return false;
@@ -195,16 +195,23 @@ static bool cxl_is_segment_miss(struct cxl_context *ctx, u64 dsisr)
static bool cxl_is_page_fault(struct cxl_context *ctx, u64 dsisr)
{
- if ((cxl_is_psl8(ctx->afu)) && (dsisr & CXL_PSL_DSISR_An_DM))
- return true;
+ u64 crs; /* Translation Checkout Response Status */
- if ((cxl_is_psl9(ctx->afu)) &&
- ((dsisr & CXL_PSL9_DSISR_An_CO_MASK) &
- (CXL_PSL9_DSISR_An_PF_SLR | CXL_PSL9_DSISR_An_PF_RGC |
- CXL_PSL9_DSISR_An_PF_RGP | CXL_PSL9_DSISR_An_PF_HRH |
- CXL_PSL9_DSISR_An_PF_STEG)))
+ if ((cxl_is_power8()) && (dsisr & CXL_PSL_DSISR_An_DM))
return true;
+ if (cxl_is_power9()) {
+ crs = (dsisr & CXL_PSL9_DSISR_An_CO_MASK);
+ if ((crs == CXL_PSL9_DSISR_An_PF_SLR) ||
+ (crs == CXL_PSL9_DSISR_An_PF_RGC) ||
+ (crs == CXL_PSL9_DSISR_An_PF_RGP) ||
+ (crs == CXL_PSL9_DSISR_An_PF_HRH) ||
+ (crs == CXL_PSL9_DSISR_An_PF_STEG) ||
+ (crs == CXL_PSL9_DSISR_An_URTCH)) {
+ return true;
+ }
+ }
+
return false;
}
diff --git a/drivers/misc/cxl/file.c b/drivers/misc/cxl/file.c
index 17b433f1ce23..0761271d68c5 100644
--- a/drivers/misc/cxl/file.c
+++ b/drivers/misc/cxl/file.c
@@ -159,11 +159,8 @@ static long afu_ioctl_start_work(struct cxl_context *ctx,
/* Do this outside the status_mutex to avoid a circular dependency with
* the locking in cxl_mmap_fault() */
- if (copy_from_user(&work, uwork,
- sizeof(struct cxl_ioctl_start_work))) {
- rc = -EFAULT;
- goto out;
- }
+ if (copy_from_user(&work, uwork, sizeof(work)))
+ return -EFAULT;
mutex_lock(&ctx->status_mutex);
if (ctx->status != OPENED) {
diff --git a/drivers/misc/cxl/main.c b/drivers/misc/cxl/main.c
index 1703655072b1..c1ba0d42cbc8 100644
--- a/drivers/misc/cxl/main.c
+++ b/drivers/misc/cxl/main.c
@@ -329,8 +329,15 @@ static int __init init_cxl(void)
cxl_debugfs_init();
- if ((rc = register_cxl_calls(&cxl_calls)))
- goto err;
+ /*
+ * we don't register the callback on P9. slb callack is only
+ * used for the PSL8 MMU and CX4.
+ */
+ if (cxl_is_power8()) {
+ rc = register_cxl_calls(&cxl_calls);
+ if (rc)
+ goto err;
+ }
if (cpu_has_feature(CPU_FTR_HVMODE)) {
cxl_ops = &cxl_native_ops;
@@ -347,7 +354,8 @@ static int __init init_cxl(void)
return 0;
err1:
- unregister_cxl_calls(&cxl_calls);
+ if (cxl_is_power8())
+ unregister_cxl_calls(&cxl_calls);
err:
cxl_debugfs_exit();
cxl_file_exit();
@@ -366,7 +374,8 @@ static void exit_cxl(void)
cxl_debugfs_exit();
cxl_file_exit();
- unregister_cxl_calls(&cxl_calls);
+ if (cxl_is_power8())
+ unregister_cxl_calls(&cxl_calls);
idr_destroy(&cxl_adapter_idr);
}
diff --git a/drivers/misc/cxl/native.c b/drivers/misc/cxl/native.c
index 871a2f09c718..2b2f8894149d 100644
--- a/drivers/misc/cxl/native.c
+++ b/drivers/misc/cxl/native.c
@@ -105,11 +105,16 @@ static int native_afu_reset(struct cxl_afu *afu)
CXL_AFU_Cntl_An_RS_MASK | CXL_AFU_Cntl_An_ES_MASK,
false);
- /* Re-enable any masked interrupts */
- serr = cxl_p1n_read(afu, CXL_PSL_SERR_An);
- serr &= ~CXL_PSL_SERR_An_IRQ_MASKS;
- cxl_p1n_write(afu, CXL_PSL_SERR_An, serr);
-
+ /*
+ * Re-enable any masked interrupts when the AFU is not
+ * activated to avoid side effects after attaching a process
+ * in dedicated mode.
+ */
+ if (afu->current_mode == 0) {
+ serr = cxl_p1n_read(afu, CXL_PSL_SERR_An);
+ serr &= ~CXL_PSL_SERR_An_IRQ_MASKS;
+ cxl_p1n_write(afu, CXL_PSL_SERR_An, serr);
+ }
return rc;
}
@@ -139,9 +144,9 @@ int cxl_psl_purge(struct cxl_afu *afu)
pr_devel("PSL purge request\n");
- if (cxl_is_psl8(afu))
+ if (cxl_is_power8())
trans_fault = CXL_PSL_DSISR_TRANS;
- if (cxl_is_psl9(afu))
+ if (cxl_is_power9())
trans_fault = CXL_PSL9_DSISR_An_TF;
if (!cxl_ops->link_ok(afu->adapter, afu)) {
@@ -603,7 +608,7 @@ static u64 calculate_sr(struct cxl_context *ctx)
if (!test_tsk_thread_flag(current, TIF_32BIT))
sr |= CXL_PSL_SR_An_SF;
}
- if (cxl_is_psl9(ctx->afu)) {
+ if (cxl_is_power9()) {
if (radix_enabled())
sr |= CXL_PSL_SR_An_XLAT_ror;
else
@@ -1117,10 +1122,10 @@ static irqreturn_t native_handle_psl_slice_error(struct cxl_context *ctx,
static bool cxl_is_translation_fault(struct cxl_afu *afu, u64 dsisr)
{
- if ((cxl_is_psl8(afu)) && (dsisr & CXL_PSL_DSISR_TRANS))
+ if ((cxl_is_power8()) && (dsisr & CXL_PSL_DSISR_TRANS))
return true;
- if ((cxl_is_psl9(afu)) && (dsisr & CXL_PSL9_DSISR_An_TF))
+ if ((cxl_is_power9()) && (dsisr & CXL_PSL9_DSISR_An_TF))
return true;
return false;
@@ -1194,10 +1199,10 @@ static void native_irq_wait(struct cxl_context *ctx)
if (ph != ctx->pe)
return;
dsisr = cxl_p2n_read(ctx->afu, CXL_PSL_DSISR_An);
- if (cxl_is_psl8(ctx->afu) &&
+ if (cxl_is_power8() &&
((dsisr & CXL_PSL_DSISR_PENDING) == 0))
return;
- if (cxl_is_psl9(ctx->afu) &&
+ if (cxl_is_power9() &&
((dsisr & CXL_PSL9_DSISR_PENDING) == 0))
return;
/*
@@ -1302,13 +1307,16 @@ int cxl_native_register_psl_err_irq(struct cxl *adapter)
void cxl_native_release_psl_err_irq(struct cxl *adapter)
{
- if (adapter->native->err_virq != irq_find_mapping(NULL, adapter->native->err_hwirq))
+ if (adapter->native->err_virq == 0 ||
+ adapter->native->err_virq !=
+ irq_find_mapping(NULL, adapter->native->err_hwirq))
return;
cxl_p1_write(adapter, CXL_PSL_ErrIVTE, 0x0000000000000000);
cxl_unmap_irq(adapter->native->err_virq, adapter);
cxl_ops->release_one_irq(adapter, adapter->native->err_hwirq);
kfree(adapter->irq_name);
+ adapter->native->err_virq = 0;
}
int cxl_native_register_serr_irq(struct cxl_afu *afu)
@@ -1346,13 +1354,15 @@ int cxl_native_register_serr_irq(struct cxl_afu *afu)
void cxl_native_release_serr_irq(struct cxl_afu *afu)
{
- if (afu->serr_virq != irq_find_mapping(NULL, afu->serr_hwirq))
+ if (afu->serr_virq == 0 ||
+ afu->serr_virq != irq_find_mapping(NULL, afu->serr_hwirq))
return;
cxl_p1n_write(afu, CXL_PSL_SERR_An, 0x0000000000000000);
cxl_unmap_irq(afu->serr_virq, afu);
cxl_ops->release_one_irq(afu->adapter, afu->serr_hwirq);
kfree(afu->err_irq_name);
+ afu->serr_virq = 0;
}
int cxl_native_register_psl_irq(struct cxl_afu *afu)
@@ -1375,12 +1385,15 @@ int cxl_native_register_psl_irq(struct cxl_afu *afu)
void cxl_native_release_psl_irq(struct cxl_afu *afu)
{
- if (afu->native->psl_virq != irq_find_mapping(NULL, afu->native->psl_hwirq))
+ if (afu->native->psl_virq == 0 ||
+ afu->native->psl_virq !=
+ irq_find_mapping(NULL, afu->native->psl_hwirq))
return;
cxl_unmap_irq(afu->native->psl_virq, afu);
cxl_ops->release_one_irq(afu->adapter, afu->native->psl_hwirq);
kfree(afu->psl_irq_name);
+ afu->native->psl_virq = 0;
}
static void recover_psl_err(struct cxl_afu *afu, u64 errstat)
diff --git a/drivers/misc/cxl/pci.c b/drivers/misc/cxl/pci.c
index 6dc1ee5b92c9..1eb9859809bf 100644
--- a/drivers/misc/cxl/pci.c
+++ b/drivers/misc/cxl/pci.c
@@ -436,7 +436,7 @@ static int init_implementation_adapter_regs_psl9(struct cxl *adapter, struct pci
/* nMMU_ID Defaults to: b’000001001’*/
xsl_dsnctl |= ((u64)0x09 << (63-28));
- if (cxl_is_power9() && !cpu_has_feature(CPU_FTR_POWER9_DD1)) {
+ if (!(cxl_is_power9_dd1())) {
/*
* Used to identify CAPI packets which should be sorted into
* the Non-Blocking queues by the PHB. This field should match
@@ -491,7 +491,7 @@ static int init_implementation_adapter_regs_psl9(struct cxl *adapter, struct pci
cxl_p1_write(adapter, CXL_PSL9_APCDEDTYPE, 0x40000003FFFF0000ULL);
/* Disable vc dd1 fix */
- if ((cxl_is_power9() && cpu_has_feature(CPU_FTR_POWER9_DD1)))
+ if (cxl_is_power9_dd1())
cxl_p1_write(adapter, CXL_PSL9_GP_CT, 0x0400000000000001ULL);
return 0;
@@ -1439,8 +1439,7 @@ int cxl_pci_reset(struct cxl *adapter)
* The adapter is about to be reset, so ignore errors.
* Not supported on P9 DD1
*/
- if ((cxl_is_power8()) ||
- ((cxl_is_power9() && !cpu_has_feature(CPU_FTR_POWER9_DD1))))
+ if ((cxl_is_power8()) || (!(cxl_is_power9_dd1())))
cxl_data_cache_flush(adapter);
/* pcie_warm_reset requests a fundamental pci reset which includes a
@@ -1750,7 +1749,6 @@ static const struct cxl_service_layer_ops psl9_ops = {
.debugfs_add_adapter_regs = cxl_debugfs_add_adapter_regs_psl9,
.debugfs_add_afu_regs = cxl_debugfs_add_afu_regs_psl9,
.psl_irq_dump_registers = cxl_native_irq_dump_regs_psl9,
- .err_irq_dump_registers = cxl_native_err_irq_dump_regs,
.debugfs_stop_trace = cxl_stop_trace_psl9,
.write_timebase_ctrl = write_timebase_ctrl_psl9,
.timebase_read = timebase_read_psl9,
@@ -1889,8 +1887,7 @@ static void cxl_pci_remove_adapter(struct cxl *adapter)
* Flush adapter datacache as its about to be removed.
* Not supported on P9 DD1.
*/
- if ((cxl_is_power8()) ||
- ((cxl_is_power9() && !cpu_has_feature(CPU_FTR_POWER9_DD1))))
+ if ((cxl_is_power8()) || (!(cxl_is_power9_dd1())))
cxl_data_cache_flush(adapter);
cxl_deconfigure_adapter(adapter);
diff --git a/drivers/misc/mei/bus.c b/drivers/misc/mei/bus.c
index d1928fdd0f43..07aad8576334 100644
--- a/drivers/misc/mei/bus.c
+++ b/drivers/misc/mei/bus.c
@@ -763,8 +763,10 @@ static ssize_t modalias_show(struct device *dev, struct device_attribute *a,
{
struct mei_cl_device *cldev = to_mei_cl_device(dev);
const uuid_le *uuid = mei_me_cl_uuid(cldev->me_cl);
+ u8 version = mei_me_cl_ver(cldev->me_cl);
- return scnprintf(buf, PAGE_SIZE, "mei:%s:%pUl:", cldev->name, uuid);
+ return scnprintf(buf, PAGE_SIZE, "mei:%s:%pUl:%02X:",
+ cldev->name, uuid, version);
}
static DEVICE_ATTR_RO(modalias);
diff --git a/drivers/misc/sgi-xp/xp.h b/drivers/misc/sgi-xp/xp.h
index c862cd4583cc..b8069eec18cb 100644
--- a/drivers/misc/sgi-xp/xp.h
+++ b/drivers/misc/sgi-xp/xp.h
@@ -309,6 +309,9 @@ static inline enum xp_retval
xpc_send(short partid, int ch_number, u32 flags, void *payload,
u16 payload_size)
{
+ if (!xpc_interface.send)
+ return xpNotLoaded;
+
return xpc_interface.send(partid, ch_number, flags, payload,
payload_size);
}
@@ -317,6 +320,9 @@ static inline enum xp_retval
xpc_send_notify(short partid, int ch_number, u32 flags, void *payload,
u16 payload_size, xpc_notify_func func, void *key)
{
+ if (!xpc_interface.send_notify)
+ return xpNotLoaded;
+
return xpc_interface.send_notify(partid, ch_number, flags, payload,
payload_size, func, key);
}
@@ -324,12 +330,16 @@ xpc_send_notify(short partid, int ch_number, u32 flags, void *payload,
static inline void
xpc_received(short partid, int ch_number, void *payload)
{
- return xpc_interface.received(partid, ch_number, payload);
+ if (xpc_interface.received)
+ xpc_interface.received(partid, ch_number, payload);
}
static inline enum xp_retval
xpc_partid_to_nasids(short partid, void *nasids)
{
+ if (!xpc_interface.partid_to_nasids)
+ return xpNotLoaded;
+
return xpc_interface.partid_to_nasids(partid, nasids);
}
diff --git a/drivers/misc/sgi-xp/xp_main.c b/drivers/misc/sgi-xp/xp_main.c
index 01be66d02ca8..6d7f557fd1c1 100644
--- a/drivers/misc/sgi-xp/xp_main.c
+++ b/drivers/misc/sgi-xp/xp_main.c
@@ -69,23 +69,9 @@ struct xpc_registration xpc_registrations[XPC_MAX_NCHANNELS];
EXPORT_SYMBOL_GPL(xpc_registrations);
/*
- * Initialize the XPC interface to indicate that XPC isn't loaded.
+ * Initialize the XPC interface to NULL to indicate that XPC isn't loaded.
*/
-static enum xp_retval
-xpc_notloaded(void)
-{
- return xpNotLoaded;
-}
-
-struct xpc_interface xpc_interface = {
- (void (*)(int))xpc_notloaded,
- (void (*)(int))xpc_notloaded,
- (enum xp_retval(*)(short, int, u32, void *, u16))xpc_notloaded,
- (enum xp_retval(*)(short, int, u32, void *, u16, xpc_notify_func,
- void *))xpc_notloaded,
- (void (*)(short, int, void *))xpc_notloaded,
- (enum xp_retval(*)(short, void *))xpc_notloaded
-};
+struct xpc_interface xpc_interface = { };
EXPORT_SYMBOL_GPL(xpc_interface);
/*
@@ -115,17 +101,7 @@ EXPORT_SYMBOL_GPL(xpc_set_interface);
void
xpc_clear_interface(void)
{
- xpc_interface.connect = (void (*)(int))xpc_notloaded;
- xpc_interface.disconnect = (void (*)(int))xpc_notloaded;
- xpc_interface.send = (enum xp_retval(*)(short, int, u32, void *, u16))
- xpc_notloaded;
- xpc_interface.send_notify = (enum xp_retval(*)(short, int, u32, void *,
- u16, xpc_notify_func,
- void *))xpc_notloaded;
- xpc_interface.received = (void (*)(short, int, void *))
- xpc_notloaded;
- xpc_interface.partid_to_nasids = (enum xp_retval(*)(short, void *))
- xpc_notloaded;
+ memset(&xpc_interface, 0, sizeof(xpc_interface));
}
EXPORT_SYMBOL_GPL(xpc_clear_interface);
@@ -188,7 +164,8 @@ xpc_connect(int ch_number, xpc_channel_func func, void *key, u16 payload_size,
mutex_unlock(&registration->mutex);
- xpc_interface.connect(ch_number);
+ if (xpc_interface.connect)
+ xpc_interface.connect(ch_number);
return xpSuccess;
}
@@ -237,7 +214,8 @@ xpc_disconnect(int ch_number)
registration->assigned_limit = 0;
registration->idle_limit = 0;
- xpc_interface.disconnect(ch_number);
+ if (xpc_interface.disconnect)
+ xpc_interface.disconnect(ch_number);
mutex_unlock(&registration->mutex);
diff --git a/drivers/mmc/core/block.c b/drivers/mmc/core/block.c
index 8273b078686d..6ff94a948a4b 100644
--- a/drivers/mmc/core/block.c
+++ b/drivers/mmc/core/block.c
@@ -1184,9 +1184,10 @@ static void mmc_blk_issue_discard_rq(struct mmc_queue *mq, struct request *req)
struct mmc_card *card = md->queue.card;
unsigned int from, nr, arg;
int err = 0, type = MMC_BLK_DISCARD;
+ blk_status_t status = BLK_STS_OK;
if (!mmc_can_erase(card)) {
- err = -EOPNOTSUPP;
+ status = BLK_STS_NOTSUPP;
goto fail;
}
@@ -1212,10 +1213,12 @@ static void mmc_blk_issue_discard_rq(struct mmc_queue *mq, struct request *req)
if (!err)
err = mmc_erase(card, from, nr, arg);
} while (err == -EIO && !mmc_blk_reset(md, card->host, type));
- if (!err)
+ if (err)
+ status = BLK_STS_IOERR;
+ else
mmc_blk_reset_success(md, type);
fail:
- blk_end_request(req, err, blk_rq_bytes(req));
+ blk_end_request(req, status, blk_rq_bytes(req));
}
static void mmc_blk_issue_secdiscard_rq(struct mmc_queue *mq,
@@ -1225,9 +1228,10 @@ static void mmc_blk_issue_secdiscard_rq(struct mmc_queue *mq,
struct mmc_card *card = md->queue.card;
unsigned int from, nr, arg;
int err = 0, type = MMC_BLK_SECDISCARD;
+ blk_status_t status = BLK_STS_OK;
if (!(mmc_can_secure_erase_trim(card))) {
- err = -EOPNOTSUPP;
+ status = BLK_STS_NOTSUPP;
goto out;
}
@@ -1254,8 +1258,10 @@ retry:
err = mmc_erase(card, from, nr, arg);
if (err == -EIO)
goto out_retry;
- if (err)
+ if (err) {
+ status = BLK_STS_IOERR;
goto out;
+ }
if (arg == MMC_SECURE_TRIM1_ARG) {
if (card->quirks & MMC_QUIRK_INAND_CMD38) {
@@ -1270,8 +1276,10 @@ retry:
err = mmc_erase(card, from, nr, MMC_SECURE_TRIM2_ARG);
if (err == -EIO)
goto out_retry;
- if (err)
+ if (err) {
+ status = BLK_STS_IOERR;
goto out;
+ }
}
out_retry:
@@ -1280,7 +1288,7 @@ out_retry:
if (!err)
mmc_blk_reset_success(md, type);
out:
- blk_end_request(req, err, blk_rq_bytes(req));
+ blk_end_request(req, status, blk_rq_bytes(req));
}
static void mmc_blk_issue_flush(struct mmc_queue *mq, struct request *req)
@@ -1290,10 +1298,7 @@ static void mmc_blk_issue_flush(struct mmc_queue *mq, struct request *req)
int ret = 0;
ret = mmc_flush_cache(card);
- if (ret)
- ret = -EIO;
-
- blk_end_request_all(req, ret);
+ blk_end_request_all(req, ret ? BLK_STS_IOERR : BLK_STS_OK);
}
/*
@@ -1641,7 +1646,7 @@ static void mmc_blk_rw_cmd_abort(struct mmc_queue *mq, struct mmc_card *card,
{
if (mmc_card_removed(card))
req->rq_flags |= RQF_QUIET;
- while (blk_end_request(req, -EIO, blk_rq_cur_bytes(req)));
+ while (blk_end_request(req, BLK_STS_IOERR, blk_rq_cur_bytes(req)));
mmc_queue_req_free(mq, mqrq);
}
@@ -1661,7 +1666,7 @@ static void mmc_blk_rw_try_restart(struct mmc_queue *mq, struct request *req,
*/
if (mmc_card_removed(mq->card)) {
req->rq_flags |= RQF_QUIET;
- blk_end_request_all(req, -EIO);
+ blk_end_request_all(req, BLK_STS_IOERR);
mmc_queue_req_free(mq, mqrq);
return;
}
@@ -1743,7 +1748,7 @@ static void mmc_blk_issue_rw_rq(struct mmc_queue *mq, struct request *new_req)
*/
mmc_blk_reset_success(md, type);
- req_pending = blk_end_request(old_req, 0,
+ req_pending = blk_end_request(old_req, BLK_STS_OK,
brq->data.bytes_xfered);
/*
* If the blk_end_request function returns non-zero even
@@ -1811,7 +1816,7 @@ static void mmc_blk_issue_rw_rq(struct mmc_queue *mq, struct request *new_req)
* time, so we only reach here after trying to
* read a single sector.
*/
- req_pending = blk_end_request(old_req, -EIO,
+ req_pending = blk_end_request(old_req, BLK_STS_IOERR,
brq->data.blksz);
if (!req_pending) {
mmc_queue_req_free(mq, mq_rq);
@@ -1860,7 +1865,7 @@ void mmc_blk_issue_rq(struct mmc_queue *mq, struct request *req)
ret = mmc_blk_part_switch(card, md);
if (ret) {
if (req) {
- blk_end_request_all(req, -EIO);
+ blk_end_request_all(req, BLK_STS_IOERR);
}
goto out;
}
diff --git a/drivers/mmc/core/pwrseq_simple.c b/drivers/mmc/core/pwrseq_simple.c
index 1304160de168..13ef162cf066 100644
--- a/drivers/mmc/core/pwrseq_simple.c
+++ b/drivers/mmc/core/pwrseq_simple.c
@@ -27,6 +27,7 @@ struct mmc_pwrseq_simple {
struct mmc_pwrseq pwrseq;
bool clk_enabled;
u32 post_power_on_delay_ms;
+ u32 power_off_delay_us;
struct clk *ext_clk;
struct gpio_descs *reset_gpios;
};
@@ -78,6 +79,10 @@ static void mmc_pwrseq_simple_power_off(struct mmc_host *host)
mmc_pwrseq_simple_set_gpios_value(pwrseq, 1);
+ if (pwrseq->power_off_delay_us)
+ usleep_range(pwrseq->power_off_delay_us,
+ 2 * pwrseq->power_off_delay_us);
+
if (!IS_ERR(pwrseq->ext_clk) && pwrseq->clk_enabled) {
clk_disable_unprepare(pwrseq->ext_clk);
pwrseq->clk_enabled = false;
@@ -119,6 +124,8 @@ static int mmc_pwrseq_simple_probe(struct platform_device *pdev)
device_property_read_u32(dev, "post-power-on-delay-ms",
&pwrseq->post_power_on_delay_ms);
+ device_property_read_u32(dev, "power-off-delay-us",
+ &pwrseq->power_off_delay_us);
pwrseq->pwrseq.dev = dev;
pwrseq->pwrseq.ops = &mmc_pwrseq_simple_ops;
diff --git a/drivers/mmc/core/queue.c b/drivers/mmc/core/queue.c
index 5c37b6be3e7b..b659a28c8018 100644
--- a/drivers/mmc/core/queue.c
+++ b/drivers/mmc/core/queue.c
@@ -133,7 +133,7 @@ static void mmc_request_fn(struct request_queue *q)
if (!mq) {
while ((req = blk_fetch_request(q)) != NULL) {
req->rq_flags |= RQF_QUIET;
- __blk_end_request_all(req, -EIO);
+ __blk_end_request_all(req, BLK_STS_IOERR);
}
return;
}
@@ -388,7 +388,6 @@ int mmc_init_queue(struct mmc_queue *mq, struct mmc_card *card,
mmc_queue_setup_discard(mq->queue, card);
if (card->bouncesz) {
- blk_queue_bounce_limit(mq->queue, BLK_BOUNCE_ANY);
blk_queue_max_hw_sectors(mq->queue, card->bouncesz / 512);
blk_queue_max_segments(mq->queue, card->bouncesz / 512);
blk_queue_max_segment_size(mq->queue, card->bouncesz);
diff --git a/drivers/mmc/host/cavium-octeon.c b/drivers/mmc/host/cavium-octeon.c
index 772d0900026d..951d2cdd7888 100644
--- a/drivers/mmc/host/cavium-octeon.c
+++ b/drivers/mmc/host/cavium-octeon.c
@@ -108,7 +108,7 @@ static void octeon_mmc_release_bus(struct cvm_mmc_host *host)
static void octeon_mmc_int_enable(struct cvm_mmc_host *host, u64 val)
{
writeq(val, host->base + MIO_EMM_INT(host));
- if (!host->dma_active || (host->dma_active && !host->has_ciu3))
+ if (!host->has_ciu3)
writeq(val, host->base + MIO_EMM_INT_EN(host));
}
@@ -267,7 +267,7 @@ static int octeon_mmc_probe(struct platform_device *pdev)
}
host->global_pwr_gpiod = devm_gpiod_get_optional(&pdev->dev,
- "power-gpios",
+ "power",
GPIOD_OUT_HIGH);
if (IS_ERR(host->global_pwr_gpiod)) {
dev_err(&pdev->dev, "Invalid power GPIO\n");
@@ -288,11 +288,20 @@ static int octeon_mmc_probe(struct platform_device *pdev)
if (ret) {
dev_err(&pdev->dev, "Error populating slots\n");
octeon_mmc_set_shared_power(host, 0);
- return ret;
+ goto error;
}
i++;
}
return 0;
+
+error:
+ for (i = 0; i < CAVIUM_MAX_MMC; i++) {
+ if (host->slot[i])
+ cvm_mmc_of_slot_remove(host->slot[i]);
+ if (host->slot_pdev[i])
+ of_platform_device_destroy(&host->slot_pdev[i]->dev, NULL);
+ }
+ return ret;
}
static int octeon_mmc_remove(struct platform_device *pdev)
diff --git a/drivers/mmc/host/cavium-thunderx.c b/drivers/mmc/host/cavium-thunderx.c
index fe3d77267cd6..b9cc95998799 100644
--- a/drivers/mmc/host/cavium-thunderx.c
+++ b/drivers/mmc/host/cavium-thunderx.c
@@ -146,6 +146,12 @@ static int thunder_mmc_probe(struct pci_dev *pdev,
return 0;
error:
+ for (i = 0; i < CAVIUM_MAX_MMC; i++) {
+ if (host->slot[i])
+ cvm_mmc_of_slot_remove(host->slot[i]);
+ if (host->slot_pdev[i])
+ of_platform_device_destroy(&host->slot_pdev[i]->dev, NULL);
+ }
clk_disable_unprepare(host->clk);
return ret;
}
diff --git a/drivers/mmc/host/cavium.c b/drivers/mmc/host/cavium.c
index 58b51ba6aabd..b8aaf0fdb77c 100644
--- a/drivers/mmc/host/cavium.c
+++ b/drivers/mmc/host/cavium.c
@@ -839,14 +839,14 @@ static void cvm_mmc_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
cvm_mmc_reset_bus(slot);
if (host->global_pwr_gpiod)
host->set_shared_power(host, 0);
- else
+ else if (!IS_ERR(mmc->supply.vmmc))
mmc_regulator_set_ocr(mmc, mmc->supply.vmmc, 0);
break;
case MMC_POWER_UP:
if (host->global_pwr_gpiod)
host->set_shared_power(host, 1);
- else
+ else if (!IS_ERR(mmc->supply.vmmc))
mmc_regulator_set_ocr(mmc, mmc->supply.vmmc, ios->vdd);
break;
}
@@ -968,20 +968,15 @@ static int cvm_mmc_of_parse(struct device *dev, struct cvm_mmc_slot *slot)
return -EINVAL;
}
- mmc->supply.vmmc = devm_regulator_get_optional(dev, "vmmc");
- if (IS_ERR(mmc->supply.vmmc)) {
- if (PTR_ERR(mmc->supply.vmmc) == -EPROBE_DEFER)
- return -EPROBE_DEFER;
- /*
- * Legacy Octeon firmware has no regulator entry, fall-back to
- * a hard-coded voltage to get a sane OCR.
- */
+ ret = mmc_regulator_get_supply(mmc);
+ if (ret == -EPROBE_DEFER)
+ return ret;
+ /*
+ * Legacy Octeon firmware has no regulator entry, fall-back to
+ * a hard-coded voltage to get a sane OCR.
+ */
+ if (IS_ERR(mmc->supply.vmmc))
mmc->ocr_avail = MMC_VDD_32_33 | MMC_VDD_33_34;
- } else {
- ret = mmc_regulator_get_ocrmask(mmc->supply.vmmc);
- if (ret > 0)
- mmc->ocr_avail = ret;
- }
/* Common MMC bindings */
ret = mmc_of_parse(mmc);
diff --git a/drivers/mmc/host/meson-gx-mmc.c b/drivers/mmc/host/meson-gx-mmc.c
index 1842ed341af1..de962c2d5e00 100644
--- a/drivers/mmc/host/meson-gx-mmc.c
+++ b/drivers/mmc/host/meson-gx-mmc.c
@@ -210,6 +210,15 @@ static void meson_mmc_get_transfer_mode(struct mmc_host *mmc,
int i;
bool use_desc_chain_mode = true;
+ /*
+ * Broken SDIO with AP6255-based WiFi on Khadas VIM Pro has been
+ * reported. For some strange reason this occurs in descriptor
+ * chain mode only. So let's fall back to bounce buffer mode
+ * for command SD_IO_RW_EXTENDED.
+ */
+ if (mrq->cmd->opcode == SD_IO_RW_EXTENDED)
+ return;
+
for_each_sg(data->sg, sg, data->sg_len, i)
/* check for 8 byte alignment */
if (sg->offset & 7) {
diff --git a/drivers/mmc/host/sdhci-iproc.c b/drivers/mmc/host/sdhci-iproc.c
index 3275d4995812..61666d269771 100644
--- a/drivers/mmc/host/sdhci-iproc.c
+++ b/drivers/mmc/host/sdhci-iproc.c
@@ -187,7 +187,8 @@ static const struct sdhci_iproc_data iproc_cygnus_data = {
};
static const struct sdhci_pltfm_data sdhci_iproc_pltfm_data = {
- .quirks = SDHCI_QUIRK_DATA_TIMEOUT_USES_SDCLK,
+ .quirks = SDHCI_QUIRK_DATA_TIMEOUT_USES_SDCLK |
+ SDHCI_QUIRK_MULTIBLOCK_READ_ACMD12,
.quirks2 = SDHCI_QUIRK2_ACMD23_BROKEN,
.ops = &sdhci_iproc_ops,
};
diff --git a/drivers/mmc/host/sdhci-pci-core.c b/drivers/mmc/host/sdhci-pci-core.c
index 92fc3f7c538d..18957fea82ff 100644
--- a/drivers/mmc/host/sdhci-pci-core.c
+++ b/drivers/mmc/host/sdhci-pci-core.c
@@ -404,10 +404,9 @@ struct intel_host {
bool d3_retune;
};
-const u8 intel_dsm_uuid[] = {
- 0xA5, 0x3E, 0xC1, 0xF6, 0xCD, 0x65, 0x1F, 0x46,
- 0xAB, 0x7A, 0x29, 0xF7, 0xE8, 0xD5, 0xBD, 0x61,
-};
+static const guid_t intel_dsm_guid =
+ GUID_INIT(0xF6C13EA5, 0x65CD, 0x461F,
+ 0xAB, 0x7A, 0x29, 0xF7, 0xE8, 0xD5, 0xBD, 0x61);
static int __intel_dsm(struct intel_host *intel_host, struct device *dev,
unsigned int fn, u32 *result)
@@ -416,7 +415,7 @@ static int __intel_dsm(struct intel_host *intel_host, struct device *dev,
int err = 0;
size_t len;
- obj = acpi_evaluate_dsm(ACPI_HANDLE(dev), intel_dsm_uuid, 0, fn, NULL);
+ obj = acpi_evaluate_dsm(ACPI_HANDLE(dev), &intel_dsm_guid, 0, fn, NULL);
if (!obj)
return -EOPNOTSUPP;
diff --git a/drivers/mmc/host/sdhci-xenon-phy.c b/drivers/mmc/host/sdhci-xenon-phy.c
index 6356781f1cca..f7e26b031e76 100644
--- a/drivers/mmc/host/sdhci-xenon-phy.c
+++ b/drivers/mmc/host/sdhci-xenon-phy.c
@@ -787,14 +787,6 @@ int xenon_phy_adj(struct sdhci_host *host, struct mmc_ios *ios)
return ret;
}
-void xenon_clean_phy(struct sdhci_host *host)
-{
- struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
- struct xenon_priv *priv = sdhci_pltfm_priv(pltfm_host);
-
- kfree(priv->phy_params);
-}
-
static int xenon_add_phy(struct device_node *np, struct sdhci_host *host,
const char *phy_name)
{
@@ -819,11 +811,7 @@ static int xenon_add_phy(struct device_node *np, struct sdhci_host *host,
if (ret)
return ret;
- ret = xenon_emmc_phy_parse_param_dt(host, np, priv->phy_params);
- if (ret)
- xenon_clean_phy(host);
-
- return ret;
+ return xenon_emmc_phy_parse_param_dt(host, np, priv->phy_params);
}
int xenon_phy_parse_dt(struct device_node *np, struct sdhci_host *host)
diff --git a/drivers/mmc/host/sdhci-xenon.c b/drivers/mmc/host/sdhci-xenon.c
index 67246655315b..bc1781bb070b 100644
--- a/drivers/mmc/host/sdhci-xenon.c
+++ b/drivers/mmc/host/sdhci-xenon.c
@@ -486,7 +486,7 @@ static int xenon_probe(struct platform_device *pdev)
err = xenon_sdhc_prepare(host);
if (err)
- goto clean_phy_param;
+ goto err_clk;
err = sdhci_add_host(host);
if (err)
@@ -496,8 +496,6 @@ static int xenon_probe(struct platform_device *pdev)
remove_sdhc:
xenon_sdhc_unprepare(host);
-clean_phy_param:
- xenon_clean_phy(host);
err_clk:
clk_disable_unprepare(pltfm_host->clk);
free_pltfm:
@@ -510,8 +508,6 @@ static int xenon_remove(struct platform_device *pdev)
struct sdhci_host *host = platform_get_drvdata(pdev);
struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
- xenon_clean_phy(host);
-
sdhci_remove_host(host, 0);
xenon_sdhc_unprepare(host);
diff --git a/drivers/mmc/host/sdhci-xenon.h b/drivers/mmc/host/sdhci-xenon.h
index 6e6523ea01ce..73debb42dc2f 100644
--- a/drivers/mmc/host/sdhci-xenon.h
+++ b/drivers/mmc/host/sdhci-xenon.h
@@ -93,7 +93,6 @@ struct xenon_priv {
};
int xenon_phy_adj(struct sdhci_host *host, struct mmc_ios *ios);
-void xenon_clean_phy(struct sdhci_host *host);
int xenon_phy_parse_dt(struct device_node *np,
struct sdhci_host *host);
void xenon_soc_pad_ctrl(struct sdhci_host *host,
diff --git a/drivers/mtd/mtd_blkdevs.c b/drivers/mtd/mtd_blkdevs.c
index 6b8d5cd7dbf6..f336a9b85576 100644
--- a/drivers/mtd/mtd_blkdevs.c
+++ b/drivers/mtd/mtd_blkdevs.c
@@ -73,7 +73,7 @@ static void blktrans_dev_put(struct mtd_blktrans_dev *dev)
}
-static int do_blktrans_request(struct mtd_blktrans_ops *tr,
+static blk_status_t do_blktrans_request(struct mtd_blktrans_ops *tr,
struct mtd_blktrans_dev *dev,
struct request *req)
{
@@ -84,33 +84,37 @@ static int do_blktrans_request(struct mtd_blktrans_ops *tr,
nsect = blk_rq_cur_bytes(req) >> tr->blkshift;
buf = bio_data(req->bio);
- if (req_op(req) == REQ_OP_FLUSH)
- return tr->flush(dev);
+ if (req_op(req) == REQ_OP_FLUSH) {
+ if (tr->flush(dev))
+ return BLK_STS_IOERR;
+ return BLK_STS_OK;
+ }
if (blk_rq_pos(req) + blk_rq_cur_sectors(req) >
get_capacity(req->rq_disk))
- return -EIO;
+ return BLK_STS_IOERR;
switch (req_op(req)) {
case REQ_OP_DISCARD:
- return tr->discard(dev, block, nsect);
+ if (tr->discard(dev, block, nsect))
+ return BLK_STS_IOERR;
+ return BLK_STS_OK;
case REQ_OP_READ:
for (; nsect > 0; nsect--, block++, buf += tr->blksize)
if (tr->readsect(dev, block, buf))
- return -EIO;
+ return BLK_STS_IOERR;
rq_flush_dcache_pages(req);
- return 0;
+ return BLK_STS_OK;
case REQ_OP_WRITE:
if (!tr->writesect)
- return -EIO;
+ return BLK_STS_IOERR;
rq_flush_dcache_pages(req);
for (; nsect > 0; nsect--, block++, buf += tr->blksize)
if (tr->writesect(dev, block, buf))
- return -EIO;
- return 0;
+ return BLK_STS_IOERR;
default:
- return -EIO;
+ return BLK_STS_IOERR;
}
}
@@ -132,7 +136,7 @@ static void mtd_blktrans_work(struct work_struct *work)
spin_lock_irq(rq->queue_lock);
while (1) {
- int res;
+ blk_status_t res;
dev->bg_stop = false;
if (!req && !(req = blk_fetch_request(rq))) {
@@ -178,7 +182,7 @@ static void mtd_blktrans_request(struct request_queue *rq)
if (!dev)
while ((req = blk_fetch_request(rq)) != NULL)
- __blk_end_request_all(req, -ENODEV);
+ __blk_end_request_all(req, BLK_STS_IOERR);
else
queue_work(dev->wq, &dev->work);
}
@@ -413,6 +417,7 @@ int add_mtd_blktrans_dev(struct mtd_blktrans_dev *new)
new->rq->queuedata = new;
blk_queue_logical_block_size(new->rq, tr->blksize);
+ blk_queue_bounce_limit(new->rq, BLK_BOUNCE_HIGH);
queue_flag_set_unlocked(QUEUE_FLAG_NONROT, new->rq);
queue_flag_clear_unlocked(QUEUE_FLAG_ADD_RANDOM, new->rq);
diff --git a/drivers/mtd/nand/nand_base.c b/drivers/mtd/nand/nand_base.c
index d474378ed810..b1dd12729f19 100644
--- a/drivers/mtd/nand/nand_base.c
+++ b/drivers/mtd/nand/nand_base.c
@@ -202,7 +202,7 @@ static int nand_ooblayout_free_lp_hamming(struct mtd_info *mtd, int section,
return 0;
}
-const struct mtd_ooblayout_ops nand_ooblayout_lp_hamming_ops = {
+static const struct mtd_ooblayout_ops nand_ooblayout_lp_hamming_ops = {
.ecc = nand_ooblayout_ecc_lp_hamming,
.free = nand_ooblayout_free_lp_hamming,
};
@@ -4361,7 +4361,7 @@ int nand_scan_ident(struct mtd_info *mtd, int maxchips,
/* Initialize the ->data_interface field. */
ret = nand_init_data_interface(chip);
if (ret)
- return ret;
+ goto err_nand_init;
/*
* Setup the data interface correctly on the chip and controller side.
@@ -4373,7 +4373,7 @@ int nand_scan_ident(struct mtd_info *mtd, int maxchips,
*/
ret = nand_setup_data_interface(chip);
if (ret)
- return ret;
+ goto err_nand_init;
nand_maf_id = chip->id.data[0];
nand_dev_id = chip->id.data[1];
@@ -4404,6 +4404,12 @@ int nand_scan_ident(struct mtd_info *mtd, int maxchips,
mtd->size = i * chip->chipsize;
return 0;
+
+err_nand_init:
+ /* Free manufacturer priv data. */
+ nand_manufacturer_cleanup(chip);
+
+ return ret;
}
EXPORT_SYMBOL(nand_scan_ident);
@@ -4574,18 +4580,23 @@ int nand_scan_tail(struct mtd_info *mtd)
/* New bad blocks should be marked in OOB, flash-based BBT, or both */
if (WARN_ON((chip->bbt_options & NAND_BBT_NO_OOB_BBM) &&
- !(chip->bbt_options & NAND_BBT_USE_FLASH)))
- return -EINVAL;
+ !(chip->bbt_options & NAND_BBT_USE_FLASH))) {
+ ret = -EINVAL;
+ goto err_ident;
+ }
if (invalid_ecc_page_accessors(chip)) {
pr_err("Invalid ECC page accessors setup\n");
- return -EINVAL;
+ ret = -EINVAL;
+ goto err_ident;
}
if (!(chip->options & NAND_OWN_BUFFERS)) {
nbuf = kzalloc(sizeof(*nbuf), GFP_KERNEL);
- if (!nbuf)
- return -ENOMEM;
+ if (!nbuf) {
+ ret = -ENOMEM;
+ goto err_ident;
+ }
nbuf->ecccalc = kmalloc(mtd->oobsize, GFP_KERNEL);
if (!nbuf->ecccalc) {
@@ -4608,8 +4619,10 @@ int nand_scan_tail(struct mtd_info *mtd)
chip->buffers = nbuf;
} else {
- if (!chip->buffers)
- return -ENOMEM;
+ if (!chip->buffers) {
+ ret = -ENOMEM;
+ goto err_ident;
+ }
}
/* Set the internal oob buffer location, just after the page data */
@@ -4842,7 +4855,11 @@ int nand_scan_tail(struct mtd_info *mtd)
return 0;
/* Build bad block table */
- return chip->scan_bbt(mtd);
+ ret = chip->scan_bbt(mtd);
+ if (ret)
+ goto err_free;
+ return 0;
+
err_free:
if (nbuf) {
kfree(nbuf->databuf);
@@ -4850,6 +4867,13 @@ err_free:
kfree(nbuf->ecccalc);
kfree(nbuf);
}
+
+err_ident:
+ /* Clean up nand_scan_ident(). */
+
+ /* Free manufacturer priv data. */
+ nand_manufacturer_cleanup(chip);
+
return ret;
}
EXPORT_SYMBOL(nand_scan_tail);
diff --git a/drivers/mtd/nand/nand_ids.c b/drivers/mtd/nand/nand_ids.c
index 9d5ca0e540b5..92e2cf8e9ff9 100644
--- a/drivers/mtd/nand/nand_ids.c
+++ b/drivers/mtd/nand/nand_ids.c
@@ -6,7 +6,6 @@
* published by the Free Software Foundation.
*
*/
-#include <linux/module.h>
#include <linux/mtd/nand.h>
#include <linux/sizes.h>
diff --git a/drivers/mtd/nand/nand_samsung.c b/drivers/mtd/nand/nand_samsung.c
index 9cfc4035a420..1e0755997762 100644
--- a/drivers/mtd/nand/nand_samsung.c
+++ b/drivers/mtd/nand/nand_samsung.c
@@ -84,6 +84,9 @@ static void samsung_nand_decode_id(struct nand_chip *chip)
case 7:
chip->ecc_strength_ds = 60;
break;
+ default:
+ WARN(1, "Could not decode ECC info");
+ chip->ecc_step_ds = 0;
}
}
} else {
diff --git a/drivers/mtd/nand/tango_nand.c b/drivers/mtd/nand/tango_nand.c
index 05b6e1065203..49b286c6c10f 100644
--- a/drivers/mtd/nand/tango_nand.c
+++ b/drivers/mtd/nand/tango_nand.c
@@ -55,10 +55,10 @@
* byte 1 for other packets in the page (PKT_N, for N > 0)
* ERR_COUNT_PKT_N is the max error count over all but the first packet.
*/
-#define DECODE_OK_PKT_0(v) ((v) & BIT(7))
-#define DECODE_OK_PKT_N(v) ((v) & BIT(15))
#define ERR_COUNT_PKT_0(v) (((v) >> 0) & 0x3f)
#define ERR_COUNT_PKT_N(v) (((v) >> 8) & 0x3f)
+#define DECODE_FAIL_PKT_0(v) (((v) & BIT(7)) == 0)
+#define DECODE_FAIL_PKT_N(v) (((v) & BIT(15)) == 0)
/* Offsets relative to pbus_base */
#define PBUS_CS_CTRL 0x83c
@@ -193,6 +193,8 @@ static int check_erased_page(struct nand_chip *chip, u8 *buf)
chip->ecc.strength);
if (res < 0)
mtd->ecc_stats.failed++;
+ else
+ mtd->ecc_stats.corrected += res;
bitflips = max(res, bitflips);
buf += pkt_size;
@@ -202,9 +204,11 @@ static int check_erased_page(struct nand_chip *chip, u8 *buf)
return bitflips;
}
-static int decode_error_report(struct tango_nfc *nfc)
+static int decode_error_report(struct nand_chip *chip)
{
u32 status, res;
+ struct mtd_info *mtd = nand_to_mtd(chip);
+ struct tango_nfc *nfc = to_tango_nfc(chip->controller);
status = readl_relaxed(nfc->reg_base + NFC_XFER_STATUS);
if (status & PAGE_IS_EMPTY)
@@ -212,10 +216,14 @@ static int decode_error_report(struct tango_nfc *nfc)
res = readl_relaxed(nfc->mem_base + ERROR_REPORT);
- if (DECODE_OK_PKT_0(res) && DECODE_OK_PKT_N(res))
- return max(ERR_COUNT_PKT_0(res), ERR_COUNT_PKT_N(res));
+ if (DECODE_FAIL_PKT_0(res) || DECODE_FAIL_PKT_N(res))
+ return -EBADMSG;
+
+ /* ERR_COUNT_PKT_N is max, not sum, but that's all we have */
+ mtd->ecc_stats.corrected +=
+ ERR_COUNT_PKT_0(res) + ERR_COUNT_PKT_N(res);
- return -EBADMSG;
+ return max(ERR_COUNT_PKT_0(res), ERR_COUNT_PKT_N(res));
}
static void tango_dma_callback(void *arg)
@@ -282,7 +290,7 @@ static int tango_read_page(struct mtd_info *mtd, struct nand_chip *chip,
if (err)
return err;
- res = decode_error_report(nfc);
+ res = decode_error_report(chip);
if (res < 0) {
chip->ecc.read_oob_raw(mtd, chip, page);
res = check_erased_page(chip, buf);
@@ -663,6 +671,7 @@ static const struct of_device_id tango_nand_ids[] = {
{ .compatible = "sigma,smp8758-nand" },
{ /* sentinel */ }
};
+MODULE_DEVICE_TABLE(of, tango_nand_ids);
static struct platform_driver tango_nand_driver = {
.probe = tango_nand_probe,
diff --git a/drivers/mtd/ubi/block.c b/drivers/mtd/ubi/block.c
index 5497e65439df..c3963f880448 100644
--- a/drivers/mtd/ubi/block.c
+++ b/drivers/mtd/ubi/block.c
@@ -313,10 +313,10 @@ static void ubiblock_do_work(struct work_struct *work)
ret = ubiblock_read(pdu);
rq_flush_dcache_pages(req);
- blk_mq_end_request(req, ret);
+ blk_mq_end_request(req, errno_to_blk_status(ret));
}
-static int ubiblock_queue_rq(struct blk_mq_hw_ctx *hctx,
+static blk_status_t ubiblock_queue_rq(struct blk_mq_hw_ctx *hctx,
const struct blk_mq_queue_data *bd)
{
struct request *req = bd->rq;
@@ -327,9 +327,9 @@ static int ubiblock_queue_rq(struct blk_mq_hw_ctx *hctx,
case REQ_OP_READ:
ubi_sgl_init(&pdu->usgl);
queue_work(dev->wq, &pdu->work);
- return BLK_MQ_RQ_QUEUE_OK;
+ return BLK_STS_OK;
default:
- return BLK_MQ_RQ_QUEUE_ERROR;
+ return BLK_STS_IOERR;
}
}
diff --git a/drivers/net/arcnet/arcnet.c b/drivers/net/arcnet/arcnet.c
index 62ee439d5882..53a1cb551def 100644
--- a/drivers/net/arcnet/arcnet.c
+++ b/drivers/net/arcnet/arcnet.c
@@ -756,6 +756,7 @@ irqreturn_t arcnet_interrupt(int irq, void *dev_id)
struct net_device *dev = dev_id;
struct arcnet_local *lp;
int recbuf, status, diagstatus, didsomething, boguscount;
+ unsigned long flags;
int retval = IRQ_NONE;
arc_printk(D_DURING, dev, "\n");
@@ -765,7 +766,7 @@ irqreturn_t arcnet_interrupt(int irq, void *dev_id)
lp = netdev_priv(dev);
BUG_ON(!lp);
- spin_lock(&lp->lock);
+ spin_lock_irqsave(&lp->lock, flags);
/* RESET flag was enabled - if device is not running, we must
* clear it right away (but nothing else).
@@ -774,7 +775,7 @@ irqreturn_t arcnet_interrupt(int irq, void *dev_id)
if (lp->hw.status(dev) & RESETflag)
lp->hw.command(dev, CFLAGScmd | RESETclear);
lp->hw.intmask(dev, 0);
- spin_unlock(&lp->lock);
+ spin_unlock_irqrestore(&lp->lock, flags);
return retval;
}
@@ -998,7 +999,7 @@ irqreturn_t arcnet_interrupt(int irq, void *dev_id)
udelay(1);
lp->hw.intmask(dev, lp->intmask);
- spin_unlock(&lp->lock);
+ spin_unlock_irqrestore(&lp->lock, flags);
return retval;
}
EXPORT_SYMBOL(arcnet_interrupt);
diff --git a/drivers/net/arcnet/capmode.c b/drivers/net/arcnet/capmode.c
index 2056878fb087..4fa2e46b48d3 100644
--- a/drivers/net/arcnet/capmode.c
+++ b/drivers/net/arcnet/capmode.c
@@ -212,7 +212,7 @@ static int ack_tx(struct net_device *dev, int acked)
ackpkt->soft.cap.proto = 0; /* using protocol 0 for acknowledge */
ackpkt->soft.cap.mes.ack = acked;
- arc_printk(D_PROTO, dev, "Ackknowledge for cap packet %x.\n",
+ arc_printk(D_PROTO, dev, "Acknowledge for cap packet %x.\n",
*((int *)&ackpkt->soft.cap.cookie[0]));
ackskb->protocol = cpu_to_be16(ETH_P_ARCNET);
diff --git a/drivers/net/arcnet/com20020-pci.c b/drivers/net/arcnet/com20020-pci.c
index 239de38fbd6a..47f80b83dcf4 100644
--- a/drivers/net/arcnet/com20020-pci.c
+++ b/drivers/net/arcnet/com20020-pci.c
@@ -135,6 +135,7 @@ static int com20020pci_probe(struct pci_dev *pdev,
for (i = 0; i < ci->devcount; i++) {
struct com20020_pci_channel_map *cm = &ci->chan_map_tbl[i];
struct com20020_dev *card;
+ int dev_id_mask = 0xf;
dev = alloc_arcdev(device);
if (!dev) {
@@ -166,6 +167,7 @@ static int com20020pci_probe(struct pci_dev *pdev,
arcnet_outb(0x00, ioaddr, COM20020_REG_W_COMMAND);
arcnet_inb(ioaddr, COM20020_REG_R_DIAGSTAT);
+ SET_NETDEV_DEV(dev, &pdev->dev);
dev->base_addr = ioaddr;
dev->dev_addr[0] = node;
dev->irq = pdev->irq;
@@ -179,8 +181,8 @@ static int com20020pci_probe(struct pci_dev *pdev,
/* Get the dev_id from the PLX rotary coder */
if (!strncmp(ci->name, "EAE PLX-PCI MA1", 15))
- dev->dev_id = 0xc;
- dev->dev_id ^= inb(priv->misc + ci->rotary) >> 4;
+ dev_id_mask = 0x3;
+ dev->dev_id = (inb(priv->misc + ci->rotary) >> 4) & dev_id_mask;
snprintf(dev->name, sizeof(dev->name), "arc%d-%d", dev->dev_id, i);
diff --git a/drivers/net/arcnet/com20020.c b/drivers/net/arcnet/com20020.c
index 13d9ad4b3f5c..78043a9c5981 100644
--- a/drivers/net/arcnet/com20020.c
+++ b/drivers/net/arcnet/com20020.c
@@ -246,8 +246,6 @@ int com20020_found(struct net_device *dev, int shared)
return -ENODEV;
}
- dev->base_addr = ioaddr;
-
arc_printk(D_NORMAL, dev, "%s: station %02Xh found at %03lXh, IRQ %d.\n",
lp->card_name, dev->dev_addr[0], dev->base_addr, dev->irq);
diff --git a/drivers/net/bonding/bond_3ad.c b/drivers/net/bonding/bond_3ad.c
index c5fd4259da33..e5386ab706ec 100644
--- a/drivers/net/bonding/bond_3ad.c
+++ b/drivers/net/bonding/bond_3ad.c
@@ -90,10 +90,13 @@ enum ad_link_speed_type {
AD_LINK_SPEED_100MBPS,
AD_LINK_SPEED_1000MBPS,
AD_LINK_SPEED_2500MBPS,
+ AD_LINK_SPEED_5000MBPS,
AD_LINK_SPEED_10000MBPS,
+ AD_LINK_SPEED_14000MBPS,
AD_LINK_SPEED_20000MBPS,
AD_LINK_SPEED_25000MBPS,
AD_LINK_SPEED_40000MBPS,
+ AD_LINK_SPEED_50000MBPS,
AD_LINK_SPEED_56000MBPS,
AD_LINK_SPEED_100000MBPS,
};
@@ -259,10 +262,13 @@ static inline int __check_agg_selection_timer(struct port *port)
* %AD_LINK_SPEED_100MBPS,
* %AD_LINK_SPEED_1000MBPS,
* %AD_LINK_SPEED_2500MBPS,
+ * %AD_LINK_SPEED_5000MBPS,
* %AD_LINK_SPEED_10000MBPS
+ * %AD_LINK_SPEED_14000MBPS,
* %AD_LINK_SPEED_20000MBPS
* %AD_LINK_SPEED_25000MBPS
* %AD_LINK_SPEED_40000MBPS
+ * %AD_LINK_SPEED_50000MBPS
* %AD_LINK_SPEED_56000MBPS
* %AD_LINK_SPEED_100000MBPS
*/
@@ -296,10 +302,18 @@ static u16 __get_link_speed(struct port *port)
speed = AD_LINK_SPEED_2500MBPS;
break;
+ case SPEED_5000:
+ speed = AD_LINK_SPEED_5000MBPS;
+ break;
+
case SPEED_10000:
speed = AD_LINK_SPEED_10000MBPS;
break;
+ case SPEED_14000:
+ speed = AD_LINK_SPEED_14000MBPS;
+ break;
+
case SPEED_20000:
speed = AD_LINK_SPEED_20000MBPS;
break;
@@ -312,6 +326,10 @@ static u16 __get_link_speed(struct port *port)
speed = AD_LINK_SPEED_40000MBPS;
break;
+ case SPEED_50000:
+ speed = AD_LINK_SPEED_50000MBPS;
+ break;
+
case SPEED_56000:
speed = AD_LINK_SPEED_56000MBPS;
break;
@@ -707,9 +725,15 @@ static u32 __get_agg_bandwidth(struct aggregator *aggregator)
case AD_LINK_SPEED_2500MBPS:
bandwidth = nports * 2500;
break;
+ case AD_LINK_SPEED_5000MBPS:
+ bandwidth = nports * 5000;
+ break;
case AD_LINK_SPEED_10000MBPS:
bandwidth = nports * 10000;
break;
+ case AD_LINK_SPEED_14000MBPS:
+ bandwidth = nports * 14000;
+ break;
case AD_LINK_SPEED_20000MBPS:
bandwidth = nports * 20000;
break;
@@ -719,6 +743,9 @@ static u32 __get_agg_bandwidth(struct aggregator *aggregator)
case AD_LINK_SPEED_40000MBPS:
bandwidth = nports * 40000;
break;
+ case AD_LINK_SPEED_50000MBPS:
+ bandwidth = nports * 50000;
+ break;
case AD_LINK_SPEED_56000MBPS:
bandwidth = nports * 56000;
break;
@@ -2577,7 +2604,7 @@ int __bond_3ad_get_active_agg_info(struct bonding *bond,
return -1;
ad_info->aggregator_id = aggregator->aggregator_identifier;
- ad_info->ports = aggregator->num_of_ports;
+ ad_info->ports = __agg_active_ports(aggregator);
ad_info->actor_key = aggregator->actor_oper_aggregator_key;
ad_info->partner_key = aggregator->partner_oper_aggregator_key;
ether_addr_copy(ad_info->partner_system,
diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c
index 2be78807fd6e..8ab6bdbe1682 100644
--- a/drivers/net/bonding/bond_main.c
+++ b/drivers/net/bonding/bond_main.c
@@ -2612,11 +2612,13 @@ static void bond_loadbalance_arp_mon(struct bonding *bond)
bond_for_each_slave_rcu(bond, slave, iter) {
unsigned long trans_start = dev_trans_start(slave->dev);
+ slave->new_link = BOND_LINK_NOCHANGE;
+
if (slave->link != BOND_LINK_UP) {
if (bond_time_in_interval(bond, trans_start, 1) &&
bond_time_in_interval(bond, slave->last_rx, 1)) {
- slave->link = BOND_LINK_UP;
+ slave->new_link = BOND_LINK_UP;
slave_state_changed = 1;
/* primary_slave has no meaning in round-robin
@@ -2643,7 +2645,7 @@ static void bond_loadbalance_arp_mon(struct bonding *bond)
if (!bond_time_in_interval(bond, trans_start, 2) ||
!bond_time_in_interval(bond, slave->last_rx, 2)) {
- slave->link = BOND_LINK_DOWN;
+ slave->new_link = BOND_LINK_DOWN;
slave_state_changed = 1;
if (slave->link_failure_count < UINT_MAX)
@@ -2674,6 +2676,11 @@ static void bond_loadbalance_arp_mon(struct bonding *bond)
if (!rtnl_trylock())
goto re_arm;
+ bond_for_each_slave(bond, slave, iter) {
+ if (slave->new_link != BOND_LINK_NOCHANGE)
+ slave->link = slave->new_link;
+ }
+
if (slave_state_changed) {
bond_slave_state_change(bond);
if (BOND_MODE(bond) == BOND_MODE_XOR)
@@ -4185,7 +4192,6 @@ static void bond_destructor(struct net_device *bond_dev)
struct bonding *bond = netdev_priv(bond_dev);
if (bond->wq)
destroy_workqueue(bond->wq);
- free_netdev(bond_dev);
}
void bond_setup(struct net_device *bond_dev)
@@ -4205,7 +4211,8 @@ void bond_setup(struct net_device *bond_dev)
bond_dev->netdev_ops = &bond_netdev_ops;
bond_dev->ethtool_ops = &bond_ethtool_ops;
- bond_dev->destructor = bond_destructor;
+ bond_dev->needs_free_netdev = true;
+ bond_dev->priv_destructor = bond_destructor;
SET_NETDEV_DEVTYPE(bond_dev, &bond_type);
@@ -4271,10 +4278,10 @@ static int bond_check_params(struct bond_params *params)
int arp_validate_value, fail_over_mac_value, primary_reselect_value, i;
struct bond_opt_value newval;
const struct bond_opt_value *valptr;
- int arp_all_targets_value;
+ int arp_all_targets_value = 0;
u16 ad_actor_sys_prio = 0;
u16 ad_user_port_key = 0;
- __be32 arp_target[BOND_MAX_ARP_TARGETS];
+ __be32 arp_target[BOND_MAX_ARP_TARGETS] = { 0 };
int arp_ip_count;
int bond_mode = BOND_MODE_ROUNDROBIN;
int xmit_hashtype = BOND_XMIT_POLICY_LAYER2;
@@ -4501,7 +4508,6 @@ static int bond_check_params(struct bond_params *params)
arp_validate_value = 0;
}
- arp_all_targets_value = 0;
if (arp_all_targets) {
bond_opt_initstr(&newval, arp_all_targets);
valptr = bond_opt_parse(bond_opt_get(BOND_OPT_ARP_ALL_TARGETS),
@@ -4730,7 +4736,7 @@ int bond_create(struct net *net, const char *name)
rtnl_unlock();
if (res < 0)
- bond_destructor(bond_dev);
+ free_netdev(bond_dev);
return res;
}
diff --git a/drivers/net/caif/caif_hsi.c b/drivers/net/caif/caif_hsi.c
index ddabce759456..71a7c3b44fdd 100644
--- a/drivers/net/caif/caif_hsi.c
+++ b/drivers/net/caif/caif_hsi.c
@@ -1121,7 +1121,7 @@ static void cfhsi_setup(struct net_device *dev)
dev->flags = IFF_POINTOPOINT | IFF_NOARP;
dev->mtu = CFHSI_MAX_CAIF_FRAME_SZ;
dev->priv_flags |= IFF_NO_QUEUE;
- dev->destructor = free_netdev;
+ dev->needs_free_netdev = true;
dev->netdev_ops = &cfhsi_netdevops;
for (i = 0; i < CFHSI_PRIO_LAST; ++i)
skb_queue_head_init(&cfhsi->qhead[i]);
diff --git a/drivers/net/caif/caif_serial.c b/drivers/net/caif/caif_serial.c
index c2dea4916e5d..76e1d3545105 100644
--- a/drivers/net/caif/caif_serial.c
+++ b/drivers/net/caif/caif_serial.c
@@ -428,7 +428,7 @@ static void caifdev_setup(struct net_device *dev)
dev->flags = IFF_POINTOPOINT | IFF_NOARP;
dev->mtu = CAIF_MAX_MTU;
dev->priv_flags |= IFF_NO_QUEUE;
- dev->destructor = free_netdev;
+ dev->needs_free_netdev = true;
skb_queue_head_init(&serdev->head);
serdev->common.link_select = CAIF_LINK_LOW_LATENCY;
serdev->common.use_frag = true;
diff --git a/drivers/net/caif/caif_spi.c b/drivers/net/caif/caif_spi.c
index 3281a3e0c144..cb0dcc99fb4f 100644
--- a/drivers/net/caif/caif_spi.c
+++ b/drivers/net/caif/caif_spi.c
@@ -712,7 +712,7 @@ static void cfspi_setup(struct net_device *dev)
dev->flags = IFF_NOARP | IFF_POINTOPOINT;
dev->priv_flags |= IFF_NO_QUEUE;
dev->mtu = SPI_MAX_PAYLOAD_SIZE;
- dev->destructor = free_netdev;
+ dev->needs_free_netdev = true;
skb_queue_head_init(&cfspi->qhead);
skb_queue_head_init(&cfspi->chead);
cfspi->cfdev.link_select = CAIF_LINK_HIGH_BANDW;
diff --git a/drivers/net/caif/caif_virtio.c b/drivers/net/caif/caif_virtio.c
index 6122768c8644..1794ea0420b7 100644
--- a/drivers/net/caif/caif_virtio.c
+++ b/drivers/net/caif/caif_virtio.c
@@ -617,7 +617,7 @@ static void cfv_netdev_setup(struct net_device *netdev)
netdev->tx_queue_len = 100;
netdev->flags = IFF_POINTOPOINT | IFF_NOARP;
netdev->mtu = CFV_DEF_MTU_SIZE;
- netdev->destructor = free_netdev;
+ netdev->needs_free_netdev = true;
}
/* Create debugfs counters for the device */
diff --git a/drivers/net/can/dev.c b/drivers/net/can/dev.c
index 611d16a7061d..ae4ed03dc642 100644
--- a/drivers/net/can/dev.c
+++ b/drivers/net/can/dev.c
@@ -391,6 +391,9 @@ void can_change_state(struct net_device *dev, struct can_frame *cf,
can_update_state_error_stats(dev, new_state);
priv->state = new_state;
+ if (!cf)
+ return;
+
if (unlikely(new_state == CAN_STATE_BUS_OFF)) {
cf->can_id |= CAN_ERR_BUSOFF;
return;
diff --git a/drivers/net/can/peak_canfd/peak_canfd.c b/drivers/net/can/peak_canfd/peak_canfd.c
index 0d57be5ea97b..85268be0c913 100644
--- a/drivers/net/can/peak_canfd/peak_canfd.c
+++ b/drivers/net/can/peak_canfd/peak_canfd.c
@@ -489,7 +489,7 @@ int peak_canfd_handle_msgs_list(struct peak_canfd_priv *priv,
struct pucan_rx_msg *msg_list, int msg_count)
{
void *msg_ptr = msg_list;
- int i, msg_size;
+ int i, msg_size = 0;
for (i = 0; i < msg_count; i++) {
msg_size = peak_canfd_handle_msg(priv, msg_ptr);
diff --git a/drivers/net/can/slcan.c b/drivers/net/can/slcan.c
index eb7173713bbc..6a6e896e52fa 100644
--- a/drivers/net/can/slcan.c
+++ b/drivers/net/can/slcan.c
@@ -417,7 +417,7 @@ static int slc_open(struct net_device *dev)
static void slc_free_netdev(struct net_device *dev)
{
int i = dev->base_addr;
- free_netdev(dev);
+
slcan_devs[i] = NULL;
}
@@ -436,7 +436,8 @@ static const struct net_device_ops slc_netdev_ops = {
static void slc_setup(struct net_device *dev)
{
dev->netdev_ops = &slc_netdev_ops;
- dev->destructor = slc_free_netdev;
+ dev->needs_free_netdev = true;
+ dev->priv_destructor = slc_free_netdev;
dev->hard_header_len = 0;
dev->addr_len = 0;
@@ -761,8 +762,6 @@ static void __exit slcan_exit(void)
if (sl->tty) {
printk(KERN_ERR "%s: tty discipline still running\n",
dev->name);
- /* Intentionally leak the control block. */
- dev->destructor = NULL;
}
unregister_netdev(dev);
diff --git a/drivers/net/can/usb/gs_usb.c b/drivers/net/can/usb/gs_usb.c
index eecee7f8dfb7..afcc1312dbaf 100644
--- a/drivers/net/can/usb/gs_usb.c
+++ b/drivers/net/can/usb/gs_usb.c
@@ -265,6 +265,8 @@ static int gs_cmd_reset(struct gs_usb *gsusb, struct gs_can *gsdev)
sizeof(*dm),
1000);
+ kfree(dm);
+
return rc;
}
diff --git a/drivers/net/can/usb/peak_usb/pcan_usb_core.c b/drivers/net/can/usb/peak_usb/pcan_usb_core.c
index 57913dbbae0a..1ca76e03e965 100644
--- a/drivers/net/can/usb/peak_usb/pcan_usb_core.c
+++ b/drivers/net/can/usb/peak_usb/pcan_usb_core.c
@@ -908,8 +908,6 @@ static int peak_usb_probe(struct usb_interface *intf,
const struct peak_usb_adapter *peak_usb_adapter = NULL;
int i, err = -ENOMEM;
- usb_dev = interface_to_usbdev(intf);
-
/* get corresponding PCAN-USB adapter */
for (i = 0; i < ARRAY_SIZE(peak_usb_adapters_list); i++)
if (peak_usb_adapters_list[i]->device_id == usb_id_product) {
@@ -920,7 +918,7 @@ static int peak_usb_probe(struct usb_interface *intf,
if (!peak_usb_adapter) {
/* should never come except device_id bad usage in this file */
pr_err("%s: didn't find device id. 0x%x in devices list\n",
- PCAN_USB_DRIVER_NAME, usb_dev->descriptor.idProduct);
+ PCAN_USB_DRIVER_NAME, usb_id_product);
return -ENODEV;
}
diff --git a/drivers/net/can/vcan.c b/drivers/net/can/vcan.c
index facca33d53e9..a8cb33264ff1 100644
--- a/drivers/net/can/vcan.c
+++ b/drivers/net/can/vcan.c
@@ -152,7 +152,7 @@ static const struct net_device_ops vcan_netdev_ops = {
static void vcan_setup(struct net_device *dev)
{
dev->type = ARPHRD_CAN;
- dev->mtu = CAN_MTU;
+ dev->mtu = CANFD_MTU;
dev->hard_header_len = 0;
dev->addr_len = 0;
dev->tx_queue_len = 0;
@@ -163,7 +163,7 @@ static void vcan_setup(struct net_device *dev)
dev->flags |= IFF_ECHO;
dev->netdev_ops = &vcan_netdev_ops;
- dev->destructor = free_netdev;
+ dev->needs_free_netdev = true;
}
static struct rtnl_link_ops vcan_link_ops __read_mostly = {
diff --git a/drivers/net/can/vxcan.c b/drivers/net/can/vxcan.c
index 7fbb24795681..cfe889e8f172 100644
--- a/drivers/net/can/vxcan.c
+++ b/drivers/net/can/vxcan.c
@@ -150,13 +150,13 @@ static const struct net_device_ops vxcan_netdev_ops = {
static void vxcan_setup(struct net_device *dev)
{
dev->type = ARPHRD_CAN;
- dev->mtu = CAN_MTU;
+ dev->mtu = CANFD_MTU;
dev->hard_header_len = 0;
dev->addr_len = 0;
dev->tx_queue_len = 0;
dev->flags = (IFF_NOARP|IFF_ECHO);
dev->netdev_ops = &vxcan_netdev_ops;
- dev->destructor = free_netdev;
+ dev->needs_free_netdev = true;
}
/* forward declaration for rtnl_create_link() */
diff --git a/drivers/net/dsa/mv88e6xxx/global2.h b/drivers/net/dsa/mv88e6xxx/global2.h
index 96046bb12ca1..14c0be98e0a4 100644
--- a/drivers/net/dsa/mv88e6xxx/global2.h
+++ b/drivers/net/dsa/mv88e6xxx/global2.h
@@ -114,13 +114,13 @@ static inline int mv88e6xxx_g2_set_eeprom16(struct mv88e6xxx_chip *chip,
return -EOPNOTSUPP;
}
-int mv88e6xxx_g2_pvt_write(struct mv88e6xxx_chip *chip, int src_dev,
- int src_port, u16 data)
+static inline int mv88e6xxx_g2_pvt_write(struct mv88e6xxx_chip *chip,
+ int src_dev, int src_port, u16 data)
{
return -EOPNOTSUPP;
}
-int mv88e6xxx_g2_misc_4_bit_port(struct mv88e6xxx_chip *chip)
+static inline int mv88e6xxx_g2_misc_4_bit_port(struct mv88e6xxx_chip *chip)
{
return -EOPNOTSUPP;
}
diff --git a/drivers/net/dummy.c b/drivers/net/dummy.c
index 149244aac20a..9905b52fe293 100644
--- a/drivers/net/dummy.c
+++ b/drivers/net/dummy.c
@@ -328,7 +328,6 @@ static void dummy_free_netdev(struct net_device *dev)
struct dummy_priv *priv = netdev_priv(dev);
kfree(priv->vfinfo);
- free_netdev(dev);
}
static void dummy_setup(struct net_device *dev)
@@ -338,7 +337,8 @@ static void dummy_setup(struct net_device *dev)
/* Initialize the device structure. */
dev->netdev_ops = &dummy_netdev_ops;
dev->ethtool_ops = &dummy_ethtool_ops;
- dev->destructor = dummy_free_netdev;
+ dev->needs_free_netdev = true;
+ dev->priv_destructor = dummy_free_netdev;
/* Fill in device structure with ethernet-generic values. */
dev->flags |= IFF_NOARP;
diff --git a/drivers/net/ethernet/8390/ax88796.c b/drivers/net/ethernet/8390/ax88796.c
index b0a3b85fc6f8..db02bc2fb4b2 100644
--- a/drivers/net/ethernet/8390/ax88796.c
+++ b/drivers/net/ethernet/8390/ax88796.c
@@ -748,13 +748,13 @@ static int ax_init_dev(struct net_device *dev)
ret = ax_mii_init(dev);
if (ret)
- goto out_irq;
+ goto err_out;
ax_NS8390_init(dev, 0);
ret = register_netdev(dev);
if (ret)
- goto out_irq;
+ goto err_out;
netdev_info(dev, "%dbit, irq %d, %lx, MAC: %pM\n",
ei_local->word16 ? 16 : 8, dev->irq, dev->base_addr,
@@ -762,9 +762,6 @@ static int ax_init_dev(struct net_device *dev)
return 0;
- out_irq:
- /* cleanup irq */
- free_irq(dev->irq, dev);
err_out:
return ret;
}
diff --git a/drivers/net/ethernet/amazon/ena/ena_com.c b/drivers/net/ethernet/amazon/ena/ena_com.c
index 08d11cede9c9..f5b237e0bd60 100644
--- a/drivers/net/ethernet/amazon/ena/ena_com.c
+++ b/drivers/net/ethernet/amazon/ena/ena_com.c
@@ -61,6 +61,8 @@
#define ENA_MMIO_READ_TIMEOUT 0xFFFFFFFF
+#define ENA_REGS_ADMIN_INTR_MASK 1
+
/*****************************************************************************/
/*****************************************************************************/
/*****************************************************************************/
@@ -232,11 +234,9 @@ static struct ena_comp_ctx *__ena_com_submit_admin_cmd(struct ena_com_admin_queu
tail_masked = admin_queue->sq.tail & queue_size_mask;
/* In case of queue FULL */
- cnt = admin_queue->sq.tail - admin_queue->sq.head;
+ cnt = atomic_read(&admin_queue->outstanding_cmds);
if (cnt >= admin_queue->q_depth) {
- pr_debug("admin queue is FULL (tail %d head %d depth: %d)\n",
- admin_queue->sq.tail, admin_queue->sq.head,
- admin_queue->q_depth);
+ pr_debug("admin queue is full.\n");
admin_queue->stats.out_of_space++;
return ERR_PTR(-ENOSPC);
}
@@ -508,15 +508,20 @@ static int ena_com_comp_status_to_errno(u8 comp_status)
static int ena_com_wait_and_process_admin_cq_polling(struct ena_comp_ctx *comp_ctx,
struct ena_com_admin_queue *admin_queue)
{
- unsigned long flags;
- u32 start_time;
+ unsigned long flags, timeout;
int ret;
- start_time = ((u32)jiffies_to_usecs(jiffies));
+ timeout = jiffies + ADMIN_CMD_TIMEOUT_US;
+
+ while (1) {
+ spin_lock_irqsave(&admin_queue->q_lock, flags);
+ ena_com_handle_admin_completion(admin_queue);
+ spin_unlock_irqrestore(&admin_queue->q_lock, flags);
+
+ if (comp_ctx->status != ENA_CMD_SUBMITTED)
+ break;
- while (comp_ctx->status == ENA_CMD_SUBMITTED) {
- if ((((u32)jiffies_to_usecs(jiffies)) - start_time) >
- ADMIN_CMD_TIMEOUT_US) {
+ if (time_is_before_jiffies(timeout)) {
pr_err("Wait for completion (polling) timeout\n");
/* ENA didn't have any completion */
spin_lock_irqsave(&admin_queue->q_lock, flags);
@@ -528,10 +533,6 @@ static int ena_com_wait_and_process_admin_cq_polling(struct ena_comp_ctx *comp_c
goto err;
}
- spin_lock_irqsave(&admin_queue->q_lock, flags);
- ena_com_handle_admin_completion(admin_queue);
- spin_unlock_irqrestore(&admin_queue->q_lock, flags);
-
msleep(100);
}
@@ -1455,6 +1456,12 @@ void ena_com_admin_destroy(struct ena_com_dev *ena_dev)
void ena_com_set_admin_polling_mode(struct ena_com_dev *ena_dev, bool polling)
{
+ u32 mask_value = 0;
+
+ if (polling)
+ mask_value = ENA_REGS_ADMIN_INTR_MASK;
+
+ writel(mask_value, ena_dev->reg_bar + ENA_REGS_INTR_MASK_OFF);
ena_dev->admin_queue.polling = polling;
}
diff --git a/drivers/net/ethernet/amazon/ena/ena_ethtool.c b/drivers/net/ethernet/amazon/ena/ena_ethtool.c
index 67b2338f8fb3..3ee55e2fd694 100644
--- a/drivers/net/ethernet/amazon/ena/ena_ethtool.c
+++ b/drivers/net/ethernet/amazon/ena/ena_ethtool.c
@@ -80,7 +80,6 @@ static const struct ena_stats ena_stats_tx_strings[] = {
ENA_STAT_TX_ENTRY(tx_poll),
ENA_STAT_TX_ENTRY(doorbells),
ENA_STAT_TX_ENTRY(prepare_ctx_err),
- ENA_STAT_TX_ENTRY(missing_tx_comp),
ENA_STAT_TX_ENTRY(bad_req_id),
};
@@ -94,6 +93,7 @@ static const struct ena_stats ena_stats_rx_strings[] = {
ENA_STAT_RX_ENTRY(dma_mapping_err),
ENA_STAT_RX_ENTRY(bad_desc_num),
ENA_STAT_RX_ENTRY(rx_copybreak_pkt),
+ ENA_STAT_RX_ENTRY(empty_rx_ring),
};
static const struct ena_stats ena_stats_ena_com_strings[] = {
diff --git a/drivers/net/ethernet/amazon/ena/ena_netdev.c b/drivers/net/ethernet/amazon/ena/ena_netdev.c
index 7c1214d78855..4f16ed38bcf3 100644
--- a/drivers/net/ethernet/amazon/ena/ena_netdev.c
+++ b/drivers/net/ethernet/amazon/ena/ena_netdev.c
@@ -190,6 +190,7 @@ static void ena_init_io_rings(struct ena_adapter *adapter)
rxr->sgl_size = adapter->max_rx_sgl_size;
rxr->smoothed_interval =
ena_com_get_nonadaptive_moderation_interval_rx(ena_dev);
+ rxr->empty_rx_queue = 0;
}
}
@@ -1078,6 +1079,26 @@ inline void ena_adjust_intr_moderation(struct ena_ring *rx_ring,
rx_ring->per_napi_bytes = 0;
}
+static inline void ena_unmask_interrupt(struct ena_ring *tx_ring,
+ struct ena_ring *rx_ring)
+{
+ struct ena_eth_io_intr_reg intr_reg;
+
+ /* Update intr register: rx intr delay,
+ * tx intr delay and interrupt unmask
+ */
+ ena_com_update_intr_reg(&intr_reg,
+ rx_ring->smoothed_interval,
+ tx_ring->smoothed_interval,
+ true);
+
+ /* It is a shared MSI-X.
+ * Tx and Rx CQ have pointer to it.
+ * So we use one of them to reach the intr reg
+ */
+ ena_com_unmask_intr(rx_ring->ena_com_io_cq, &intr_reg);
+}
+
static inline void ena_update_ring_numa_node(struct ena_ring *tx_ring,
struct ena_ring *rx_ring)
{
@@ -1108,7 +1129,6 @@ static int ena_io_poll(struct napi_struct *napi, int budget)
{
struct ena_napi *ena_napi = container_of(napi, struct ena_napi, napi);
struct ena_ring *tx_ring, *rx_ring;
- struct ena_eth_io_intr_reg intr_reg;
u32 tx_work_done;
u32 rx_work_done;
@@ -1149,22 +1169,9 @@ static int ena_io_poll(struct napi_struct *napi, int budget)
if (ena_com_get_adaptive_moderation_enabled(rx_ring->ena_dev))
ena_adjust_intr_moderation(rx_ring, tx_ring);
- /* Update intr register: rx intr delay,
- * tx intr delay and interrupt unmask
- */
- ena_com_update_intr_reg(&intr_reg,
- rx_ring->smoothed_interval,
- tx_ring->smoothed_interval,
- true);
-
- /* It is a shared MSI-X.
- * Tx and Rx CQ have pointer to it.
- * So we use one of them to reach the intr reg
- */
- ena_com_unmask_intr(rx_ring->ena_com_io_cq, &intr_reg);
+ ena_unmask_interrupt(tx_ring, rx_ring);
}
-
ena_update_ring_numa_node(tx_ring, rx_ring);
ret = rx_work_done;
@@ -1485,6 +1492,11 @@ static int ena_up_complete(struct ena_adapter *adapter)
ena_napi_enable_all(adapter);
+ /* Enable completion queues interrupt */
+ for (i = 0; i < adapter->num_queues; i++)
+ ena_unmask_interrupt(&adapter->tx_ring[i],
+ &adapter->rx_ring[i]);
+
/* schedule napi in case we had pending packets
* from the last time we disable napi
*/
@@ -1532,6 +1544,7 @@ static int ena_create_io_tx_queue(struct ena_adapter *adapter, int qid)
"Failed to get TX queue handlers. TX queue num %d rc: %d\n",
qid, rc);
ena_com_destroy_io_queue(ena_dev, ena_qid);
+ return rc;
}
ena_com_update_numa_node(tx_ring->ena_com_io_cq, ctx.numa_node);
@@ -1596,6 +1609,7 @@ static int ena_create_io_rx_queue(struct ena_adapter *adapter, int qid)
"Failed to get RX queue handlers. RX queue num %d rc: %d\n",
qid, rc);
ena_com_destroy_io_queue(ena_dev, ena_qid);
+ return rc;
}
ena_com_update_numa_node(rx_ring->ena_com_io_cq, ctx.numa_node);
@@ -1981,6 +1995,7 @@ static netdev_tx_t ena_start_xmit(struct sk_buff *skb, struct net_device *dev)
tx_info->tx_descs = nb_hw_desc;
tx_info->last_jiffies = jiffies;
+ tx_info->print_once = 0;
tx_ring->next_to_use = ENA_TX_RING_IDX_NEXT(next_to_use,
tx_ring->ring_size);
@@ -2550,13 +2565,44 @@ err:
"Reset attempt failed. Can not reset the device\n");
}
-static void check_for_missing_tx_completions(struct ena_adapter *adapter)
+static int check_missing_comp_in_queue(struct ena_adapter *adapter,
+ struct ena_ring *tx_ring)
{
struct ena_tx_buffer *tx_buf;
unsigned long last_jiffies;
+ u32 missed_tx = 0;
+ int i;
+
+ for (i = 0; i < tx_ring->ring_size; i++) {
+ tx_buf = &tx_ring->tx_buffer_info[i];
+ last_jiffies = tx_buf->last_jiffies;
+ if (unlikely(last_jiffies &&
+ time_is_before_jiffies(last_jiffies + TX_TIMEOUT))) {
+ if (!tx_buf->print_once)
+ netif_notice(adapter, tx_err, adapter->netdev,
+ "Found a Tx that wasn't completed on time, qid %d, index %d.\n",
+ tx_ring->qid, i);
+
+ tx_buf->print_once = 1;
+ missed_tx++;
+
+ if (unlikely(missed_tx > MAX_NUM_OF_TIMEOUTED_PACKETS)) {
+ netif_err(adapter, tx_err, adapter->netdev,
+ "The number of lost tx completions is above the threshold (%d > %d). Reset the device\n",
+ missed_tx, MAX_NUM_OF_TIMEOUTED_PACKETS);
+ set_bit(ENA_FLAG_TRIGGER_RESET, &adapter->flags);
+ return -EIO;
+ }
+ }
+ }
+
+ return 0;
+}
+
+static void check_for_missing_tx_completions(struct ena_adapter *adapter)
+{
struct ena_ring *tx_ring;
- int i, j, budget;
- u32 missed_tx;
+ int i, budget, rc;
/* Make sure the driver doesn't turn the device in other process */
smp_rmb();
@@ -2572,31 +2618,9 @@ static void check_for_missing_tx_completions(struct ena_adapter *adapter)
for (i = adapter->last_monitored_tx_qid; i < adapter->num_queues; i++) {
tx_ring = &adapter->tx_ring[i];
- for (j = 0; j < tx_ring->ring_size; j++) {
- tx_buf = &tx_ring->tx_buffer_info[j];
- last_jiffies = tx_buf->last_jiffies;
- if (unlikely(last_jiffies && time_is_before_jiffies(last_jiffies + TX_TIMEOUT))) {
- netif_notice(adapter, tx_err, adapter->netdev,
- "Found a Tx that wasn't completed on time, qid %d, index %d.\n",
- tx_ring->qid, j);
-
- u64_stats_update_begin(&tx_ring->syncp);
- missed_tx = tx_ring->tx_stats.missing_tx_comp++;
- u64_stats_update_end(&tx_ring->syncp);
-
- /* Clear last jiffies so the lost buffer won't
- * be counted twice.
- */
- tx_buf->last_jiffies = 0;
-
- if (unlikely(missed_tx > MAX_NUM_OF_TIMEOUTED_PACKETS)) {
- netif_err(adapter, tx_err, adapter->netdev,
- "The number of lost tx completion is above the threshold (%d > %d). Reset the device\n",
- missed_tx, MAX_NUM_OF_TIMEOUTED_PACKETS);
- set_bit(ENA_FLAG_TRIGGER_RESET, &adapter->flags);
- }
- }
- }
+ rc = check_missing_comp_in_queue(adapter, tx_ring);
+ if (unlikely(rc))
+ return;
budget--;
if (!budget)
@@ -2606,6 +2630,58 @@ static void check_for_missing_tx_completions(struct ena_adapter *adapter)
adapter->last_monitored_tx_qid = i % adapter->num_queues;
}
+/* trigger napi schedule after 2 consecutive detections */
+#define EMPTY_RX_REFILL 2
+/* For the rare case where the device runs out of Rx descriptors and the
+ * napi handler failed to refill new Rx descriptors (due to a lack of memory
+ * for example).
+ * This case will lead to a deadlock:
+ * The device won't send interrupts since all the new Rx packets will be dropped
+ * The napi handler won't allocate new Rx descriptors so the device will be
+ * able to send new packets.
+ *
+ * This scenario can happen when the kernel's vm.min_free_kbytes is too small.
+ * It is recommended to have at least 512MB, with a minimum of 128MB for
+ * constrained environment).
+ *
+ * When such a situation is detected - Reschedule napi
+ */
+static void check_for_empty_rx_ring(struct ena_adapter *adapter)
+{
+ struct ena_ring *rx_ring;
+ int i, refill_required;
+
+ if (!test_bit(ENA_FLAG_DEV_UP, &adapter->flags))
+ return;
+
+ if (test_bit(ENA_FLAG_TRIGGER_RESET, &adapter->flags))
+ return;
+
+ for (i = 0; i < adapter->num_queues; i++) {
+ rx_ring = &adapter->rx_ring[i];
+
+ refill_required =
+ ena_com_sq_empty_space(rx_ring->ena_com_io_sq);
+ if (unlikely(refill_required == (rx_ring->ring_size - 1))) {
+ rx_ring->empty_rx_queue++;
+
+ if (rx_ring->empty_rx_queue >= EMPTY_RX_REFILL) {
+ u64_stats_update_begin(&rx_ring->syncp);
+ rx_ring->rx_stats.empty_rx_ring++;
+ u64_stats_update_end(&rx_ring->syncp);
+
+ netif_err(adapter, drv, adapter->netdev,
+ "trigger refill for ring %d\n", i);
+
+ napi_schedule(rx_ring->napi);
+ rx_ring->empty_rx_queue = 0;
+ }
+ } else {
+ rx_ring->empty_rx_queue = 0;
+ }
+ }
+}
+
/* Check for keep alive expiration */
static void check_for_missing_keep_alive(struct ena_adapter *adapter)
{
@@ -2660,6 +2736,8 @@ static void ena_timer_service(unsigned long data)
check_for_missing_tx_completions(adapter);
+ check_for_empty_rx_ring(adapter);
+
if (debug_area)
ena_dump_stats_to_buf(adapter, debug_area);
@@ -2840,6 +2918,11 @@ static void ena_release_bars(struct ena_com_dev *ena_dev, struct pci_dev *pdev)
{
int release_bars;
+ if (ena_dev->mem_bar)
+ devm_iounmap(&pdev->dev, ena_dev->mem_bar);
+
+ devm_iounmap(&pdev->dev, ena_dev->reg_bar);
+
release_bars = pci_select_bars(pdev, IORESOURCE_MEM) & ENA_BAR_MASK;
pci_release_selected_regions(pdev, release_bars);
}
@@ -2927,8 +3010,9 @@ static int ena_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
goto err_free_ena_dev;
}
- ena_dev->reg_bar = ioremap(pci_resource_start(pdev, ENA_REG_BAR),
- pci_resource_len(pdev, ENA_REG_BAR));
+ ena_dev->reg_bar = devm_ioremap(&pdev->dev,
+ pci_resource_start(pdev, ENA_REG_BAR),
+ pci_resource_len(pdev, ENA_REG_BAR));
if (!ena_dev->reg_bar) {
dev_err(&pdev->dev, "failed to remap regs bar\n");
rc = -EFAULT;
@@ -2948,8 +3032,9 @@ static int ena_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
ena_set_push_mode(pdev, ena_dev, &get_feat_ctx);
if (ena_dev->tx_mem_queue_type == ENA_ADMIN_PLACEMENT_POLICY_DEV) {
- ena_dev->mem_bar = ioremap_wc(pci_resource_start(pdev, ENA_MEM_BAR),
- pci_resource_len(pdev, ENA_MEM_BAR));
+ ena_dev->mem_bar = devm_ioremap_wc(&pdev->dev,
+ pci_resource_start(pdev, ENA_MEM_BAR),
+ pci_resource_len(pdev, ENA_MEM_BAR));
if (!ena_dev->mem_bar) {
rc = -EFAULT;
goto err_device_destroy;
diff --git a/drivers/net/ethernet/amazon/ena/ena_netdev.h b/drivers/net/ethernet/amazon/ena/ena_netdev.h
index 0e22bce6239d..a4d3d5e21068 100644
--- a/drivers/net/ethernet/amazon/ena/ena_netdev.h
+++ b/drivers/net/ethernet/amazon/ena/ena_netdev.h
@@ -45,7 +45,7 @@
#define DRV_MODULE_VER_MAJOR 1
#define DRV_MODULE_VER_MINOR 1
-#define DRV_MODULE_VER_SUBMINOR 2
+#define DRV_MODULE_VER_SUBMINOR 7
#define DRV_MODULE_NAME "ena"
#ifndef DRV_MODULE_VERSION
@@ -146,7 +146,18 @@ struct ena_tx_buffer {
u32 tx_descs;
/* num of buffers used by this skb */
u32 num_of_bufs;
- /* Save the last jiffies to detect missing tx packets */
+
+ /* Used for detect missing tx packets to limit the number of prints */
+ u32 print_once;
+ /* Save the last jiffies to detect missing tx packets
+ *
+ * sets to non zero value on ena_start_xmit and set to zero on
+ * napi and timer_Service_routine.
+ *
+ * while this value is not protected by lock,
+ * a given packet is not expected to be handled by ena_start_xmit
+ * and by napi/timer_service at the same time.
+ */
unsigned long last_jiffies;
struct ena_com_buf bufs[ENA_PKT_MAX_BUFS];
} ____cacheline_aligned;
@@ -170,7 +181,6 @@ struct ena_stats_tx {
u64 napi_comp;
u64 tx_poll;
u64 doorbells;
- u64 missing_tx_comp;
u64 bad_req_id;
};
@@ -184,6 +194,7 @@ struct ena_stats_rx {
u64 dma_mapping_err;
u64 bad_desc_num;
u64 rx_copybreak_pkt;
+ u64 empty_rx_ring;
};
struct ena_ring {
@@ -231,6 +242,7 @@ struct ena_ring {
struct ena_stats_tx tx_stats;
struct ena_stats_rx rx_stats;
};
+ int empty_rx_queue;
} ____cacheline_aligned;
struct ena_stats_dev {
diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-desc.c b/drivers/net/ethernet/amd/xgbe/xgbe-desc.c
index b3bc87fe3764..0a98c369df20 100644
--- a/drivers/net/ethernet/amd/xgbe/xgbe-desc.c
+++ b/drivers/net/ethernet/amd/xgbe/xgbe-desc.c
@@ -324,7 +324,7 @@ static int xgbe_map_rx_buffer(struct xgbe_prv_data *pdata,
struct xgbe_ring *ring,
struct xgbe_ring_data *rdata)
{
- int order, ret;
+ int ret;
if (!ring->rx_hdr_pa.pages) {
ret = xgbe_alloc_pages(pdata, &ring->rx_hdr_pa, GFP_ATOMIC, 0);
@@ -333,9 +333,8 @@ static int xgbe_map_rx_buffer(struct xgbe_prv_data *pdata,
}
if (!ring->rx_buf_pa.pages) {
- order = max_t(int, PAGE_ALLOC_COSTLY_ORDER - 1, 0);
ret = xgbe_alloc_pages(pdata, &ring->rx_buf_pa, GFP_ATOMIC,
- order);
+ PAGE_ALLOC_COSTLY_ORDER);
if (ret)
return ret;
}
diff --git a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_utils.h b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_utils.h
index b8e3d88f0879..a66aee51ab5b 100644
--- a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_utils.h
+++ b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_utils.h
@@ -193,9 +193,6 @@ int hw_atl_utils_hw_get_regs(struct aq_hw_s *self,
struct aq_hw_caps_s *aq_hw_caps,
u32 *regs_buff);
-int hw_atl_utils_hw_get_settings(struct aq_hw_s *self,
- struct ethtool_cmd *cmd);
-
int hw_atl_utils_hw_set_power(struct aq_hw_s *self,
unsigned int power_state);
diff --git a/drivers/net/ethernet/atheros/atlx/atl2.c b/drivers/net/ethernet/atheros/atlx/atl2.c
index 63f2deec2a52..77a1c03255de 100644
--- a/drivers/net/ethernet/atheros/atlx/atl2.c
+++ b/drivers/net/ethernet/atheros/atlx/atl2.c
@@ -1353,6 +1353,7 @@ static int atl2_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
if (pci_set_dma_mask(pdev, DMA_BIT_MASK(32)) &&
pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32))) {
printk(KERN_ERR "atl2: No usable DMA configuration, aborting\n");
+ err = -EIO;
goto err_dma;
}
@@ -1366,10 +1367,11 @@ static int atl2_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
* pcibios_set_master to do the needed arch specific settings */
pci_set_master(pdev);
- err = -ENOMEM;
netdev = alloc_etherdev(sizeof(struct atl2_adapter));
- if (!netdev)
+ if (!netdev) {
+ err = -ENOMEM;
goto err_alloc_etherdev;
+ }
SET_NETDEV_DEV(netdev, &pdev->dev);
@@ -1408,8 +1410,6 @@ static int atl2_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
if (err)
goto err_sw_init;
- err = -EIO;
-
netdev->hw_features = NETIF_F_HW_VLAN_CTAG_RX;
netdev->features |= (NETIF_F_HW_VLAN_CTAG_TX | NETIF_F_HW_VLAN_CTAG_RX);
diff --git a/drivers/net/ethernet/broadcom/bcmsysport.c b/drivers/net/ethernet/broadcom/bcmsysport.c
index 099b374c1b17..5274501428e4 100644
--- a/drivers/net/ethernet/broadcom/bcmsysport.c
+++ b/drivers/net/ethernet/broadcom/bcmsysport.c
@@ -2026,9 +2026,12 @@ static int bcm_sysport_probe(struct platform_device *pdev)
priv->num_rx_desc_words = params->num_rx_desc_words;
priv->irq0 = platform_get_irq(pdev, 0);
- if (!priv->is_lite)
+ if (!priv->is_lite) {
priv->irq1 = platform_get_irq(pdev, 1);
- priv->wol_irq = platform_get_irq(pdev, 2);
+ priv->wol_irq = platform_get_irq(pdev, 2);
+ } else {
+ priv->wol_irq = platform_get_irq(pdev, 1);
+ }
if (priv->irq0 <= 0 || (priv->irq1 <= 0 && !priv->is_lite)) {
dev_err(&pdev->dev, "invalid interrupts\n");
ret = -EINVAL;
diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c
index eccb3d1b6abb..f619c4cac51f 100644
--- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c
+++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c
@@ -1926,7 +1926,7 @@ u16 bnx2x_select_queue(struct net_device *dev, struct sk_buff *skb,
}
/* select a non-FCoE queue */
- return fallback(dev, skb) % BNX2X_NUM_ETH_QUEUES(bp);
+ return fallback(dev, skb) % (BNX2X_NUM_ETH_QUEUES(bp) * bp->max_cos);
}
void bnx2x_set_num_queues(struct bnx2x *bp)
@@ -3883,15 +3883,26 @@ netdev_tx_t bnx2x_start_xmit(struct sk_buff *skb, struct net_device *dev)
/* when transmitting in a vf, start bd must hold the ethertype
* for fw to enforce it
*/
+ u16 vlan_tci = 0;
#ifndef BNX2X_STOP_ON_ERROR
- if (IS_VF(bp))
+ if (IS_VF(bp)) {
#endif
- tx_start_bd->vlan_or_ethertype =
- cpu_to_le16(ntohs(eth->h_proto));
+ /* Still need to consider inband vlan for enforced */
+ if (__vlan_get_tag(skb, &vlan_tci)) {
+ tx_start_bd->vlan_or_ethertype =
+ cpu_to_le16(ntohs(eth->h_proto));
+ } else {
+ tx_start_bd->bd_flags.as_bitfield |=
+ (X_ETH_INBAND_VLAN <<
+ ETH_TX_BD_FLAGS_VLAN_MODE_SHIFT);
+ tx_start_bd->vlan_or_ethertype =
+ cpu_to_le16(vlan_tci);
+ }
#ifndef BNX2X_STOP_ON_ERROR
- else
+ } else {
/* used by FW for packet accounting */
tx_start_bd->vlan_or_ethertype = cpu_to_le16(pkt_prod);
+ }
#endif
}
diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c
index a851f95c307a..349a46593abf 100644
--- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c
+++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c
@@ -12729,7 +12729,7 @@ static int bnx2x_set_mc_list(struct bnx2x *bp)
} else {
/* If no mc addresses are required, flush the configuration */
rc = bnx2x_config_mcast(bp, &rparam, BNX2X_MCAST_CMD_DEL);
- if (rc)
+ if (rc < 0)
BNX2X_ERR("Failed to clear multicast configuration %d\n",
rc);
}
diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.c
index bdfd53b46bc5..9ca994d0bab6 100644
--- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.c
+++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.c
@@ -901,6 +901,8 @@ static void bnx2x_vf_flr(struct bnx2x *bp, struct bnx2x_virtf *vf)
/* release VF resources */
bnx2x_vf_free_resc(bp, vf);
+ vf->malicious = false;
+
/* re-open the mailbox */
bnx2x_vf_enable_mbx(bp, vf->abs_vfid);
return;
@@ -1822,9 +1824,11 @@ get_vf:
vf->abs_vfid, qidx);
bnx2x_vf_handle_rss_update_eqe(bp, vf);
case EVENT_RING_OPCODE_VF_FLR:
- case EVENT_RING_OPCODE_MALICIOUS_VF:
/* Do nothing for now */
return 0;
+ case EVENT_RING_OPCODE_MALICIOUS_VF:
+ vf->malicious = true;
+ return 0;
}
return 0;
@@ -1905,6 +1909,13 @@ void bnx2x_iov_adjust_stats_req(struct bnx2x *bp)
continue;
}
+ if (vf->malicious) {
+ DP_AND((BNX2X_MSG_IOV | BNX2X_MSG_STATS),
+ "vf %d malicious so no stats for it\n",
+ vf->abs_vfid);
+ continue;
+ }
+
DP_AND((BNX2X_MSG_IOV | BNX2X_MSG_STATS),
"add addresses for vf %d\n", vf->abs_vfid);
for_each_vfq(vf, j) {
@@ -3042,7 +3053,7 @@ void bnx2x_vf_pci_dealloc(struct bnx2x *bp)
{
BNX2X_PCI_FREE(bp->vf2pf_mbox, bp->vf2pf_mbox_mapping,
sizeof(struct bnx2x_vf_mbx_msg));
- BNX2X_PCI_FREE(bp->vf2pf_mbox, bp->pf2vf_bulletin_mapping,
+ BNX2X_PCI_FREE(bp->pf2vf_bulletin, bp->pf2vf_bulletin_mapping,
sizeof(union pf_vf_bulletin));
}
diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.h b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.h
index 888d0b6632e8..53466f6cebab 100644
--- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.h
+++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.h
@@ -141,6 +141,7 @@ struct bnx2x_virtf {
#define VF_RESET 3 /* VF FLR'd, pending cleanup */
bool flr_clnup_stage; /* true during flr cleanup */
+ bool malicious; /* true if FW indicated so, until FLR */
/* dma */
dma_addr_t fw_stat_map;
diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt.c b/drivers/net/ethernet/broadcom/bnxt/bnxt.c
index 03f55daecb20..74e8e215524d 100644
--- a/drivers/net/ethernet/broadcom/bnxt/bnxt.c
+++ b/drivers/net/ethernet/broadcom/bnxt/bnxt.c
@@ -1301,10 +1301,11 @@ static inline struct sk_buff *bnxt_tpa_end(struct bnxt *bp,
cp_cons = NEXT_CMP(cp_cons);
}
- if (unlikely(agg_bufs > MAX_SKB_FRAGS)) {
+ if (unlikely(agg_bufs > MAX_SKB_FRAGS || TPA_END_ERRORS(tpa_end1))) {
bnxt_abort_tpa(bp, bnapi, cp_cons, agg_bufs);
- netdev_warn(bp->dev, "TPA frags %d exceeded MAX_SKB_FRAGS %d\n",
- agg_bufs, (int)MAX_SKB_FRAGS);
+ if (agg_bufs > MAX_SKB_FRAGS)
+ netdev_warn(bp->dev, "TPA frags %d exceeded MAX_SKB_FRAGS %d\n",
+ agg_bufs, (int)MAX_SKB_FRAGS);
return NULL;
}
@@ -1562,6 +1563,45 @@ next_rx_no_prod:
return rc;
}
+/* In netpoll mode, if we are using a combined completion ring, we need to
+ * discard the rx packets and recycle the buffers.
+ */
+static int bnxt_force_rx_discard(struct bnxt *bp, struct bnxt_napi *bnapi,
+ u32 *raw_cons, u8 *event)
+{
+ struct bnxt_cp_ring_info *cpr = &bnapi->cp_ring;
+ u32 tmp_raw_cons = *raw_cons;
+ struct rx_cmp_ext *rxcmp1;
+ struct rx_cmp *rxcmp;
+ u16 cp_cons;
+ u8 cmp_type;
+
+ cp_cons = RING_CMP(tmp_raw_cons);
+ rxcmp = (struct rx_cmp *)
+ &cpr->cp_desc_ring[CP_RING(cp_cons)][CP_IDX(cp_cons)];
+
+ tmp_raw_cons = NEXT_RAW_CMP(tmp_raw_cons);
+ cp_cons = RING_CMP(tmp_raw_cons);
+ rxcmp1 = (struct rx_cmp_ext *)
+ &cpr->cp_desc_ring[CP_RING(cp_cons)][CP_IDX(cp_cons)];
+
+ if (!RX_CMP_VALID(rxcmp1, tmp_raw_cons))
+ return -EBUSY;
+
+ cmp_type = RX_CMP_TYPE(rxcmp);
+ if (cmp_type == CMP_TYPE_RX_L2_CMP) {
+ rxcmp1->rx_cmp_cfa_code_errors_v2 |=
+ cpu_to_le32(RX_CMPL_ERRORS_CRC_ERROR);
+ } else if (cmp_type == CMP_TYPE_RX_L2_TPA_END_CMP) {
+ struct rx_tpa_end_cmp_ext *tpa_end1;
+
+ tpa_end1 = (struct rx_tpa_end_cmp_ext *)rxcmp1;
+ tpa_end1->rx_tpa_end_cmp_errors_v2 |=
+ cpu_to_le32(RX_TPA_END_CMP_ERRORS);
+ }
+ return bnxt_rx_pkt(bp, bnapi, raw_cons, event);
+}
+
#define BNXT_GET_EVENT_PORT(data) \
((data) & \
ASYNC_EVENT_CMPL_PORT_CONN_NOT_ALLOWED_EVENT_DATA1_PORT_ID_MASK)
@@ -1744,7 +1784,11 @@ static int bnxt_poll_work(struct bnxt *bp, struct bnxt_napi *bnapi, int budget)
if (unlikely(tx_pkts > bp->tx_wake_thresh))
rx_pkts = budget;
} else if ((TX_CMP_TYPE(txcmp) & 0x30) == 0x10) {
- rc = bnxt_rx_pkt(bp, bnapi, &raw_cons, &event);
+ if (likely(budget))
+ rc = bnxt_rx_pkt(bp, bnapi, &raw_cons, &event);
+ else
+ rc = bnxt_force_rx_discard(bp, bnapi, &raw_cons,
+ &event);
if (likely(rc >= 0))
rx_pkts += rc;
else if (rc == -EBUSY) /* partial completion */
@@ -6663,12 +6707,11 @@ static void bnxt_poll_controller(struct net_device *dev)
struct bnxt *bp = netdev_priv(dev);
int i;
- for (i = 0; i < bp->cp_nr_rings; i++) {
- struct bnxt_irq *irq = &bp->irq_tbl[i];
+ /* Only process tx rings/combined rings in netpoll mode. */
+ for (i = 0; i < bp->tx_nr_rings; i++) {
+ struct bnxt_tx_ring_info *txr = &bp->tx_ring[i];
- disable_irq(irq->vector);
- irq->handler(irq->vector, bp->bnapi[i]);
- enable_irq(irq->vector);
+ napi_schedule(&txr->bnapi->napi);
}
}
#endif
diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt.h b/drivers/net/ethernet/broadcom/bnxt/bnxt.h
index 3ef42dbc6327..d46a85041083 100644
--- a/drivers/net/ethernet/broadcom/bnxt/bnxt.h
+++ b/drivers/net/ethernet/broadcom/bnxt/bnxt.h
@@ -374,12 +374,16 @@ struct rx_tpa_end_cmp_ext {
__le32 rx_tpa_end_cmp_errors_v2;
#define RX_TPA_END_CMP_V2 (0x1 << 0)
- #define RX_TPA_END_CMP_ERRORS (0x7fff << 1)
+ #define RX_TPA_END_CMP_ERRORS (0x3 << 1)
#define RX_TPA_END_CMPL_ERRORS_SHIFT 1
u32 rx_tpa_end_cmp_start_opaque;
};
+#define TPA_END_ERRORS(rx_tpa_end_ext) \
+ ((rx_tpa_end_ext)->rx_tpa_end_cmp_errors_v2 & \
+ cpu_to_le32(RX_TPA_END_CMP_ERRORS))
+
#define DB_IDX_MASK 0xffffff
#define DB_IDX_VALID (0x1 << 26)
#define DB_IRQ_DIS (0x1 << 27)
diff --git a/drivers/net/ethernet/cavium/liquidio/octeon_main.h b/drivers/net/ethernet/cavium/liquidio/octeon_main.h
index bed9ef17bc26..7ccffbb0019e 100644
--- a/drivers/net/ethernet/cavium/liquidio/octeon_main.h
+++ b/drivers/net/ethernet/cavium/liquidio/octeon_main.h
@@ -144,7 +144,7 @@ static inline int
sleep_cond(wait_queue_head_t *wait_queue, int *condition)
{
int errno = 0;
- wait_queue_t we;
+ wait_queue_entry_t we;
init_waitqueue_entry(&we, current);
add_wait_queue(wait_queue, &we);
@@ -171,7 +171,7 @@ sleep_timeout_cond(wait_queue_head_t *wait_queue,
int *condition,
int timeout)
{
- wait_queue_t we;
+ wait_queue_entry_t we;
init_waitqueue_entry(&we, current);
add_wait_queue(wait_queue, &we);
diff --git a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c
index 38a5c6764bb5..53309f659951 100644
--- a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c
+++ b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c
@@ -2171,9 +2171,10 @@ static int cxgb_up(struct adapter *adap)
{
int err;
+ mutex_lock(&uld_mutex);
err = setup_sge_queues(adap);
if (err)
- goto out;
+ goto rel_lock;
err = setup_rss(adap);
if (err)
goto freeq;
@@ -2196,23 +2197,28 @@ static int cxgb_up(struct adapter *adap)
if (err)
goto irq_err;
}
+
enable_rx(adap);
t4_sge_start(adap);
t4_intr_enable(adap);
adap->flags |= FULL_INIT_DONE;
+ mutex_unlock(&uld_mutex);
+
notify_ulds(adap, CXGB4_STATE_UP);
#if IS_ENABLED(CONFIG_IPV6)
update_clip(adap);
#endif
/* Initialize hash mac addr list*/
INIT_LIST_HEAD(&adap->mac_hlist);
- out:
return err;
+
irq_err:
dev_err(adap->pdev_dev, "request_irq failed, err %d\n", err);
freeq:
t4_free_sge_resources(adap);
- goto out;
+ rel_lock:
+ mutex_unlock(&uld_mutex);
+ return err;
}
static void cxgb_down(struct adapter *adapter)
@@ -2771,6 +2777,9 @@ void t4_fatal_err(struct adapter *adap)
{
int port;
+ if (pci_channel_offline(adap->pdev))
+ return;
+
/* Disable the SGE since ULDs are going to free resources that
* could be exposed to the adapter. RDMA MWs for example...
*/
@@ -3882,9 +3891,10 @@ static pci_ers_result_t eeh_err_detected(struct pci_dev *pdev,
spin_lock(&adap->stats_lock);
for_each_port(adap, i) {
struct net_device *dev = adap->port[i];
-
- netif_device_detach(dev);
- netif_carrier_off(dev);
+ if (dev) {
+ netif_device_detach(dev);
+ netif_carrier_off(dev);
+ }
}
spin_unlock(&adap->stats_lock);
disable_interrupts(adap);
@@ -3963,12 +3973,13 @@ static void eeh_resume(struct pci_dev *pdev)
rtnl_lock();
for_each_port(adap, i) {
struct net_device *dev = adap->port[i];
-
- if (netif_running(dev)) {
- link_start(dev);
- cxgb_set_rxmode(dev);
+ if (dev) {
+ if (netif_running(dev)) {
+ link_start(dev);
+ cxgb_set_rxmode(dev);
+ }
+ netif_device_attach(dev);
}
- netif_device_attach(dev);
}
rtnl_unlock();
}
@@ -4516,7 +4527,7 @@ static void dummy_setup(struct net_device *dev)
/* Initialize the device structure. */
dev->netdev_ops = &cxgb4_mgmt_netdev_ops;
dev->ethtool_ops = &cxgb4_mgmt_ethtool_ops;
- dev->destructor = free_netdev;
+ dev->needs_free_netdev = true;
}
static int config_mgmt_dev(struct pci_dev *pdev)
diff --git a/drivers/net/ethernet/chelsio/cxgb4/t4_hw.c b/drivers/net/ethernet/chelsio/cxgb4/t4_hw.c
index aded42b96f6d..3a34aa629f7d 100644
--- a/drivers/net/ethernet/chelsio/cxgb4/t4_hw.c
+++ b/drivers/net/ethernet/chelsio/cxgb4/t4_hw.c
@@ -4557,8 +4557,13 @@ void t4_intr_enable(struct adapter *adapter)
*/
void t4_intr_disable(struct adapter *adapter)
{
- u32 whoami = t4_read_reg(adapter, PL_WHOAMI_A);
- u32 pf = CHELSIO_CHIP_VERSION(adapter->params.chip) <= CHELSIO_T5 ?
+ u32 whoami, pf;
+
+ if (pci_channel_offline(adapter->pdev))
+ return;
+
+ whoami = t4_read_reg(adapter, PL_WHOAMI_A);
+ pf = CHELSIO_CHIP_VERSION(adapter->params.chip) <= CHELSIO_T5 ?
SOURCEPF_G(whoami) : T6_SOURCEPF_G(whoami);
t4_write_reg(adapter, MYPF_REG(PL_PF_INT_ENABLE_A), 0);
diff --git a/drivers/net/ethernet/chelsio/cxgb4/t4fw_version.h b/drivers/net/ethernet/chelsio/cxgb4/t4fw_version.h
index 3549d3876278..f2d623a7aee0 100644
--- a/drivers/net/ethernet/chelsio/cxgb4/t4fw_version.h
+++ b/drivers/net/ethernet/chelsio/cxgb4/t4fw_version.h
@@ -37,7 +37,7 @@
#define T4FW_VERSION_MAJOR 0x01
#define T4FW_VERSION_MINOR 0x10
-#define T4FW_VERSION_MICRO 0x2B
+#define T4FW_VERSION_MICRO 0x2D
#define T4FW_VERSION_BUILD 0x00
#define T4FW_MIN_VERSION_MAJOR 0x01
@@ -46,7 +46,7 @@
#define T5FW_VERSION_MAJOR 0x01
#define T5FW_VERSION_MINOR 0x10
-#define T5FW_VERSION_MICRO 0x2B
+#define T5FW_VERSION_MICRO 0x2D
#define T5FW_VERSION_BUILD 0x00
#define T5FW_MIN_VERSION_MAJOR 0x00
@@ -55,7 +55,7 @@
#define T6FW_VERSION_MAJOR 0x01
#define T6FW_VERSION_MINOR 0x10
-#define T6FW_VERSION_MICRO 0x2B
+#define T6FW_VERSION_MICRO 0x2D
#define T6FW_VERSION_BUILD 0x00
#define T6FW_MIN_VERSION_MAJOR 0x00
diff --git a/drivers/net/ethernet/emulex/benet/be_main.c b/drivers/net/ethernet/emulex/benet/be_main.c
index f3a09ab55900..4eee18ce9be4 100644
--- a/drivers/net/ethernet/emulex/benet/be_main.c
+++ b/drivers/net/ethernet/emulex/benet/be_main.c
@@ -5078,9 +5078,11 @@ static netdev_features_t be_features_check(struct sk_buff *skb,
struct be_adapter *adapter = netdev_priv(dev);
u8 l4_hdr = 0;
- /* The code below restricts offload features for some tunneled packets.
+ /* The code below restricts offload features for some tunneled and
+ * Q-in-Q packets.
* Offload features for normal (non tunnel) packets are unchanged.
*/
+ features = vlan_features_check(skb, features);
if (!skb->encapsulation ||
!(adapter->flags & BE_FLAGS_VXLAN_OFFLOADS))
return features;
diff --git a/drivers/net/ethernet/ethoc.c b/drivers/net/ethernet/ethoc.c
index e863ba74d005..8bb0db990c8f 100644
--- a/drivers/net/ethernet/ethoc.c
+++ b/drivers/net/ethernet/ethoc.c
@@ -739,6 +739,8 @@ static int ethoc_open(struct net_device *dev)
if (ret)
return ret;
+ napi_enable(&priv->napi);
+
ethoc_init_ring(priv, dev->mem_start);
ethoc_reset(priv);
@@ -754,7 +756,6 @@ static int ethoc_open(struct net_device *dev)
priv->old_duplex = -1;
phy_start(dev->phydev);
- napi_enable(&priv->napi);
if (netif_msg_ifup(priv)) {
dev_info(&dev->dev, "I/O: %08lx Memory: %08lx-%08lx\n",
diff --git a/drivers/net/ethernet/freescale/dpaa/dpaa_eth.c b/drivers/net/ethernet/freescale/dpaa/dpaa_eth.c
index 9a520e4f0df9..290ad0563320 100644
--- a/drivers/net/ethernet/freescale/dpaa/dpaa_eth.c
+++ b/drivers/net/ethernet/freescale/dpaa/dpaa_eth.c
@@ -2647,7 +2647,7 @@ static int dpaa_eth_probe(struct platform_device *pdev)
priv->buf_layout[TX].priv_data_size = DPAA_TX_PRIV_DATA_SIZE; /* Tx */
/* device used for DMA mapping */
- arch_setup_dma_ops(dev, 0, 0, NULL, false);
+ set_dma_ops(dev, get_dma_ops(&pdev->dev));
err = dma_coerce_mask_and_coherent(dev, DMA_BIT_MASK(40));
if (err) {
dev_err(dev, "dma_coerce_mask_and_coherent() failed\n");
diff --git a/drivers/net/ethernet/freescale/fec_main.c b/drivers/net/ethernet/freescale/fec_main.c
index 56a563f90b0b..f7c8649fd28f 100644
--- a/drivers/net/ethernet/freescale/fec_main.c
+++ b/drivers/net/ethernet/freescale/fec_main.c
@@ -3192,7 +3192,7 @@ static int fec_reset_phy(struct platform_device *pdev)
{
int err, phy_reset;
bool active_high = false;
- int msec = 1;
+ int msec = 1, phy_post_delay = 0;
struct device_node *np = pdev->dev.of_node;
if (!np)
@@ -3209,6 +3209,11 @@ static int fec_reset_phy(struct platform_device *pdev)
else if (!gpio_is_valid(phy_reset))
return 0;
+ err = of_property_read_u32(np, "phy-reset-post-delay", &phy_post_delay);
+ /* valid reset duration should be less than 1s */
+ if (!err && phy_post_delay > 1000)
+ return -EINVAL;
+
active_high = of_property_read_bool(np, "phy-reset-active-high");
err = devm_gpio_request_one(&pdev->dev, phy_reset,
@@ -3226,6 +3231,15 @@ static int fec_reset_phy(struct platform_device *pdev)
gpio_set_value_cansleep(phy_reset, !active_high);
+ if (!phy_post_delay)
+ return 0;
+
+ if (phy_post_delay > 20)
+ msleep(phy_post_delay);
+ else
+ usleep_range(phy_post_delay * 1000,
+ phy_post_delay * 1000 + 1000);
+
return 0;
}
#else /* CONFIG_OF */
diff --git a/drivers/net/ethernet/freescale/fman/Kconfig b/drivers/net/ethernet/freescale/fman/Kconfig
index dc0850b3b517..8870a9a798ca 100644
--- a/drivers/net/ethernet/freescale/fman/Kconfig
+++ b/drivers/net/ethernet/freescale/fman/Kconfig
@@ -2,6 +2,7 @@ config FSL_FMAN
tristate "FMan support"
depends on FSL_SOC || ARCH_LAYERSCAPE || COMPILE_TEST
select GENERIC_ALLOCATOR
+ depends on HAS_DMA
select PHYLIB
default n
help
diff --git a/drivers/net/ethernet/freescale/fman/mac.c b/drivers/net/ethernet/freescale/fman/mac.c
index 0b31f8502ada..6e67d22fd0d5 100644
--- a/drivers/net/ethernet/freescale/fman/mac.c
+++ b/drivers/net/ethernet/freescale/fman/mac.c
@@ -623,6 +623,8 @@ static struct platform_device *dpaa_eth_add_device(int fman_id,
goto no_mem;
}
+ set_dma_ops(&pdev->dev, get_dma_ops(priv->dev));
+
ret = platform_device_add_data(pdev, &data, sizeof(data));
if (ret)
goto err;
diff --git a/drivers/net/ethernet/freescale/fsl_pq_mdio.c b/drivers/net/ethernet/freescale/fsl_pq_mdio.c
index 446c7b374ff5..a10de1e9c157 100644
--- a/drivers/net/ethernet/freescale/fsl_pq_mdio.c
+++ b/drivers/net/ethernet/freescale/fsl_pq_mdio.c
@@ -381,7 +381,7 @@ static int fsl_pq_mdio_probe(struct platform_device *pdev)
{
const struct of_device_id *id =
of_match_device(fsl_pq_mdio_match, &pdev->dev);
- const struct fsl_pq_mdio_data *data = id->data;
+ const struct fsl_pq_mdio_data *data;
struct device_node *np = pdev->dev.of_node;
struct resource res;
struct device_node *tbi;
@@ -389,6 +389,13 @@ static int fsl_pq_mdio_probe(struct platform_device *pdev)
struct mii_bus *new_bus;
int err;
+ if (!id) {
+ dev_err(&pdev->dev, "Failed to match device\n");
+ return -ENODEV;
+ }
+
+ data = id->data;
+
dev_dbg(&pdev->dev, "found %s compatible node\n", id->compatible);
new_bus = mdiobus_alloc_size(sizeof(*priv));
diff --git a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_misc.c b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_misc.c
index e13aa064a8e9..7a8addda726e 100644
--- a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_misc.c
+++ b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_misc.c
@@ -29,10 +29,9 @@ enum _dsm_rst_type {
HNS_ROCE_RESET_FUNC = 0x7,
};
-const u8 hns_dsaf_acpi_dsm_uuid[] = {
- 0x1A, 0xAA, 0x85, 0x1A, 0x93, 0xE2, 0x5E, 0x41,
- 0x8E, 0x28, 0x8D, 0x69, 0x0A, 0x0F, 0x82, 0x0A
-};
+static const guid_t hns_dsaf_acpi_dsm_guid =
+ GUID_INIT(0x1A85AA1A, 0xE293, 0x415E,
+ 0x8E, 0x28, 0x8D, 0x69, 0x0A, 0x0F, 0x82, 0x0A);
static void dsaf_write_sub(struct dsaf_device *dsaf_dev, u32 reg, u32 val)
{
@@ -151,7 +150,7 @@ static void hns_dsaf_acpi_srst_by_port(struct dsaf_device *dsaf_dev, u8 op_type,
argv4.package.elements = obj_args;
obj = acpi_evaluate_dsm(ACPI_HANDLE(dsaf_dev->dev),
- hns_dsaf_acpi_dsm_uuid, 0, op_type, &argv4);
+ &hns_dsaf_acpi_dsm_guid, 0, op_type, &argv4);
if (!obj) {
dev_warn(dsaf_dev->dev, "reset port_type%d port%d fail!",
port_type, port);
@@ -434,7 +433,7 @@ static phy_interface_t hns_mac_get_phy_if_acpi(struct hns_mac_cb *mac_cb)
argv4.package.elements = &obj_args,
obj = acpi_evaluate_dsm(ACPI_HANDLE(mac_cb->dev),
- hns_dsaf_acpi_dsm_uuid, 0,
+ &hns_dsaf_acpi_dsm_guid, 0,
HNS_OP_GET_PORT_TYPE_FUNC, &argv4);
if (!obj || obj->type != ACPI_TYPE_INTEGER)
@@ -474,7 +473,7 @@ int hns_mac_get_sfp_prsnt_acpi(struct hns_mac_cb *mac_cb, int *sfp_prsnt)
argv4.package.elements = &obj_args,
obj = acpi_evaluate_dsm(ACPI_HANDLE(mac_cb->dev),
- hns_dsaf_acpi_dsm_uuid, 0,
+ &hns_dsaf_acpi_dsm_guid, 0,
HNS_OP_GET_SFP_STAT_FUNC, &argv4);
if (!obj || obj->type != ACPI_TYPE_INTEGER)
@@ -565,7 +564,7 @@ hns_mac_config_sds_loopback_acpi(struct hns_mac_cb *mac_cb, bool en)
argv4.package.elements = obj_args;
obj = acpi_evaluate_dsm(ACPI_HANDLE(mac_cb->dsaf_dev->dev),
- hns_dsaf_acpi_dsm_uuid, 0,
+ &hns_dsaf_acpi_dsm_guid, 0,
HNS_OP_SERDES_LP_FUNC, &argv4);
if (!obj) {
dev_warn(mac_cb->dsaf_dev->dev, "set port%d serdes lp fail!",
diff --git a/drivers/net/ethernet/hisilicon/hns/hns_ethtool.c b/drivers/net/ethernet/hisilicon/hns/hns_ethtool.c
index b8fab149690f..e95795b3c841 100644
--- a/drivers/net/ethernet/hisilicon/hns/hns_ethtool.c
+++ b/drivers/net/ethernet/hisilicon/hns/hns_ethtool.c
@@ -288,9 +288,15 @@ static int hns_nic_config_phy_loopback(struct phy_device *phy_dev, u8 en)
/* Force 1000M Link, Default is 0x0200 */
phy_write(phy_dev, 7, 0x20C);
- phy_write(phy_dev, HNS_PHY_PAGE_REG, 0);
- /* Enable PHY loop-back */
+ /* Powerup Fiber */
+ phy_write(phy_dev, HNS_PHY_PAGE_REG, 1);
+ val = phy_read(phy_dev, COPPER_CONTROL_REG);
+ val &= ~PHY_POWER_DOWN;
+ phy_write(phy_dev, COPPER_CONTROL_REG, val);
+
+ /* Enable Phy Loopback */
+ phy_write(phy_dev, HNS_PHY_PAGE_REG, 0);
val = phy_read(phy_dev, COPPER_CONTROL_REG);
val |= PHY_LOOP_BACK;
val &= ~PHY_POWER_DOWN;
@@ -299,6 +305,12 @@ static int hns_nic_config_phy_loopback(struct phy_device *phy_dev, u8 en)
phy_write(phy_dev, HNS_PHY_PAGE_REG, 0xFA);
phy_write(phy_dev, 1, 0x400);
phy_write(phy_dev, 7, 0x200);
+
+ phy_write(phy_dev, HNS_PHY_PAGE_REG, 1);
+ val = phy_read(phy_dev, COPPER_CONTROL_REG);
+ val |= PHY_POWER_DOWN;
+ phy_write(phy_dev, COPPER_CONTROL_REG, val);
+
phy_write(phy_dev, HNS_PHY_PAGE_REG, 0);
phy_write(phy_dev, 9, 0xF00);
diff --git a/drivers/net/ethernet/ibm/emac/core.c b/drivers/net/ethernet/ibm/emac/core.c
index 508923f39ccf..259e69a52ec5 100644
--- a/drivers/net/ethernet/ibm/emac/core.c
+++ b/drivers/net/ethernet/ibm/emac/core.c
@@ -343,6 +343,7 @@ static int emac_reset(struct emac_instance *dev)
{
struct emac_regs __iomem *p = dev->emacp;
int n = 20;
+ bool __maybe_unused try_internal_clock = false;
DBG(dev, "reset" NL);
@@ -355,6 +356,7 @@ static int emac_reset(struct emac_instance *dev)
}
#ifdef CONFIG_PPC_DCR_NATIVE
+do_retry:
/*
* PPC460EX/GT Embedded Processor Advanced User's Manual
* section 28.10.1 Mode Register 0 (EMACx_MR0) states:
@@ -362,10 +364,19 @@ static int emac_reset(struct emac_instance *dev)
* of the EMAC. If none is present, select the internal clock
* (SDR0_ETH_CFG[EMACx_PHY_CLK] = 1).
* After a soft reset, select the external clock.
+ *
+ * The AR8035-A PHY Meraki MR24 does not provide a TX Clk if the
+ * ethernet cable is not attached. This causes the reset to timeout
+ * and the PHY detection code in emac_init_phy() is unable to
+ * communicate and detect the AR8035-A PHY. As a result, the emac
+ * driver bails out early and the user has no ethernet.
+ * In order to stay compatible with existing configurations, the
+ * driver will temporarily switch to the internal clock, after
+ * the first reset fails.
*/
if (emac_has_feature(dev, EMAC_FTR_460EX_PHY_CLK_FIX)) {
- if (dev->phy_address == 0xffffffff &&
- dev->phy_map == 0xffffffff) {
+ if (try_internal_clock || (dev->phy_address == 0xffffffff &&
+ dev->phy_map == 0xffffffff)) {
/* No PHY: select internal loop clock before reset */
dcri_clrset(SDR0, SDR0_ETH_CFG,
0, SDR0_ETH_CFG_ECS << dev->cell_index);
@@ -383,8 +394,15 @@ static int emac_reset(struct emac_instance *dev)
#ifdef CONFIG_PPC_DCR_NATIVE
if (emac_has_feature(dev, EMAC_FTR_460EX_PHY_CLK_FIX)) {
- if (dev->phy_address == 0xffffffff &&
- dev->phy_map == 0xffffffff) {
+ if (!n && !try_internal_clock) {
+ /* first attempt has timed out. */
+ n = 20;
+ try_internal_clock = true;
+ goto do_retry;
+ }
+
+ if (try_internal_clock || (dev->phy_address == 0xffffffff &&
+ dev->phy_map == 0xffffffff)) {
/* No PHY: restore external clock source after reset */
dcri_clrset(SDR0, SDR0_ETH_CFG,
SDR0_ETH_CFG_ECS << dev->cell_index, 0);
@@ -2460,20 +2478,24 @@ static int emac_mii_bus_reset(struct mii_bus *bus)
return emac_reset(dev);
}
+static int emac_mdio_phy_start_aneg(struct mii_phy *phy,
+ struct phy_device *phy_dev)
+{
+ phy_dev->autoneg = phy->autoneg;
+ phy_dev->speed = phy->speed;
+ phy_dev->duplex = phy->duplex;
+ phy_dev->advertising = phy->advertising;
+ return phy_start_aneg(phy_dev);
+}
+
static int emac_mdio_setup_aneg(struct mii_phy *phy, u32 advertise)
{
struct net_device *ndev = phy->dev;
struct emac_instance *dev = netdev_priv(ndev);
- dev->phy.autoneg = AUTONEG_ENABLE;
- dev->phy.speed = SPEED_1000;
- dev->phy.duplex = DUPLEX_FULL;
- dev->phy.advertising = advertise;
phy->autoneg = AUTONEG_ENABLE;
- phy->speed = dev->phy.speed;
- phy->duplex = dev->phy.duplex;
phy->advertising = advertise;
- return phy_start_aneg(dev->phy_dev);
+ return emac_mdio_phy_start_aneg(phy, dev->phy_dev);
}
static int emac_mdio_setup_forced(struct mii_phy *phy, int speed, int fd)
@@ -2481,13 +2503,10 @@ static int emac_mdio_setup_forced(struct mii_phy *phy, int speed, int fd)
struct net_device *ndev = phy->dev;
struct emac_instance *dev = netdev_priv(ndev);
- dev->phy.autoneg = AUTONEG_DISABLE;
- dev->phy.speed = speed;
- dev->phy.duplex = fd;
phy->autoneg = AUTONEG_DISABLE;
phy->speed = speed;
phy->duplex = fd;
- return phy_start_aneg(dev->phy_dev);
+ return emac_mdio_phy_start_aneg(phy, dev->phy_dev);
}
static int emac_mdio_poll_link(struct mii_phy *phy)
@@ -2509,16 +2528,17 @@ static int emac_mdio_read_link(struct mii_phy *phy)
{
struct net_device *ndev = phy->dev;
struct emac_instance *dev = netdev_priv(ndev);
+ struct phy_device *phy_dev = dev->phy_dev;
int res;
- res = phy_read_status(dev->phy_dev);
+ res = phy_read_status(phy_dev);
if (res)
return res;
- dev->phy.speed = phy->speed;
- dev->phy.duplex = phy->duplex;
- dev->phy.pause = phy->pause;
- dev->phy.asym_pause = phy->asym_pause;
+ phy->speed = phy_dev->speed;
+ phy->duplex = phy_dev->duplex;
+ phy->pause = phy_dev->pause;
+ phy->asym_pause = phy_dev->asym_pause;
return 0;
}
@@ -2528,13 +2548,6 @@ static int emac_mdio_init_phy(struct mii_phy *phy)
struct emac_instance *dev = netdev_priv(ndev);
phy_start(dev->phy_dev);
- dev->phy.autoneg = phy->autoneg;
- dev->phy.speed = phy->speed;
- dev->phy.duplex = phy->duplex;
- dev->phy.advertising = phy->advertising;
- dev->phy.pause = phy->pause;
- dev->phy.asym_pause = phy->asym_pause;
-
return phy_init_hw(dev->phy_dev);
}
diff --git a/drivers/net/ethernet/ibm/ibmvnic.c b/drivers/net/ethernet/ibm/ibmvnic.c
index 4f2d329dba99..c0fbeb387db4 100644
--- a/drivers/net/ethernet/ibm/ibmvnic.c
+++ b/drivers/net/ethernet/ibm/ibmvnic.c
@@ -81,7 +81,7 @@
static const char ibmvnic_driver_name[] = "ibmvnic";
static const char ibmvnic_driver_string[] = "IBM System i/p Virtual NIC Driver";
-MODULE_AUTHOR("Santiago Leon <santi_leon@yahoo.com>");
+MODULE_AUTHOR("Santiago Leon");
MODULE_DESCRIPTION("IBM System i/p Virtual NIC Driver");
MODULE_LICENSE("GPL");
MODULE_VERSION(IBMVNIC_DRIVER_VERSION);
@@ -1468,6 +1468,11 @@ static void ibmvnic_netpoll_controller(struct net_device *dev)
}
#endif
+static int ibmvnic_change_mtu(struct net_device *netdev, int new_mtu)
+{
+ return -EOPNOTSUPP;
+}
+
static const struct net_device_ops ibmvnic_netdev_ops = {
.ndo_open = ibmvnic_open,
.ndo_stop = ibmvnic_close,
@@ -1479,6 +1484,7 @@ static const struct net_device_ops ibmvnic_netdev_ops = {
#ifdef CONFIG_NET_POLL_CONTROLLER
.ndo_poll_controller = ibmvnic_netpoll_controller,
#endif
+ .ndo_change_mtu = ibmvnic_change_mtu,
};
/* ethtool functions */
diff --git a/drivers/net/ethernet/intel/i40e/i40e.h b/drivers/net/ethernet/intel/i40e/i40e.h
index cdde3cc28fb5..44d9610f7a15 100644
--- a/drivers/net/ethernet/intel/i40e/i40e.h
+++ b/drivers/net/ethernet/intel/i40e/i40e.h
@@ -399,6 +399,7 @@ struct i40e_pf {
#define I40E_FLAG_RX_CSUM_ENABLED BIT_ULL(1)
#define I40E_FLAG_MSI_ENABLED BIT_ULL(2)
#define I40E_FLAG_MSIX_ENABLED BIT_ULL(3)
+#define I40E_FLAG_HW_ATR_EVICT_ENABLED BIT_ULL(4)
#define I40E_FLAG_RSS_ENABLED BIT_ULL(6)
#define I40E_FLAG_VMDQ_ENABLED BIT_ULL(7)
#define I40E_FLAG_IWARP_ENABLED BIT_ULL(10)
diff --git a/drivers/net/ethernet/intel/i40e/i40e_ethtool.c b/drivers/net/ethernet/intel/i40e/i40e_ethtool.c
index 7a8eb486b9ea..894c8e57ba00 100644
--- a/drivers/net/ethernet/intel/i40e/i40e_ethtool.c
+++ b/drivers/net/ethernet/intel/i40e/i40e_ethtool.c
@@ -224,7 +224,7 @@ static const struct i40e_priv_flags i40e_gstrings_priv_flags[] = {
I40E_PRIV_FLAG("LinkPolling", I40E_FLAG_LINK_POLLING_ENABLED, 0),
I40E_PRIV_FLAG("flow-director-atr", I40E_FLAG_FD_ATR_ENABLED, 0),
I40E_PRIV_FLAG("veb-stats", I40E_FLAG_VEB_STATS_ENABLED, 0),
- I40E_PRIV_FLAG("hw-atr-eviction", I40E_FLAG_HW_ATR_EVICT_CAPABLE, 0),
+ I40E_PRIV_FLAG("hw-atr-eviction", I40E_FLAG_HW_ATR_EVICT_ENABLED, 0),
I40E_PRIV_FLAG("legacy-rx", I40E_FLAG_LEGACY_RX, 0),
};
@@ -4092,7 +4092,7 @@ flags_complete:
/* Only allow ATR evict on hardware that is capable of handling it */
if (pf->flags & I40E_FLAG_HW_ATR_EVICT_CAPABLE)
- pf->flags &= ~I40E_FLAG_HW_ATR_EVICT_CAPABLE;
+ pf->flags &= ~I40E_FLAG_HW_ATR_EVICT_ENABLED;
if (changed_flags & I40E_FLAG_TRUE_PROMISC_SUPPORT) {
u16 sw_flags = 0, valid_flags = 0;
diff --git a/drivers/net/ethernet/intel/i40e/i40e_main.c b/drivers/net/ethernet/intel/i40e/i40e_main.c
index d5c9c9e06ff5..a7a4b28b4144 100644
--- a/drivers/net/ethernet/intel/i40e/i40e_main.c
+++ b/drivers/net/ethernet/intel/i40e/i40e_main.c
@@ -295,7 +295,7 @@ struct i40e_vsi *i40e_find_vsi_from_id(struct i40e_pf *pf, u16 id)
**/
void i40e_service_event_schedule(struct i40e_pf *pf)
{
- if (!test_bit(__I40E_VSI_DOWN, pf->state) &&
+ if (!test_bit(__I40E_DOWN, pf->state) &&
!test_bit(__I40E_RESET_RECOVERY_PENDING, pf->state))
queue_work(i40e_wq, &pf->service_task);
}
@@ -3611,7 +3611,7 @@ static irqreturn_t i40e_intr(int irq, void *data)
* this is not a performance path and napi_schedule()
* can deal with rescheduling.
*/
- if (!test_bit(__I40E_VSI_DOWN, pf->state))
+ if (!test_bit(__I40E_DOWN, pf->state))
napi_schedule_irqoff(&q_vector->napi);
}
@@ -3687,7 +3687,7 @@ static irqreturn_t i40e_intr(int irq, void *data)
enable_intr:
/* re-enable interrupt causes */
wr32(hw, I40E_PFINT_ICR0_ENA, ena_mask);
- if (!test_bit(__I40E_VSI_DOWN, pf->state)) {
+ if (!test_bit(__I40E_DOWN, pf->state)) {
i40e_service_event_schedule(pf);
i40e_irq_dynamic_enable_icr0(pf, false);
}
@@ -6203,7 +6203,7 @@ static void i40e_fdir_reinit_subtask(struct i40e_pf *pf)
{
/* if interface is down do nothing */
- if (test_bit(__I40E_VSI_DOWN, pf->state))
+ if (test_bit(__I40E_DOWN, pf->state))
return;
if (test_bit(__I40E_FD_FLUSH_REQUESTED, pf->state))
@@ -6344,7 +6344,7 @@ static void i40e_watchdog_subtask(struct i40e_pf *pf)
int i;
/* if interface is down do nothing */
- if (test_bit(__I40E_VSI_DOWN, pf->state) ||
+ if (test_bit(__I40E_DOWN, pf->state) ||
test_bit(__I40E_CONFIG_BUSY, pf->state))
return;
@@ -6399,9 +6399,9 @@ static void i40e_reset_subtask(struct i40e_pf *pf)
reset_flags |= BIT(__I40E_GLOBAL_RESET_REQUESTED);
clear_bit(__I40E_GLOBAL_RESET_REQUESTED, pf->state);
}
- if (test_bit(__I40E_VSI_DOWN_REQUESTED, pf->state)) {
- reset_flags |= BIT(__I40E_VSI_DOWN_REQUESTED);
- clear_bit(__I40E_VSI_DOWN_REQUESTED, pf->state);
+ if (test_bit(__I40E_DOWN_REQUESTED, pf->state)) {
+ reset_flags |= BIT(__I40E_DOWN_REQUESTED);
+ clear_bit(__I40E_DOWN_REQUESTED, pf->state);
}
/* If there's a recovery already waiting, it takes
@@ -6415,7 +6415,7 @@ static void i40e_reset_subtask(struct i40e_pf *pf)
/* If we're already down or resetting, just bail */
if (reset_flags &&
- !test_bit(__I40E_VSI_DOWN, pf->state) &&
+ !test_bit(__I40E_DOWN, pf->state) &&
!test_bit(__I40E_CONFIG_BUSY, pf->state)) {
rtnl_lock();
i40e_do_reset(pf, reset_flags, true);
@@ -7002,7 +7002,7 @@ static void i40e_rebuild(struct i40e_pf *pf, bool reinit, bool lock_acquired)
u32 val;
int v;
- if (test_bit(__I40E_VSI_DOWN, pf->state))
+ if (test_bit(__I40E_DOWN, pf->state))
goto clear_recovery;
dev_dbg(&pf->pdev->dev, "Rebuilding internal switch\n");
@@ -8821,11 +8821,12 @@ static int i40e_sw_init(struct i40e_pf *pf)
(pf->hw.aq.api_min_ver > 4))) {
/* Supported in FW API version higher than 1.4 */
pf->flags |= I40E_FLAG_GENEVE_OFFLOAD_CAPABLE;
- pf->flags = I40E_FLAG_HW_ATR_EVICT_CAPABLE;
- } else {
- pf->flags = I40E_FLAG_HW_ATR_EVICT_CAPABLE;
}
+ /* Enable HW ATR eviction if possible */
+ if (pf->flags & I40E_FLAG_HW_ATR_EVICT_CAPABLE)
+ pf->flags |= I40E_FLAG_HW_ATR_EVICT_ENABLED;
+
pf->eeprom_version = 0xDEAD;
pf->lan_veb = I40E_NO_VEB;
pf->lan_vsi = I40E_NO_VSI;
@@ -9767,7 +9768,7 @@ int i40e_vsi_release(struct i40e_vsi *vsi)
return -ENODEV;
}
if (vsi == pf->vsi[pf->lan_vsi] &&
- !test_bit(__I40E_VSI_DOWN, pf->state)) {
+ !test_bit(__I40E_DOWN, pf->state)) {
dev_info(&pf->pdev->dev, "Can't remove PF VSI\n");
return -ENODEV;
}
@@ -11003,7 +11004,7 @@ static int i40e_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
}
pf->next_vsi = 0;
pf->pdev = pdev;
- set_bit(__I40E_VSI_DOWN, pf->state);
+ set_bit(__I40E_DOWN, pf->state);
hw = &pf->hw;
hw->back = pf;
@@ -11293,7 +11294,7 @@ static int i40e_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
* before setting up the misc vector or we get a race and the vector
* ends up disabled forever.
*/
- clear_bit(__I40E_VSI_DOWN, pf->state);
+ clear_bit(__I40E_DOWN, pf->state);
/* In case of MSIX we are going to setup the misc vector right here
* to handle admin queue events etc. In case of legacy and MSI
@@ -11448,7 +11449,7 @@ static int i40e_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
/* Unwind what we've done if something failed in the setup */
err_vsis:
- set_bit(__I40E_VSI_DOWN, pf->state);
+ set_bit(__I40E_DOWN, pf->state);
i40e_clear_interrupt_scheme(pf);
kfree(pf->vsi);
err_switch_setup:
@@ -11500,7 +11501,7 @@ static void i40e_remove(struct pci_dev *pdev)
/* no more scheduling of any task */
set_bit(__I40E_SUSPENDED, pf->state);
- set_bit(__I40E_VSI_DOWN, pf->state);
+ set_bit(__I40E_DOWN, pf->state);
if (pf->service_timer.data)
del_timer_sync(&pf->service_timer);
if (pf->service_task.func)
@@ -11740,7 +11741,7 @@ static void i40e_shutdown(struct pci_dev *pdev)
struct i40e_hw *hw = &pf->hw;
set_bit(__I40E_SUSPENDED, pf->state);
- set_bit(__I40E_VSI_DOWN, pf->state);
+ set_bit(__I40E_DOWN, pf->state);
rtnl_lock();
i40e_prep_for_reset(pf, true);
rtnl_unlock();
@@ -11789,7 +11790,7 @@ static int i40e_suspend(struct pci_dev *pdev, pm_message_t state)
int retval = 0;
set_bit(__I40E_SUSPENDED, pf->state);
- set_bit(__I40E_VSI_DOWN, pf->state);
+ set_bit(__I40E_DOWN, pf->state);
if (pf->wol_en && (pf->flags & I40E_FLAG_WOL_MC_MAGIC_PKT_WAKE))
i40e_enable_mc_magic_wake(pf);
@@ -11841,7 +11842,7 @@ static int i40e_resume(struct pci_dev *pdev)
/* handling the reset will rebuild the device state */
if (test_and_clear_bit(__I40E_SUSPENDED, pf->state)) {
- clear_bit(__I40E_VSI_DOWN, pf->state);
+ clear_bit(__I40E_DOWN, pf->state);
rtnl_lock();
i40e_reset_and_rebuild(pf, false, true);
rtnl_unlock();
diff --git a/drivers/net/ethernet/intel/i40e/i40e_txrx.c b/drivers/net/ethernet/intel/i40e/i40e_txrx.c
index 29321a6167a6..77115c25d96f 100644
--- a/drivers/net/ethernet/intel/i40e/i40e_txrx.c
+++ b/drivers/net/ethernet/intel/i40e/i40e_txrx.c
@@ -1854,7 +1854,8 @@ static struct sk_buff *i40e_build_skb(struct i40e_ring *rx_ring,
#if (PAGE_SIZE < 8192)
unsigned int truesize = i40e_rx_pg_size(rx_ring) / 2;
#else
- unsigned int truesize = SKB_DATA_ALIGN(size);
+ unsigned int truesize = SKB_DATA_ALIGN(sizeof(struct skb_shared_info)) +
+ SKB_DATA_ALIGN(I40E_SKB_PAD + size);
#endif
struct sk_buff *skb;
@@ -2340,7 +2341,7 @@ static void i40e_atr(struct i40e_ring *tx_ring, struct sk_buff *skb,
/* Due to lack of space, no more new filters can be programmed */
if (th->syn && (pf->flags & I40E_FLAG_FD_ATR_AUTO_DISABLED))
return;
- if (pf->flags & I40E_FLAG_HW_ATR_EVICT_CAPABLE) {
+ if (pf->flags & I40E_FLAG_HW_ATR_EVICT_ENABLED) {
/* HW ATR eviction will take care of removing filters on FIN
* and RST packets.
*/
@@ -2402,7 +2403,7 @@ static void i40e_atr(struct i40e_ring *tx_ring, struct sk_buff *skb,
I40E_TXD_FLTR_QW1_CNTINDEX_SHIFT) &
I40E_TXD_FLTR_QW1_CNTINDEX_MASK;
- if (pf->flags & I40E_FLAG_HW_ATR_EVICT_CAPABLE)
+ if (pf->flags & I40E_FLAG_HW_ATR_EVICT_ENABLED)
dtype_cmd |= I40E_TXD_FLTR_QW1_ATR_MASK;
fdir_desc->qindex_flex_ptype_vsi = cpu_to_le32(flex_ptype);
diff --git a/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c b/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c
index 95c23fbaa211..0fb38ca78900 100644
--- a/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c
+++ b/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c
@@ -3017,10 +3017,12 @@ int i40e_ndo_set_vf_port_vlan(struct net_device *netdev, int vf_id,
VLAN_VID_MASK));
}
+ spin_unlock_bh(&vsi->mac_filter_hash_lock);
if (vlan_id || qos)
ret = i40e_vsi_add_pvid(vsi, vlanprio);
else
i40e_vsi_remove_pvid(vsi);
+ spin_lock_bh(&vsi->mac_filter_hash_lock);
if (vlan_id) {
dev_info(&pf->pdev->dev, "Setting VLAN %d, QOS 0x%x on VF %d\n",
diff --git a/drivers/net/ethernet/intel/i40evf/i40e_txrx.c b/drivers/net/ethernet/intel/i40evf/i40e_txrx.c
index dfe241a12ad0..12b02e530503 100644
--- a/drivers/net/ethernet/intel/i40evf/i40e_txrx.c
+++ b/drivers/net/ethernet/intel/i40evf/i40e_txrx.c
@@ -1190,7 +1190,8 @@ static struct sk_buff *i40e_build_skb(struct i40e_ring *rx_ring,
#if (PAGE_SIZE < 8192)
unsigned int truesize = i40e_rx_pg_size(rx_ring) / 2;
#else
- unsigned int truesize = SKB_DATA_ALIGN(size);
+ unsigned int truesize = SKB_DATA_ALIGN(sizeof(struct skb_shared_info)) +
+ SKB_DATA_ALIGN(I40E_SKB_PAD + size);
#endif
struct sk_buff *skb;
diff --git a/drivers/net/ethernet/marvell/mvpp2.c b/drivers/net/ethernet/marvell/mvpp2.c
index 9b875d776b29..33c901622ed5 100644
--- a/drivers/net/ethernet/marvell/mvpp2.c
+++ b/drivers/net/ethernet/marvell/mvpp2.c
@@ -3719,7 +3719,7 @@ static void mvpp2_bm_bufs_get_addrs(struct device *dev, struct mvpp2 *priv,
dma_addr_t *dma_addr,
phys_addr_t *phys_addr)
{
- int cpu = smp_processor_id();
+ int cpu = get_cpu();
*dma_addr = mvpp2_percpu_read(priv, cpu,
MVPP2_BM_PHY_ALLOC_REG(bm_pool->id));
@@ -3740,6 +3740,8 @@ static void mvpp2_bm_bufs_get_addrs(struct device *dev, struct mvpp2 *priv,
if (sizeof(phys_addr_t) == 8)
*phys_addr |= (u64)phys_addr_highbits << 32;
}
+
+ put_cpu();
}
/* Free all buffers from the pool */
@@ -3920,18 +3922,12 @@ static inline u32 mvpp2_bm_cookie_pool_set(u32 cookie, int pool)
return bm;
}
-/* Get pool number from a BM cookie */
-static inline int mvpp2_bm_cookie_pool_get(unsigned long cookie)
-{
- return (cookie >> MVPP2_BM_COOKIE_POOL_OFFS) & 0xFF;
-}
-
/* Release buffer to BM */
static inline void mvpp2_bm_pool_put(struct mvpp2_port *port, int pool,
dma_addr_t buf_dma_addr,
phys_addr_t buf_phys_addr)
{
- int cpu = smp_processor_id();
+ int cpu = get_cpu();
if (port->priv->hw_version == MVPP22) {
u32 val = 0;
@@ -3958,15 +3954,15 @@ static inline void mvpp2_bm_pool_put(struct mvpp2_port *port, int pool,
MVPP2_BM_VIRT_RLS_REG, buf_phys_addr);
mvpp2_percpu_write(port->priv, cpu,
MVPP2_BM_PHY_RLS_REG(pool), buf_dma_addr);
+
+ put_cpu();
}
/* Refill BM pool */
-static void mvpp2_pool_refill(struct mvpp2_port *port, u32 bm,
+static void mvpp2_pool_refill(struct mvpp2_port *port, int pool,
dma_addr_t dma_addr,
phys_addr_t phys_addr)
{
- int pool = mvpp2_bm_cookie_pool_get(bm);
-
mvpp2_bm_pool_put(port, pool, dma_addr, phys_addr);
}
@@ -4186,8 +4182,6 @@ static void mvpp22_port_mii_set(struct mvpp2_port *port)
{
u32 val;
- return;
-
/* Only GOP port 0 has an XLG MAC */
if (port->gop_id == 0) {
val = readl(port->base + MVPP22_XLG_CTRL3_REG);
@@ -4515,21 +4509,6 @@ static void mvpp2_rxq_offset_set(struct mvpp2_port *port,
mvpp2_write(port->priv, MVPP2_RXQ_CONFIG_REG(prxq), val);
}
-/* Obtain BM cookie information from descriptor */
-static u32 mvpp2_bm_cookie_build(struct mvpp2_port *port,
- struct mvpp2_rx_desc *rx_desc)
-{
- int cpu = smp_processor_id();
- int pool;
-
- pool = (mvpp2_rxdesc_status_get(port, rx_desc) &
- MVPP2_RXD_BM_POOL_ID_MASK) >>
- MVPP2_RXD_BM_POOL_ID_OFFS;
-
- return ((pool & 0xFF) << MVPP2_BM_COOKIE_POOL_OFFS) |
- ((cpu & 0xFF) << MVPP2_BM_COOKIE_CPU_OFFS);
-}
-
/* Tx descriptors helper methods */
/* Get pointer to next Tx descriptor to be processed (send) by HW */
@@ -4757,7 +4736,7 @@ static void mvpp2_txp_max_tx_size_set(struct mvpp2_port *port)
static void mvpp2_rx_pkts_coal_set(struct mvpp2_port *port,
struct mvpp2_rx_queue *rxq)
{
- int cpu = smp_processor_id();
+ int cpu = get_cpu();
if (rxq->pkts_coal > MVPP2_OCCUPIED_THRESH_MASK)
rxq->pkts_coal = MVPP2_OCCUPIED_THRESH_MASK;
@@ -4765,6 +4744,8 @@ static void mvpp2_rx_pkts_coal_set(struct mvpp2_port *port,
mvpp2_percpu_write(port->priv, cpu, MVPP2_RXQ_NUM_REG, rxq->id);
mvpp2_percpu_write(port->priv, cpu, MVPP2_RXQ_THRESH_REG,
rxq->pkts_coal);
+
+ put_cpu();
}
static u32 mvpp2_usec_to_cycles(u32 usec, unsigned long clk_hz)
@@ -4945,7 +4926,7 @@ static int mvpp2_rxq_init(struct mvpp2_port *port,
mvpp2_write(port->priv, MVPP2_RXQ_STATUS_REG(rxq->id), 0);
/* Set Rx descriptors queue starting address - indirect access */
- cpu = smp_processor_id();
+ cpu = get_cpu();
mvpp2_percpu_write(port->priv, cpu, MVPP2_RXQ_NUM_REG, rxq->id);
if (port->priv->hw_version == MVPP21)
rxq_dma = rxq->descs_dma;
@@ -4954,6 +4935,7 @@ static int mvpp2_rxq_init(struct mvpp2_port *port,
mvpp2_percpu_write(port->priv, cpu, MVPP2_RXQ_DESC_ADDR_REG, rxq_dma);
mvpp2_percpu_write(port->priv, cpu, MVPP2_RXQ_DESC_SIZE_REG, rxq->size);
mvpp2_percpu_write(port->priv, cpu, MVPP2_RXQ_INDEX_REG, 0);
+ put_cpu();
/* Set Offset */
mvpp2_rxq_offset_set(port, rxq->id, NET_SKB_PAD);
@@ -4980,9 +4962,13 @@ static void mvpp2_rxq_drop_pkts(struct mvpp2_port *port,
for (i = 0; i < rx_received; i++) {
struct mvpp2_rx_desc *rx_desc = mvpp2_rxq_next_desc_get(rxq);
- u32 bm = mvpp2_bm_cookie_build(port, rx_desc);
+ u32 status = mvpp2_rxdesc_status_get(port, rx_desc);
+ int pool;
+
+ pool = (status & MVPP2_RXD_BM_POOL_ID_MASK) >>
+ MVPP2_RXD_BM_POOL_ID_OFFS;
- mvpp2_pool_refill(port, bm,
+ mvpp2_pool_refill(port, pool,
mvpp2_rxdesc_dma_addr_get(port, rx_desc),
mvpp2_rxdesc_cookie_get(port, rx_desc));
}
@@ -5012,10 +4998,11 @@ static void mvpp2_rxq_deinit(struct mvpp2_port *port,
* free descriptor number
*/
mvpp2_write(port->priv, MVPP2_RXQ_STATUS_REG(rxq->id), 0);
- cpu = smp_processor_id();
+ cpu = get_cpu();
mvpp2_percpu_write(port->priv, cpu, MVPP2_RXQ_NUM_REG, rxq->id);
mvpp2_percpu_write(port->priv, cpu, MVPP2_RXQ_DESC_ADDR_REG, 0);
mvpp2_percpu_write(port->priv, cpu, MVPP2_RXQ_DESC_SIZE_REG, 0);
+ put_cpu();
}
/* Create and initialize a Tx queue */
@@ -5038,7 +5025,7 @@ static int mvpp2_txq_init(struct mvpp2_port *port,
txq->last_desc = txq->size - 1;
/* Set Tx descriptors queue starting address - indirect access */
- cpu = smp_processor_id();
+ cpu = get_cpu();
mvpp2_percpu_write(port->priv, cpu, MVPP2_TXQ_NUM_REG, txq->id);
mvpp2_percpu_write(port->priv, cpu, MVPP2_TXQ_DESC_ADDR_REG,
txq->descs_dma);
@@ -5063,6 +5050,7 @@ static int mvpp2_txq_init(struct mvpp2_port *port,
mvpp2_percpu_write(port->priv, cpu, MVPP2_TXQ_PREF_BUF_REG,
MVPP2_PREF_BUF_PTR(desc) | MVPP2_PREF_BUF_SIZE_16 |
MVPP2_PREF_BUF_THRESH(desc_per_txq / 2));
+ put_cpu();
/* WRR / EJP configuration - indirect access */
tx_port_num = mvpp2_egress_port(port);
@@ -5133,10 +5121,11 @@ static void mvpp2_txq_deinit(struct mvpp2_port *port,
mvpp2_write(port->priv, MVPP2_TXQ_SCHED_TOKEN_CNTR_REG(txq->id), 0);
/* Set Tx descriptors queue starting address and size */
- cpu = smp_processor_id();
+ cpu = get_cpu();
mvpp2_percpu_write(port->priv, cpu, MVPP2_TXQ_NUM_REG, txq->id);
mvpp2_percpu_write(port->priv, cpu, MVPP2_TXQ_DESC_ADDR_REG, 0);
mvpp2_percpu_write(port->priv, cpu, MVPP2_TXQ_DESC_SIZE_REG, 0);
+ put_cpu();
}
/* Cleanup Tx ports */
@@ -5146,7 +5135,7 @@ static void mvpp2_txq_clean(struct mvpp2_port *port, struct mvpp2_tx_queue *txq)
int delay, pending, cpu;
u32 val;
- cpu = smp_processor_id();
+ cpu = get_cpu();
mvpp2_percpu_write(port->priv, cpu, MVPP2_TXQ_NUM_REG, txq->id);
val = mvpp2_percpu_read(port->priv, cpu, MVPP2_TXQ_PREF_BUF_REG);
val |= MVPP2_TXQ_DRAIN_EN_MASK;
@@ -5173,6 +5162,7 @@ static void mvpp2_txq_clean(struct mvpp2_port *port, struct mvpp2_tx_queue *txq)
val &= ~MVPP2_TXQ_DRAIN_EN_MASK;
mvpp2_percpu_write(port->priv, cpu, MVPP2_TXQ_PREF_BUF_REG, val);
+ put_cpu();
for_each_present_cpu(cpu) {
txq_pcpu = per_cpu_ptr(txq->pcpu, cpu);
@@ -5420,7 +5410,7 @@ static void mvpp2_rx_csum(struct mvpp2_port *port, u32 status,
/* Reuse skb if possible, or allocate a new skb and add it to BM pool */
static int mvpp2_rx_refill(struct mvpp2_port *port,
- struct mvpp2_bm_pool *bm_pool, u32 bm)
+ struct mvpp2_bm_pool *bm_pool, int pool)
{
dma_addr_t dma_addr;
phys_addr_t phys_addr;
@@ -5432,7 +5422,7 @@ static int mvpp2_rx_refill(struct mvpp2_port *port,
if (!buf)
return -ENOMEM;
- mvpp2_pool_refill(port, bm, dma_addr, phys_addr);
+ mvpp2_pool_refill(port, pool, dma_addr, phys_addr);
return 0;
}
@@ -5490,7 +5480,7 @@ static int mvpp2_rx(struct mvpp2_port *port, int rx_todo,
unsigned int frag_size;
dma_addr_t dma_addr;
phys_addr_t phys_addr;
- u32 bm, rx_status;
+ u32 rx_status;
int pool, rx_bytes, err;
void *data;
@@ -5502,8 +5492,8 @@ static int mvpp2_rx(struct mvpp2_port *port, int rx_todo,
phys_addr = mvpp2_rxdesc_cookie_get(port, rx_desc);
data = (void *)phys_to_virt(phys_addr);
- bm = mvpp2_bm_cookie_build(port, rx_desc);
- pool = mvpp2_bm_cookie_pool_get(bm);
+ pool = (rx_status & MVPP2_RXD_BM_POOL_ID_MASK) >>
+ MVPP2_RXD_BM_POOL_ID_OFFS;
bm_pool = &port->priv->bm_pools[pool];
/* In case of an error, release the requested buffer pointer
@@ -5516,7 +5506,7 @@ err_drop_frame:
dev->stats.rx_errors++;
mvpp2_rx_error(port, rx_desc);
/* Return the buffer to the pool */
- mvpp2_pool_refill(port, bm, dma_addr, phys_addr);
+ mvpp2_pool_refill(port, pool, dma_addr, phys_addr);
continue;
}
@@ -5531,7 +5521,7 @@ err_drop_frame:
goto err_drop_frame;
}
- err = mvpp2_rx_refill(port, bm_pool, bm);
+ err = mvpp2_rx_refill(port, bm_pool, pool);
if (err) {
netdev_err(port->dev, "failed to refill BM pools\n");
goto err_drop_frame;
diff --git a/drivers/net/ethernet/mellanox/mlx4/en_ethtool.c b/drivers/net/ethernet/mellanox/mlx4/en_ethtool.c
index ae5fdc2df654..ffbcb27c05e5 100644
--- a/drivers/net/ethernet/mellanox/mlx4/en_ethtool.c
+++ b/drivers/net/ethernet/mellanox/mlx4/en_ethtool.c
@@ -1562,11 +1562,6 @@ static int mlx4_en_flow_replace(struct net_device *dev,
qpn = priv->drop_qp.qpn;
else if (cmd->fs.ring_cookie & EN_ETHTOOL_QP_ATTACH) {
qpn = cmd->fs.ring_cookie & (EN_ETHTOOL_QP_ATTACH - 1);
- if (qpn < priv->rss_map.base_qpn ||
- qpn >= priv->rss_map.base_qpn + priv->rx_ring_num) {
- en_warn(priv, "rxnfc: QP (0x%x) doesn't exist\n", qpn);
- return -EINVAL;
- }
} else {
if (cmd->fs.ring_cookie >= priv->rx_ring_num) {
en_warn(priv, "rxnfc: RX ring (%llu) doesn't exist\n",
diff --git a/drivers/net/ethernet/mellanox/mlx4/mcg.c b/drivers/net/ethernet/mellanox/mlx4/mcg.c
index 1a670b681555..0710b3677464 100644
--- a/drivers/net/ethernet/mellanox/mlx4/mcg.c
+++ b/drivers/net/ethernet/mellanox/mlx4/mcg.c
@@ -35,6 +35,7 @@
#include <linux/etherdevice.h>
#include <linux/mlx4/cmd.h>
+#include <linux/mlx4/qp.h>
#include <linux/export.h>
#include "mlx4.h"
@@ -985,16 +986,21 @@ int mlx4_flow_attach(struct mlx4_dev *dev,
if (IS_ERR(mailbox))
return PTR_ERR(mailbox);
+ if (!mlx4_qp_lookup(dev, rule->qpn)) {
+ mlx4_err_rule(dev, "QP doesn't exist\n", rule);
+ ret = -EINVAL;
+ goto out;
+ }
+
trans_rule_ctrl_to_hw(rule, mailbox->buf);
size += sizeof(struct mlx4_net_trans_rule_hw_ctrl);
list_for_each_entry(cur, &rule->list, list) {
ret = parse_trans_rule(dev, cur, mailbox->buf + size);
- if (ret < 0) {
- mlx4_free_cmd_mailbox(dev, mailbox);
- return ret;
- }
+ if (ret < 0)
+ goto out;
+
size += ret;
}
@@ -1021,6 +1027,7 @@ int mlx4_flow_attach(struct mlx4_dev *dev,
}
}
+out:
mlx4_free_cmd_mailbox(dev, mailbox);
return ret;
diff --git a/drivers/net/ethernet/mellanox/mlx4/qp.c b/drivers/net/ethernet/mellanox/mlx4/qp.c
index 2d6abd4662b1..5a310d313e94 100644
--- a/drivers/net/ethernet/mellanox/mlx4/qp.c
+++ b/drivers/net/ethernet/mellanox/mlx4/qp.c
@@ -384,6 +384,19 @@ static void mlx4_qp_free_icm(struct mlx4_dev *dev, int qpn)
__mlx4_qp_free_icm(dev, qpn);
}
+struct mlx4_qp *mlx4_qp_lookup(struct mlx4_dev *dev, u32 qpn)
+{
+ struct mlx4_qp_table *qp_table = &mlx4_priv(dev)->qp_table;
+ struct mlx4_qp *qp;
+
+ spin_lock(&qp_table->lock);
+
+ qp = __mlx4_qp_lookup(dev, qpn);
+
+ spin_unlock(&qp_table->lock);
+ return qp;
+}
+
int mlx4_qp_alloc(struct mlx4_dev *dev, int qpn, struct mlx4_qp *qp, gfp_t gfp)
{
struct mlx4_priv *priv = mlx4_priv(dev);
@@ -471,6 +484,12 @@ int mlx4_update_qp(struct mlx4_dev *dev, u32 qpn,
}
if (attr & MLX4_UPDATE_QP_QOS_VPORT) {
+ if (!(dev->caps.flags2 & MLX4_DEV_CAP_FLAG2_QOS_VPP)) {
+ mlx4_warn(dev, "Granular QoS per VF is not enabled\n");
+ err = -EOPNOTSUPP;
+ goto out;
+ }
+
qp_mask |= 1ULL << MLX4_UPD_QP_MASK_QOS_VPP;
cmd->qp_context.qos_vport = params->qos_vport;
}
diff --git a/drivers/net/ethernet/mellanox/mlx4/resource_tracker.c b/drivers/net/ethernet/mellanox/mlx4/resource_tracker.c
index 07516545474f..812783865205 100644
--- a/drivers/net/ethernet/mellanox/mlx4/resource_tracker.c
+++ b/drivers/net/ethernet/mellanox/mlx4/resource_tracker.c
@@ -5255,6 +5255,13 @@ void mlx4_delete_all_resources_for_slave(struct mlx4_dev *dev, int slave)
mutex_unlock(&priv->mfunc.master.res_tracker.slave_list[slave].mutex);
}
+static void update_qos_vpp(struct mlx4_update_qp_context *ctx,
+ struct mlx4_vf_immed_vlan_work *work)
+{
+ ctx->qp_mask |= cpu_to_be64(1ULL << MLX4_UPD_QP_MASK_QOS_VPP);
+ ctx->qp_context.qos_vport = work->qos_vport;
+}
+
void mlx4_vf_immed_vlan_work_handler(struct work_struct *_work)
{
struct mlx4_vf_immed_vlan_work *work =
@@ -5369,11 +5376,10 @@ void mlx4_vf_immed_vlan_work_handler(struct work_struct *_work)
qp->sched_queue & 0xC7;
upd_context->qp_context.pri_path.sched_queue |=
((work->qos & 0x7) << 3);
- upd_context->qp_mask |=
- cpu_to_be64(1ULL <<
- MLX4_UPD_QP_MASK_QOS_VPP);
- upd_context->qp_context.qos_vport =
- work->qos_vport;
+
+ if (dev->caps.flags2 &
+ MLX4_DEV_CAP_FLAG2_QOS_VPP)
+ update_qos_vpp(upd_context, work);
}
err = mlx4_cmd(dev, mailbox->dma,
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/cmd.c b/drivers/net/ethernet/mellanox/mlx5/core/cmd.c
index 5bdaf3d545b2..10d282841f5b 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/cmd.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/cmd.c
@@ -774,7 +774,7 @@ static void cb_timeout_handler(struct work_struct *work)
mlx5_core_warn(dev, "%s(0x%x) timeout. Will cause a leak of a command resource\n",
mlx5_command_str(msg_to_opcode(ent->in)),
msg_to_opcode(ent->in));
- mlx5_cmd_comp_handler(dev, 1UL << ent->idx);
+ mlx5_cmd_comp_handler(dev, 1UL << ent->idx, true);
}
static void cmd_work_handler(struct work_struct *work)
@@ -804,6 +804,7 @@ static void cmd_work_handler(struct work_struct *work)
}
cmd->ent_arr[ent->idx] = ent;
+ set_bit(MLX5_CMD_ENT_STATE_PENDING_COMP, &ent->state);
lay = get_inst(cmd, ent->idx);
ent->lay = lay;
memset(lay, 0, sizeof(*lay));
@@ -825,6 +826,20 @@ static void cmd_work_handler(struct work_struct *work)
if (ent->callback)
schedule_delayed_work(&ent->cb_timeout_work, cb_timeout);
+ /* Skip sending command to fw if internal error */
+ if (pci_channel_offline(dev->pdev) ||
+ dev->state == MLX5_DEVICE_STATE_INTERNAL_ERROR) {
+ u8 status = 0;
+ u32 drv_synd;
+
+ ent->ret = mlx5_internal_err_ret_value(dev, msg_to_opcode(ent->in), &drv_synd, &status);
+ MLX5_SET(mbox_out, ent->out, status, status);
+ MLX5_SET(mbox_out, ent->out, syndrome, drv_synd);
+
+ mlx5_cmd_comp_handler(dev, 1UL << ent->idx, true);
+ return;
+ }
+
/* ring doorbell after the descriptor is valid */
mlx5_core_dbg(dev, "writing 0x%x to command doorbell\n", 1 << ent->idx);
wmb();
@@ -835,7 +850,7 @@ static void cmd_work_handler(struct work_struct *work)
poll_timeout(ent);
/* make sure we read the descriptor after ownership is SW */
rmb();
- mlx5_cmd_comp_handler(dev, 1UL << ent->idx);
+ mlx5_cmd_comp_handler(dev, 1UL << ent->idx, (ent->ret == -ETIMEDOUT));
}
}
@@ -879,7 +894,7 @@ static int wait_func(struct mlx5_core_dev *dev, struct mlx5_cmd_work_ent *ent)
wait_for_completion(&ent->done);
} else if (!wait_for_completion_timeout(&ent->done, timeout)) {
ent->ret = -ETIMEDOUT;
- mlx5_cmd_comp_handler(dev, 1UL << ent->idx);
+ mlx5_cmd_comp_handler(dev, 1UL << ent->idx, true);
}
err = ent->ret;
@@ -1375,7 +1390,7 @@ static void free_msg(struct mlx5_core_dev *dev, struct mlx5_cmd_msg *msg)
}
}
-void mlx5_cmd_comp_handler(struct mlx5_core_dev *dev, u64 vec)
+void mlx5_cmd_comp_handler(struct mlx5_core_dev *dev, u64 vec, bool forced)
{
struct mlx5_cmd *cmd = &dev->cmd;
struct mlx5_cmd_work_ent *ent;
@@ -1395,6 +1410,19 @@ void mlx5_cmd_comp_handler(struct mlx5_core_dev *dev, u64 vec)
struct semaphore *sem;
ent = cmd->ent_arr[i];
+
+ /* if we already completed the command, ignore it */
+ if (!test_and_clear_bit(MLX5_CMD_ENT_STATE_PENDING_COMP,
+ &ent->state)) {
+ /* only real completion can free the cmd slot */
+ if (!forced) {
+ mlx5_core_err(dev, "Command completion arrived after timeout (entry idx = %d).\n",
+ ent->idx);
+ free_ent(cmd, ent->idx);
+ }
+ continue;
+ }
+
if (ent->callback)
cancel_delayed_work(&ent->cb_timeout_work);
if (ent->page_queue)
@@ -1417,7 +1445,10 @@ void mlx5_cmd_comp_handler(struct mlx5_core_dev *dev, u64 vec)
mlx5_core_dbg(dev, "command completed. ret 0x%x, delivery status %s(0x%x)\n",
ent->ret, deliv_status_to_str(ent->status), ent->status);
}
- free_ent(cmd, ent->idx);
+
+ /* only real completion will free the entry slot */
+ if (!forced)
+ free_ent(cmd, ent->idx);
if (ent->callback) {
ds = ent->ts2 - ent->ts1;
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en.h b/drivers/net/ethernet/mellanox/mlx5/core/en.h
index 2fd044b23875..944fc1742464 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en.h
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en.h
@@ -458,13 +458,15 @@ struct mlx5e_mpw_info {
struct mlx5e_rx_am_stats {
int ppms; /* packets per msec */
+ int bpms; /* bytes per msec */
int epms; /* events per msec */
};
struct mlx5e_rx_am_sample {
- ktime_t time;
- unsigned int pkt_ctr;
- u16 event_ctr;
+ ktime_t time;
+ u32 pkt_ctr;
+ u32 byte_ctr;
+ u16 event_ctr;
};
struct mlx5e_rx_am { /* Adaptive Moderation */
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_ethtool.c b/drivers/net/ethernet/mellanox/mlx5/core/en_ethtool.c
index 8209affa75c3..16486dff1493 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en_ethtool.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en_ethtool.c
@@ -1242,11 +1242,11 @@ static int mlx5e_get_ts_info(struct net_device *dev,
SOF_TIMESTAMPING_RX_HARDWARE |
SOF_TIMESTAMPING_RAW_HARDWARE;
- info->tx_types = (BIT(1) << HWTSTAMP_TX_OFF) |
- (BIT(1) << HWTSTAMP_TX_ON);
+ info->tx_types = BIT(HWTSTAMP_TX_OFF) |
+ BIT(HWTSTAMP_TX_ON);
- info->rx_filters = (BIT(1) << HWTSTAMP_FILTER_NONE) |
- (BIT(1) << HWTSTAMP_FILTER_ALL);
+ info->rx_filters = BIT(HWTSTAMP_FILTER_NONE) |
+ BIT(HWTSTAMP_FILTER_ALL);
return 0;
}
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c
index 41cd22a223dc..277f4de30375 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c
@@ -4241,7 +4241,8 @@ struct net_device *mlx5e_create_netdev(struct mlx5_core_dev *mdev,
return netdev;
err_cleanup_nic:
- profile->cleanup(priv);
+ if (profile->cleanup)
+ profile->cleanup(priv);
free_netdev(netdev);
return NULL;
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_rep.c b/drivers/net/ethernet/mellanox/mlx5/core/en_rep.c
index 79462c0368a0..46984a52a94b 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en_rep.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en_rep.c
@@ -791,6 +791,8 @@ static void mlx5e_build_rep_params(struct mlx5_core_dev *mdev,
params->tx_max_inline = mlx5e_get_max_inline_cap(mdev);
params->num_tc = 1;
params->lro_wqe_sz = MLX5E_PARAMS_DEFAULT_LRO_WQE_SZ;
+
+ mlx5_query_min_inline(mdev, &params->tx_min_inline_mode);
}
static void mlx5e_build_rep_netdev(struct net_device *netdev)
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_rx.c b/drivers/net/ethernet/mellanox/mlx5/core/en_rx.c
index 7b1566f0ae58..66b5fec15313 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en_rx.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en_rx.c
@@ -1041,6 +1041,8 @@ void mlx5e_free_xdpsq_descs(struct mlx5e_xdpsq *sq)
#define MLX5_IB_GRH_BYTES 40
#define MLX5_IPOIB_ENCAP_LEN 4
#define MLX5_GID_SIZE 16
+#define MLX5_IPOIB_PSEUDO_LEN 20
+#define MLX5_IPOIB_HARD_LEN (MLX5_IPOIB_PSEUDO_LEN + MLX5_IPOIB_ENCAP_LEN)
static inline void mlx5i_complete_rx_cqe(struct mlx5e_rq *rq,
struct mlx5_cqe64 *cqe,
@@ -1048,6 +1050,7 @@ static inline void mlx5i_complete_rx_cqe(struct mlx5e_rq *rq,
struct sk_buff *skb)
{
struct net_device *netdev = rq->netdev;
+ char *pseudo_header;
u8 *dgid;
u8 g;
@@ -1076,8 +1079,11 @@ static inline void mlx5i_complete_rx_cqe(struct mlx5e_rq *rq,
if (likely(netdev->features & NETIF_F_RXHASH))
mlx5e_skb_set_hash(cqe, skb);
+ /* 20 bytes of ipoib header and 4 for encap existing */
+ pseudo_header = skb_push(skb, MLX5_IPOIB_PSEUDO_LEN);
+ memset(pseudo_header, 0, MLX5_IPOIB_PSEUDO_LEN);
skb_reset_mac_header(skb);
- skb_pull(skb, MLX5_IPOIB_ENCAP_LEN);
+ skb_pull(skb, MLX5_IPOIB_HARD_LEN);
skb->dev = netdev;
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_rx_am.c b/drivers/net/ethernet/mellanox/mlx5/core/en_rx_am.c
index 02dd3a95ed8f..acf32fe952cd 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en_rx_am.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en_rx_am.c
@@ -183,28 +183,27 @@ static void mlx5e_am_exit_parking(struct mlx5e_rx_am *am)
mlx5e_am_step(am);
}
+#define IS_SIGNIFICANT_DIFF(val, ref) \
+ (((100 * abs((val) - (ref))) / (ref)) > 10) /* more than 10% difference */
+
static int mlx5e_am_stats_compare(struct mlx5e_rx_am_stats *curr,
struct mlx5e_rx_am_stats *prev)
{
- int diff;
-
- if (!prev->ppms)
- return curr->ppms ? MLX5E_AM_STATS_BETTER :
+ if (!prev->bpms)
+ return curr->bpms ? MLX5E_AM_STATS_BETTER :
MLX5E_AM_STATS_SAME;
- diff = curr->ppms - prev->ppms;
- if (((100 * abs(diff)) / prev->ppms) > 10) /* more than 10% diff */
- return (diff > 0) ? MLX5E_AM_STATS_BETTER :
- MLX5E_AM_STATS_WORSE;
+ if (IS_SIGNIFICANT_DIFF(curr->bpms, prev->bpms))
+ return (curr->bpms > prev->bpms) ? MLX5E_AM_STATS_BETTER :
+ MLX5E_AM_STATS_WORSE;
- if (!prev->epms)
- return curr->epms ? MLX5E_AM_STATS_WORSE :
- MLX5E_AM_STATS_SAME;
+ if (IS_SIGNIFICANT_DIFF(curr->ppms, prev->ppms))
+ return (curr->ppms > prev->ppms) ? MLX5E_AM_STATS_BETTER :
+ MLX5E_AM_STATS_WORSE;
- diff = curr->epms - prev->epms;
- if (((100 * abs(diff)) / prev->epms) > 10) /* more than 10% diff */
- return (diff < 0) ? MLX5E_AM_STATS_BETTER :
- MLX5E_AM_STATS_WORSE;
+ if (IS_SIGNIFICANT_DIFF(curr->epms, prev->epms))
+ return (curr->epms < prev->epms) ? MLX5E_AM_STATS_BETTER :
+ MLX5E_AM_STATS_WORSE;
return MLX5E_AM_STATS_SAME;
}
@@ -266,10 +265,13 @@ static void mlx5e_am_sample(struct mlx5e_rq *rq,
{
s->time = ktime_get();
s->pkt_ctr = rq->stats.packets;
+ s->byte_ctr = rq->stats.bytes;
s->event_ctr = rq->cq.event_ctr;
}
#define MLX5E_AM_NEVENTS 64
+#define BITS_PER_TYPE(type) (sizeof(type) * BITS_PER_BYTE)
+#define BIT_GAP(bits, end, start) ((((end) - (start)) + BIT_ULL(bits)) & (BIT_ULL(bits) - 1))
static void mlx5e_am_calc_stats(struct mlx5e_rx_am_sample *start,
struct mlx5e_rx_am_sample *end,
@@ -277,13 +279,17 @@ static void mlx5e_am_calc_stats(struct mlx5e_rx_am_sample *start,
{
/* u32 holds up to 71 minutes, should be enough */
u32 delta_us = ktime_us_delta(end->time, start->time);
- unsigned int npkts = end->pkt_ctr - start->pkt_ctr;
+ u32 npkts = BIT_GAP(BITS_PER_TYPE(u32), end->pkt_ctr, start->pkt_ctr);
+ u32 nbytes = BIT_GAP(BITS_PER_TYPE(u32), end->byte_ctr,
+ start->byte_ctr);
if (!delta_us)
return;
- curr_stats->ppms = (npkts * USEC_PER_MSEC) / delta_us;
- curr_stats->epms = (MLX5E_AM_NEVENTS * USEC_PER_MSEC) / delta_us;
+ curr_stats->ppms = DIV_ROUND_UP(npkts * USEC_PER_MSEC, delta_us);
+ curr_stats->bpms = DIV_ROUND_UP(nbytes * USEC_PER_MSEC, delta_us);
+ curr_stats->epms = DIV_ROUND_UP(MLX5E_AM_NEVENTS * USEC_PER_MSEC,
+ delta_us);
}
void mlx5e_rx_am_work(struct work_struct *work)
@@ -308,7 +314,8 @@ void mlx5e_rx_am(struct mlx5e_rq *rq)
switch (am->state) {
case MLX5E_AM_MEASURE_IN_PROGRESS:
- nevents = rq->cq.event_ctr - am->start_sample.event_ctr;
+ nevents = BIT_GAP(BITS_PER_TYPE(u16), rq->cq.event_ctr,
+ am->start_sample.event_ctr);
if (nevents < MLX5E_AM_NEVENTS)
break;
mlx5e_am_sample(rq, &end_sample);
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_stats.h b/drivers/net/ethernet/mellanox/mlx5/core/en_stats.h
index 53e4992d6511..f81c3aa60b46 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en_stats.h
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en_stats.h
@@ -417,20 +417,13 @@ struct mlx5e_stats {
};
static const struct counter_desc mlx5e_pme_status_desc[] = {
- { "module_plug", 0 },
{ "module_unplug", 8 },
};
static const struct counter_desc mlx5e_pme_error_desc[] = {
- { "module_pwr_budget_exd", 0 }, /* power budget exceed */
- { "module_long_range", 8 }, /* long range for non MLNX cable */
- { "module_bus_stuck", 16 }, /* bus stuck (I2C or data shorted) */
- { "module_no_eeprom", 24 }, /* no eeprom/retry time out */
- { "module_enforce_part", 32 }, /* enforce part number list */
- { "module_unknown_id", 40 }, /* unknown identifier */
- { "module_high_temp", 48 }, /* high temperature */
+ { "module_bus_stuck", 16 }, /* bus stuck (I2C or data shorted) */
+ { "module_high_temp", 48 }, /* high temperature */
{ "module_bad_shorted", 56 }, /* bad or shorted cable/module */
- { "module_unknown_status", 64 },
};
#endif /* __MLX5_EN_STATS_H__ */
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c b/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c
index 11c27e4fadf6..9df9fc0d26f5 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c
@@ -43,6 +43,7 @@
#include <net/tc_act/tc_vlan.h>
#include <net/tc_act/tc_tunnel_key.h>
#include <net/tc_act/tc_pedit.h>
+#include <net/tc_act/tc_csum.h>
#include <net/vxlan.h>
#include <net/arp.h>
#include "en.h"
@@ -384,7 +385,7 @@ static void mlx5e_detach_encap(struct mlx5e_priv *priv,
if (e->flags & MLX5_ENCAP_ENTRY_VALID)
mlx5_encap_dealloc(priv->mdev, e->encap_id);
- hlist_del_rcu(&e->encap_hlist);
+ hash_del_rcu(&e->encap_hlist);
kfree(e->encap_header);
kfree(e);
}
@@ -894,7 +895,6 @@ static struct mlx5_fields fields[] = {
{MLX5_ACTION_IN_FIELD_OUT_SMAC_15_0, 2, offsetof(struct pedit_headers, eth.h_source[4])},
{MLX5_ACTION_IN_FIELD_OUT_ETHERTYPE, 2, offsetof(struct pedit_headers, eth.h_proto)},
- {MLX5_ACTION_IN_FIELD_OUT_IP_DSCP, 1, offsetof(struct pedit_headers, ip4.tos)},
{MLX5_ACTION_IN_FIELD_OUT_IP_TTL, 1, offsetof(struct pedit_headers, ip4.ttl)},
{MLX5_ACTION_IN_FIELD_OUT_SIPV4, 4, offsetof(struct pedit_headers, ip4.saddr)},
{MLX5_ACTION_IN_FIELD_OUT_DIPV4, 4, offsetof(struct pedit_headers, ip4.daddr)},
@@ -925,11 +925,11 @@ static int offload_pedit_fields(struct pedit_headers *masks,
struct mlx5e_tc_flow_parse_attr *parse_attr)
{
struct pedit_headers *set_masks, *add_masks, *set_vals, *add_vals;
- int i, action_size, nactions, max_actions, first, last;
+ int i, action_size, nactions, max_actions, first, last, first_z;
void *s_masks_p, *a_masks_p, *vals_p;
- u32 s_mask, a_mask, val;
struct mlx5_fields *f;
u8 cmd, field_bsize;
+ u32 s_mask, a_mask;
unsigned long mask;
void *action;
@@ -946,7 +946,8 @@ static int offload_pedit_fields(struct pedit_headers *masks,
for (i = 0; i < ARRAY_SIZE(fields); i++) {
f = &fields[i];
/* avoid seeing bits set from previous iterations */
- s_mask = a_mask = mask = val = 0;
+ s_mask = 0;
+ a_mask = 0;
s_masks_p = (void *)set_masks + f->offset;
a_masks_p = (void *)add_masks + f->offset;
@@ -981,12 +982,12 @@ static int offload_pedit_fields(struct pedit_headers *masks,
memset(a_masks_p, 0, f->size);
}
- memcpy(&val, vals_p, f->size);
-
field_bsize = f->size * BITS_PER_BYTE;
+
+ first_z = find_first_zero_bit(&mask, field_bsize);
first = find_first_bit(&mask, field_bsize);
last = find_last_bit(&mask, field_bsize);
- if (first > 0 || last != (field_bsize - 1)) {
+ if (first > 0 || last != (field_bsize - 1) || first_z < last) {
printk(KERN_WARNING "mlx5: partial rewrite (mask %lx) is currently not offloaded\n",
mask);
return -EOPNOTSUPP;
@@ -1002,11 +1003,11 @@ static int offload_pedit_fields(struct pedit_headers *masks,
}
if (field_bsize == 32)
- MLX5_SET(set_action_in, action, data, ntohl(val));
+ MLX5_SET(set_action_in, action, data, ntohl(*(__be32 *)vals_p));
else if (field_bsize == 16)
- MLX5_SET(set_action_in, action, data, ntohs(val));
+ MLX5_SET(set_action_in, action, data, ntohs(*(__be16 *)vals_p));
else if (field_bsize == 8)
- MLX5_SET(set_action_in, action, data, val);
+ MLX5_SET(set_action_in, action, data, *(u8 *)vals_p);
action += action_size;
nactions++;
@@ -1109,6 +1110,28 @@ out_err:
return err;
}
+static bool csum_offload_supported(struct mlx5e_priv *priv, u32 action, u32 update_flags)
+{
+ u32 prot_flags = TCA_CSUM_UPDATE_FLAG_IPV4HDR | TCA_CSUM_UPDATE_FLAG_TCP |
+ TCA_CSUM_UPDATE_FLAG_UDP;
+
+ /* The HW recalcs checksums only if re-writing headers */
+ if (!(action & MLX5_FLOW_CONTEXT_ACTION_MOD_HDR)) {
+ netdev_warn(priv->netdev,
+ "TC csum action is only offloaded with pedit\n");
+ return false;
+ }
+
+ if (update_flags & ~prot_flags) {
+ netdev_warn(priv->netdev,
+ "can't offload TC csum action for some header/s - flags %#x\n",
+ update_flags);
+ return false;
+ }
+
+ return true;
+}
+
static int parse_tc_nic_actions(struct mlx5e_priv *priv, struct tcf_exts *exts,
struct mlx5e_tc_flow_parse_attr *parse_attr,
struct mlx5e_tc_flow *flow)
@@ -1149,6 +1172,14 @@ static int parse_tc_nic_actions(struct mlx5e_priv *priv, struct tcf_exts *exts,
continue;
}
+ if (is_tcf_csum(a)) {
+ if (csum_offload_supported(priv, attr->action,
+ tcf_csum_update_flags(a)))
+ continue;
+
+ return -EOPNOTSUPP;
+ }
+
if (is_tcf_skbedit_mark(a)) {
u32 mark = tcf_skbedit_mark(a);
@@ -1651,6 +1682,14 @@ static int parse_tc_fdb_actions(struct mlx5e_priv *priv, struct tcf_exts *exts,
continue;
}
+ if (is_tcf_csum(a)) {
+ if (csum_offload_supported(priv, attr->action,
+ tcf_csum_update_flags(a)))
+ continue;
+
+ return -EOPNOTSUPP;
+ }
+
if (is_tcf_mirred_egress_redirect(a)) {
int ifindex = tcf_mirred_ifindex(a);
struct net_device *out_dev, *encap_dev = NULL;
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/eq.c b/drivers/net/ethernet/mellanox/mlx5/core/eq.c
index ea5d8d37a75c..33eae5ad2fb0 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/eq.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/eq.c
@@ -422,7 +422,7 @@ static irqreturn_t mlx5_eq_int(int irq, void *eq_ptr)
break;
case MLX5_EVENT_TYPE_CMD:
- mlx5_cmd_comp_handler(dev, be32_to_cpu(eqe->data.cmd.vector));
+ mlx5_cmd_comp_handler(dev, be32_to_cpu(eqe->data.cmd.vector), false);
break;
case MLX5_EVENT_TYPE_PORT_CHANGE:
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c b/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c
index f991f669047e..a53e982a6863 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c
@@ -906,21 +906,34 @@ static int esw_inline_mode_to_devlink(u8 mlx5_mode, u8 *mode)
return 0;
}
-int mlx5_devlink_eswitch_mode_set(struct devlink *devlink, u16 mode)
+static int mlx5_devlink_eswitch_check(struct devlink *devlink)
{
- struct mlx5_core_dev *dev;
- u16 cur_mlx5_mode, mlx5_mode = 0;
+ struct mlx5_core_dev *dev = devlink_priv(devlink);
- dev = devlink_priv(devlink);
+ if (MLX5_CAP_GEN(dev, port_type) != MLX5_CAP_PORT_TYPE_ETH)
+ return -EOPNOTSUPP;
if (!MLX5_CAP_GEN(dev, vport_group_manager))
return -EOPNOTSUPP;
- cur_mlx5_mode = dev->priv.eswitch->mode;
-
- if (cur_mlx5_mode == SRIOV_NONE)
+ if (dev->priv.eswitch->mode == SRIOV_NONE)
return -EOPNOTSUPP;
+ return 0;
+}
+
+int mlx5_devlink_eswitch_mode_set(struct devlink *devlink, u16 mode)
+{
+ struct mlx5_core_dev *dev = devlink_priv(devlink);
+ u16 cur_mlx5_mode, mlx5_mode = 0;
+ int err;
+
+ err = mlx5_devlink_eswitch_check(devlink);
+ if (err)
+ return err;
+
+ cur_mlx5_mode = dev->priv.eswitch->mode;
+
if (esw_mode_from_devlink(mode, &mlx5_mode))
return -EINVAL;
@@ -937,15 +950,12 @@ int mlx5_devlink_eswitch_mode_set(struct devlink *devlink, u16 mode)
int mlx5_devlink_eswitch_mode_get(struct devlink *devlink, u16 *mode)
{
- struct mlx5_core_dev *dev;
-
- dev = devlink_priv(devlink);
-
- if (!MLX5_CAP_GEN(dev, vport_group_manager))
- return -EOPNOTSUPP;
+ struct mlx5_core_dev *dev = devlink_priv(devlink);
+ int err;
- if (dev->priv.eswitch->mode == SRIOV_NONE)
- return -EOPNOTSUPP;
+ err = mlx5_devlink_eswitch_check(devlink);
+ if (err)
+ return err;
return esw_mode_to_devlink(dev->priv.eswitch->mode, mode);
}
@@ -954,15 +964,12 @@ int mlx5_devlink_eswitch_inline_mode_set(struct devlink *devlink, u8 mode)
{
struct mlx5_core_dev *dev = devlink_priv(devlink);
struct mlx5_eswitch *esw = dev->priv.eswitch;
- int num_vports = esw->enabled_vports;
int err, vport;
u8 mlx5_mode;
- if (!MLX5_CAP_GEN(dev, vport_group_manager))
- return -EOPNOTSUPP;
-
- if (esw->mode == SRIOV_NONE)
- return -EOPNOTSUPP;
+ err = mlx5_devlink_eswitch_check(devlink);
+ if (err)
+ return err;
switch (MLX5_CAP_ETH(dev, wqe_inline_mode)) {
case MLX5_CAP_INLINE_MODE_NOT_REQUIRED:
@@ -985,7 +992,7 @@ int mlx5_devlink_eswitch_inline_mode_set(struct devlink *devlink, u8 mode)
if (err)
goto out;
- for (vport = 1; vport < num_vports; vport++) {
+ for (vport = 1; vport < esw->enabled_vports; vport++) {
err = mlx5_modify_nic_vport_min_inline(dev, vport, mlx5_mode);
if (err) {
esw_warn(dev, "Failed to set min inline on vport %d\n",
@@ -1010,12 +1017,11 @@ int mlx5_devlink_eswitch_inline_mode_get(struct devlink *devlink, u8 *mode)
{
struct mlx5_core_dev *dev = devlink_priv(devlink);
struct mlx5_eswitch *esw = dev->priv.eswitch;
+ int err;
- if (!MLX5_CAP_GEN(dev, vport_group_manager))
- return -EOPNOTSUPP;
-
- if (esw->mode == SRIOV_NONE)
- return -EOPNOTSUPP;
+ err = mlx5_devlink_eswitch_check(devlink);
+ if (err)
+ return err;
return esw_inline_mode_to_devlink(esw->offloads.inline_mode, mode);
}
@@ -1062,11 +1068,9 @@ int mlx5_devlink_eswitch_encap_mode_set(struct devlink *devlink, u8 encap)
struct mlx5_eswitch *esw = dev->priv.eswitch;
int err;
- if (!MLX5_CAP_GEN(dev, vport_group_manager))
- return -EOPNOTSUPP;
-
- if (esw->mode == SRIOV_NONE)
- return -EOPNOTSUPP;
+ err = mlx5_devlink_eswitch_check(devlink);
+ if (err)
+ return err;
if (encap != DEVLINK_ESWITCH_ENCAP_MODE_NONE &&
(!MLX5_CAP_ESW_FLOWTABLE_FDB(dev, encap) ||
@@ -1105,12 +1109,11 @@ int mlx5_devlink_eswitch_encap_mode_get(struct devlink *devlink, u8 *encap)
{
struct mlx5_core_dev *dev = devlink_priv(devlink);
struct mlx5_eswitch *esw = dev->priv.eswitch;
+ int err;
- if (!MLX5_CAP_GEN(dev, vport_group_manager))
- return -EOPNOTSUPP;
-
- if (esw->mode == SRIOV_NONE)
- return -EOPNOTSUPP;
+ err = mlx5_devlink_eswitch_check(devlink);
+ if (err)
+ return err;
*encap = esw->offloads.encap;
return 0;
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/fs_core.c b/drivers/net/ethernet/mellanox/mlx5/core/fs_core.c
index 0e487e8ca634..8f5125ccd8d4 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/fs_core.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/fs_core.c
@@ -862,7 +862,7 @@ struct mlx5_flow_table *mlx5_create_vport_flow_table(struct mlx5_flow_namespace
ft_attr.level = level;
ft_attr.prio = prio;
- return __mlx5_create_flow_table(ns, &ft_attr, FS_FT_OP_MOD_NORMAL, 0);
+ return __mlx5_create_flow_table(ns, &ft_attr, FS_FT_OP_MOD_NORMAL, vport);
}
struct mlx5_flow_table*
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/health.c b/drivers/net/ethernet/mellanox/mlx5/core/health.c
index d0515391d33b..f27f84ffbc85 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/health.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/health.c
@@ -90,7 +90,7 @@ static void trigger_cmd_completions(struct mlx5_core_dev *dev)
spin_unlock_irqrestore(&dev->cmd.alloc_lock, flags);
mlx5_core_dbg(dev, "vector 0x%llx\n", vector);
- mlx5_cmd_comp_handler(dev, vector);
+ mlx5_cmd_comp_handler(dev, vector, true);
return;
no_trig:
@@ -275,10 +275,8 @@ static void poll_health(unsigned long data)
struct mlx5_core_health *health = &dev->priv.health;
u32 count;
- if (dev->state == MLX5_DEVICE_STATE_INTERNAL_ERROR) {
- mod_timer(&health->timer, get_next_poll_jiffies());
- return;
- }
+ if (dev->state == MLX5_DEVICE_STATE_INTERNAL_ERROR)
+ goto out;
count = ioread32be(health->health_counter);
if (count == health->prev)
@@ -290,8 +288,6 @@ static void poll_health(unsigned long data)
if (health->miss_counter == MAX_MISSES) {
dev_err(&dev->pdev->dev, "device's health compromised - reached miss count\n");
print_health_info(dev);
- } else {
- mod_timer(&health->timer, get_next_poll_jiffies());
}
if (in_fatal(dev) && !health->sick) {
@@ -305,6 +301,9 @@ static void poll_health(unsigned long data)
"new health works are not permitted at this stage\n");
spin_unlock(&health->wq_lock);
}
+
+out:
+ mod_timer(&health->timer, get_next_poll_jiffies());
}
void mlx5_start_health_poll(struct mlx5_core_dev *dev)
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/main.c b/drivers/net/ethernet/mellanox/mlx5/core/main.c
index 0c123d571b4c..13be264587f1 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/main.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/main.c
@@ -175,8 +175,9 @@ static struct mlx5_profile profile[] = {
},
};
-#define FW_INIT_TIMEOUT_MILI 2000
-#define FW_INIT_WAIT_MS 2
+#define FW_INIT_TIMEOUT_MILI 2000
+#define FW_INIT_WAIT_MS 2
+#define FW_PRE_INIT_TIMEOUT_MILI 10000
static int wait_fw_init(struct mlx5_core_dev *dev, u32 max_wait_mili)
{
@@ -537,8 +538,10 @@ static int handle_hca_cap(struct mlx5_core_dev *dev)
/* disable cmdif checksum */
MLX5_SET(cmd_hca_cap, set_hca_cap, cmdif_checksum, 0);
- /* If the HCA supports 4K UARs use it */
- if (MLX5_CAP_GEN_MAX(dev, uar_4k))
+ /* Enable 4K UAR only when HCA supports it and page size is bigger
+ * than 4K.
+ */
+ if (MLX5_CAP_GEN_MAX(dev, uar_4k) && PAGE_SIZE > 4096)
MLX5_SET(cmd_hca_cap, set_hca_cap, uar_4k, 1);
MLX5_SET(cmd_hca_cap, set_hca_cap, log_uar_page_sz, PAGE_SHIFT - 12);
@@ -612,7 +615,6 @@ static int mlx5_irq_set_affinity_hint(struct mlx5_core_dev *mdev, int i)
struct mlx5_priv *priv = &mdev->priv;
struct msix_entry *msix = priv->msix_arr;
int irq = msix[i + MLX5_EQ_VEC_COMP_BASE].vector;
- int err;
if (!zalloc_cpumask_var(&priv->irq_info[i].mask, GFP_KERNEL)) {
mlx5_core_warn(mdev, "zalloc_cpumask_var failed");
@@ -622,18 +624,11 @@ static int mlx5_irq_set_affinity_hint(struct mlx5_core_dev *mdev, int i)
cpumask_set_cpu(cpumask_local_spread(i, priv->numa_node),
priv->irq_info[i].mask);
- err = irq_set_affinity_hint(irq, priv->irq_info[i].mask);
- if (err) {
- mlx5_core_warn(mdev, "irq_set_affinity_hint failed,irq 0x%.4x",
- irq);
- goto err_clear_mask;
- }
+ if (IS_ENABLED(CONFIG_SMP) &&
+ irq_set_affinity_hint(irq, priv->irq_info[i].mask))
+ mlx5_core_warn(mdev, "irq_set_affinity_hint failed, irq 0x%.4x", irq);
return 0;
-
-err_clear_mask:
- free_cpumask_var(priv->irq_info[i].mask);
- return err;
}
static void mlx5_irq_clear_affinity_hint(struct mlx5_core_dev *mdev, int i)
@@ -1019,6 +1014,15 @@ static int mlx5_load_one(struct mlx5_core_dev *dev, struct mlx5_priv *priv,
*/
dev->state = MLX5_DEVICE_STATE_UP;
+ /* wait for firmware to accept initialization segments configurations
+ */
+ err = wait_fw_init(dev, FW_PRE_INIT_TIMEOUT_MILI);
+ if (err) {
+ dev_err(&dev->pdev->dev, "Firmware over %d MS in pre-initializing state, aborting\n",
+ FW_PRE_INIT_TIMEOUT_MILI);
+ goto out;
+ }
+
err = mlx5_cmd_init(dev);
if (err) {
dev_err(&pdev->dev, "Failed initializing command interface, aborting\n");
diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c
index 9f89c4137d21..0744452a0b18 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c
+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c
@@ -3334,6 +3334,9 @@ static int mlxsw_sp_inetaddr_vlan_event(struct net_device *vlan_dev,
struct mlxsw_sp *mlxsw_sp = mlxsw_sp_lower_get(vlan_dev);
u16 vid = vlan_dev_vlan_id(vlan_dev);
+ if (netif_is_bridge_port(vlan_dev))
+ return 0;
+
if (mlxsw_sp_port_dev_check(real_dev))
return mlxsw_sp_inetaddr_vport_event(vlan_dev, real_dev, event,
vid);
diff --git a/drivers/net/ethernet/qlogic/qed/qed_debug.c b/drivers/net/ethernet/qlogic/qed/qed_debug.c
index 483241b4b05d..a672f6a860dc 100644
--- a/drivers/net/ethernet/qlogic/qed/qed_debug.c
+++ b/drivers/net/ethernet/qlogic/qed/qed_debug.c
@@ -2956,7 +2956,7 @@ static u32 qed_grc_dump_ctx_data(struct qed_hwfn *p_hwfn,
qed_wr(p_hwfn,
p_ptt,
s_storm_defs[storm_id].cm_ctx_wr_addr,
- BIT(9) | lid);
+ (i << 9) | lid);
*(dump_buf + offset) = qed_rd(p_hwfn,
p_ptt,
rd_reg_addr);
diff --git a/drivers/net/ethernet/qlogic/qed/qed_main.c b/drivers/net/ethernet/qlogic/qed/qed_main.c
index 537d1236a4fe..715b3aaf83ac 100644
--- a/drivers/net/ethernet/qlogic/qed/qed_main.c
+++ b/drivers/net/ethernet/qlogic/qed/qed_main.c
@@ -1730,7 +1730,8 @@ void qed_get_protocol_stats(struct qed_dev *cdev,
qed_get_protocol_stats_iscsi(cdev, &stats->iscsi_stats);
break;
default:
- DP_ERR(cdev, "Invalid protocol type = %d\n", type);
+ DP_VERBOSE(cdev, QED_MSG_SP,
+ "Invalid protocol type = %d\n", type);
return;
}
}
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic.h b/drivers/net/ethernet/qlogic/qlcnic/qlcnic.h
index 7245b1072518..81312924df14 100644
--- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic.h
+++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic.h
@@ -1824,22 +1824,44 @@ struct qlcnic_hardware_ops {
u32 (*get_cap_size)(void *, int);
void (*set_sys_info)(void *, int, u32);
void (*store_cap_mask)(void *, u32);
+ bool (*encap_rx_offload) (struct qlcnic_adapter *adapter);
+ bool (*encap_tx_offload) (struct qlcnic_adapter *adapter);
};
extern struct qlcnic_nic_template qlcnic_vf_ops;
-static inline bool qlcnic_encap_tx_offload(struct qlcnic_adapter *adapter)
+static inline bool qlcnic_83xx_encap_tx_offload(struct qlcnic_adapter *adapter)
{
return adapter->ahw->extra_capability[0] &
QLCNIC_83XX_FW_CAPAB_ENCAP_TX_OFFLOAD;
}
-static inline bool qlcnic_encap_rx_offload(struct qlcnic_adapter *adapter)
+static inline bool qlcnic_83xx_encap_rx_offload(struct qlcnic_adapter *adapter)
{
return adapter->ahw->extra_capability[0] &
QLCNIC_83XX_FW_CAPAB_ENCAP_RX_OFFLOAD;
}
+static inline bool qlcnic_82xx_encap_tx_offload(struct qlcnic_adapter *adapter)
+{
+ return false;
+}
+
+static inline bool qlcnic_82xx_encap_rx_offload(struct qlcnic_adapter *adapter)
+{
+ return false;
+}
+
+static inline bool qlcnic_encap_rx_offload(struct qlcnic_adapter *adapter)
+{
+ return adapter->ahw->hw_ops->encap_rx_offload(adapter);
+}
+
+static inline bool qlcnic_encap_tx_offload(struct qlcnic_adapter *adapter)
+{
+ return adapter->ahw->hw_ops->encap_tx_offload(adapter);
+}
+
static inline int qlcnic_start_firmware(struct qlcnic_adapter *adapter)
{
return adapter->nic_ops->start_firmware(adapter);
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.c
index 4fb68797630e..f7080d0ab874 100644
--- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.c
+++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.c
@@ -242,6 +242,8 @@ static struct qlcnic_hardware_ops qlcnic_83xx_hw_ops = {
.get_cap_size = qlcnic_83xx_get_cap_size,
.set_sys_info = qlcnic_83xx_set_sys_info,
.store_cap_mask = qlcnic_83xx_store_cap_mask,
+ .encap_rx_offload = qlcnic_83xx_encap_rx_offload,
+ .encap_tx_offload = qlcnic_83xx_encap_tx_offload,
};
static struct qlcnic_nic_template qlcnic_83xx_ops = {
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_hw.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_hw.c
index 838cc0ceafd8..7848cf04b29a 100644
--- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_hw.c
+++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_hw.c
@@ -341,7 +341,7 @@ qlcnic_pcie_sem_lock(struct qlcnic_adapter *adapter, int sem, u32 id_reg)
}
return -EIO;
}
- usleep_range(1000, 1500);
+ udelay(1200);
}
if (id_reg)
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c
index b6628aaa6e4a..1b5f7d57b6f8 100644
--- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c
+++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c
@@ -632,6 +632,8 @@ static struct qlcnic_hardware_ops qlcnic_hw_ops = {
.get_cap_size = qlcnic_82xx_get_cap_size,
.set_sys_info = qlcnic_82xx_set_sys_info,
.store_cap_mask = qlcnic_82xx_store_cap_mask,
+ .encap_rx_offload = qlcnic_82xx_encap_rx_offload,
+ .encap_tx_offload = qlcnic_82xx_encap_tx_offload,
};
static int qlcnic_check_multi_tx_capability(struct qlcnic_adapter *adapter)
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_sriov_common.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_sriov_common.c
index 2f656f395f39..c58180f40844 100644
--- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_sriov_common.c
+++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_sriov_common.c
@@ -77,6 +77,8 @@ static struct qlcnic_hardware_ops qlcnic_sriov_vf_hw_ops = {
.free_mac_list = qlcnic_sriov_vf_free_mac_list,
.enable_sds_intr = qlcnic_83xx_enable_sds_intr,
.disable_sds_intr = qlcnic_83xx_disable_sds_intr,
+ .encap_rx_offload = qlcnic_83xx_encap_rx_offload,
+ .encap_tx_offload = qlcnic_83xx_encap_tx_offload,
};
static struct qlcnic_nic_template qlcnic_sriov_vf_ops = {
diff --git a/drivers/net/ethernet/qualcomm/emac/emac-mac.c b/drivers/net/ethernet/qualcomm/emac/emac-mac.c
index cc065ffbe4b5..bcd4708b3745 100644
--- a/drivers/net/ethernet/qualcomm/emac/emac-mac.c
+++ b/drivers/net/ethernet/qualcomm/emac/emac-mac.c
@@ -931,7 +931,7 @@ int emac_mac_up(struct emac_adapter *adpt)
emac_mac_config(adpt);
emac_mac_rx_descs_refill(adpt, &adpt->rx_q);
- adpt->phydev->irq = PHY_IGNORE_INTERRUPT;
+ adpt->phydev->irq = PHY_POLL;
ret = phy_connect_direct(netdev, adpt->phydev, emac_adjust_link,
PHY_INTERFACE_MODE_SGMII);
if (ret) {
diff --git a/drivers/net/ethernet/qualcomm/emac/emac-phy.c b/drivers/net/ethernet/qualcomm/emac/emac-phy.c
index 441c19366489..18461fcb9815 100644
--- a/drivers/net/ethernet/qualcomm/emac/emac-phy.c
+++ b/drivers/net/ethernet/qualcomm/emac/emac-phy.c
@@ -13,15 +13,11 @@
/* Qualcomm Technologies, Inc. EMAC PHY Controller driver.
*/
-#include <linux/module.h>
-#include <linux/of.h>
-#include <linux/of_net.h>
#include <linux/of_mdio.h>
#include <linux/phy.h>
#include <linux/iopoll.h>
#include <linux/acpi.h>
#include "emac.h"
-#include "emac-mac.h"
/* EMAC base register offsets */
#define EMAC_MDIO_CTRL 0x001414
@@ -52,62 +48,10 @@
#define MDIO_WAIT_TIMES 1000
-#define EMAC_LINK_SPEED_DEFAULT (\
- EMAC_LINK_SPEED_10_HALF |\
- EMAC_LINK_SPEED_10_FULL |\
- EMAC_LINK_SPEED_100_HALF |\
- EMAC_LINK_SPEED_100_FULL |\
- EMAC_LINK_SPEED_1GB_FULL)
-
-/**
- * emac_phy_mdio_autopoll_disable() - disable mdio autopoll
- * @adpt: the emac adapter
- *
- * The autopoll feature takes over the MDIO bus. In order for
- * the PHY driver to be able to talk to the PHY over the MDIO
- * bus, we need to temporarily disable the autopoll feature.
- */
-static int emac_phy_mdio_autopoll_disable(struct emac_adapter *adpt)
-{
- u32 val;
-
- /* disable autopoll */
- emac_reg_update32(adpt->base + EMAC_MDIO_CTRL, MDIO_AP_EN, 0);
-
- /* wait for any mdio polling to complete */
- if (!readl_poll_timeout(adpt->base + EMAC_MDIO_CTRL, val,
- !(val & MDIO_BUSY), 100, MDIO_WAIT_TIMES * 100))
- return 0;
-
- /* failed to disable; ensure it is enabled before returning */
- emac_reg_update32(adpt->base + EMAC_MDIO_CTRL, 0, MDIO_AP_EN);
-
- return -EBUSY;
-}
-
-/**
- * emac_phy_mdio_autopoll_disable() - disable mdio autopoll
- * @adpt: the emac adapter
- *
- * The EMAC has the ability to poll the external PHY on the MDIO
- * bus for link state changes. This eliminates the need for the
- * driver to poll the phy. If if the link state does change,
- * the EMAC issues an interrupt on behalf of the PHY.
- */
-static void emac_phy_mdio_autopoll_enable(struct emac_adapter *adpt)
-{
- emac_reg_update32(adpt->base + EMAC_MDIO_CTRL, 0, MDIO_AP_EN);
-}
-
static int emac_mdio_read(struct mii_bus *bus, int addr, int regnum)
{
struct emac_adapter *adpt = bus->priv;
u32 reg;
- int ret;
-
- ret = emac_phy_mdio_autopoll_disable(adpt);
- if (ret)
- return ret;
emac_reg_update32(adpt->base + EMAC_PHY_STS, PHY_ADDR_BMSK,
(addr << PHY_ADDR_SHFT));
@@ -122,24 +66,15 @@ static int emac_mdio_read(struct mii_bus *bus, int addr, int regnum)
if (readl_poll_timeout(adpt->base + EMAC_MDIO_CTRL, reg,
!(reg & (MDIO_START | MDIO_BUSY)),
100, MDIO_WAIT_TIMES * 100))
- ret = -EIO;
- else
- ret = (reg >> MDIO_DATA_SHFT) & MDIO_DATA_BMSK;
+ return -EIO;
- emac_phy_mdio_autopoll_enable(adpt);
-
- return ret;
+ return (reg >> MDIO_DATA_SHFT) & MDIO_DATA_BMSK;
}
static int emac_mdio_write(struct mii_bus *bus, int addr, int regnum, u16 val)
{
struct emac_adapter *adpt = bus->priv;
u32 reg;
- int ret;
-
- ret = emac_phy_mdio_autopoll_disable(adpt);
- if (ret)
- return ret;
emac_reg_update32(adpt->base + EMAC_PHY_STS, PHY_ADDR_BMSK,
(addr << PHY_ADDR_SHFT));
@@ -155,11 +90,9 @@ static int emac_mdio_write(struct mii_bus *bus, int addr, int regnum, u16 val)
if (readl_poll_timeout(adpt->base + EMAC_MDIO_CTRL, reg,
!(reg & (MDIO_START | MDIO_BUSY)), 100,
MDIO_WAIT_TIMES * 100))
- ret = -EIO;
+ return -EIO;
- emac_phy_mdio_autopoll_enable(adpt);
-
- return ret;
+ return 0;
}
/* Configure the MDIO bus and connect the external PHY */
diff --git a/drivers/net/ethernet/qualcomm/emac/emac.c b/drivers/net/ethernet/qualcomm/emac/emac.c
index 28a8cdc36485..98a326faea29 100644
--- a/drivers/net/ethernet/qualcomm/emac/emac.c
+++ b/drivers/net/ethernet/qualcomm/emac/emac.c
@@ -50,19 +50,7 @@
#define DMAR_DLY_CNT_DEF 15
#define DMAW_DLY_CNT_DEF 4
-#define IMR_NORMAL_MASK (\
- ISR_ERROR |\
- ISR_GPHY_LINK |\
- ISR_TX_PKT |\
- GPHY_WAKEUP_INT)
-
-#define IMR_EXTENDED_MASK (\
- SW_MAN_INT |\
- ISR_OVER |\
- ISR_ERROR |\
- ISR_GPHY_LINK |\
- ISR_TX_PKT |\
- GPHY_WAKEUP_INT)
+#define IMR_NORMAL_MASK (ISR_ERROR | ISR_OVER | ISR_TX_PKT)
#define ISR_TX_PKT (\
TX_PKT_INT |\
@@ -70,10 +58,6 @@
TX_PKT_INT2 |\
TX_PKT_INT3)
-#define ISR_GPHY_LINK (\
- GPHY_LINK_UP_INT |\
- GPHY_LINK_DOWN_INT)
-
#define ISR_OVER (\
RFD0_UR_INT |\
RFD1_UR_INT |\
@@ -187,10 +171,6 @@ irqreturn_t emac_isr(int _irq, void *data)
if (status & ISR_OVER)
net_warn_ratelimited("warning: TX/RX overflow\n");
- /* link event */
- if (status & ISR_GPHY_LINK)
- phy_mac_interrupt(adpt->phydev, !!(status & GPHY_LINK_UP_INT));
-
exit:
/* enable the interrupt */
writel(irq->mask, adpt->base + EMAC_INT_MASK);
diff --git a/drivers/net/ethernet/renesas/ravb_main.c b/drivers/net/ethernet/renesas/ravb_main.c
index 3cd7989c007d..784782da3a85 100644
--- a/drivers/net/ethernet/renesas/ravb_main.c
+++ b/drivers/net/ethernet/renesas/ravb_main.c
@@ -230,18 +230,6 @@ static void ravb_ring_free(struct net_device *ndev, int q)
int ring_size;
int i;
- /* Free RX skb ringbuffer */
- if (priv->rx_skb[q]) {
- for (i = 0; i < priv->num_rx_ring[q]; i++)
- dev_kfree_skb(priv->rx_skb[q][i]);
- }
- kfree(priv->rx_skb[q]);
- priv->rx_skb[q] = NULL;
-
- /* Free aligned TX buffers */
- kfree(priv->tx_align[q]);
- priv->tx_align[q] = NULL;
-
if (priv->rx_ring[q]) {
for (i = 0; i < priv->num_rx_ring[q]; i++) {
struct ravb_ex_rx_desc *desc = &priv->rx_ring[q][i];
@@ -270,6 +258,18 @@ static void ravb_ring_free(struct net_device *ndev, int q)
priv->tx_ring[q] = NULL;
}
+ /* Free RX skb ringbuffer */
+ if (priv->rx_skb[q]) {
+ for (i = 0; i < priv->num_rx_ring[q]; i++)
+ dev_kfree_skb(priv->rx_skb[q][i]);
+ }
+ kfree(priv->rx_skb[q]);
+ priv->rx_skb[q] = NULL;
+
+ /* Free aligned TX buffers */
+ kfree(priv->tx_align[q]);
+ priv->tx_align[q] = NULL;
+
/* Free TX skb ringbuffer.
* SKBs are freed by ravb_tx_free() call above.
*/
diff --git a/drivers/net/ethernet/rocker/rocker_ofdpa.c b/drivers/net/ethernet/rocker/rocker_ofdpa.c
index 2ae852454780..a9ce82d3e9cf 100644
--- a/drivers/net/ethernet/rocker/rocker_ofdpa.c
+++ b/drivers/net/ethernet/rocker/rocker_ofdpa.c
@@ -1505,8 +1505,8 @@ static int ofdpa_port_ipv4_nh(struct ofdpa_port *ofdpa_port,
*index = entry->index;
resolved = false;
} else if (removing) {
- ofdpa_neigh_del(trans, found);
*index = found->index;
+ ofdpa_neigh_del(trans, found);
} else if (updating) {
ofdpa_neigh_update(found, trans, NULL, false);
resolved = !is_zero_ether_addr(found->eth_dst);
diff --git a/drivers/net/ethernet/sfc/ef10.c b/drivers/net/ethernet/sfc/ef10.c
index 78efb2822b86..78f9e43420e0 100644
--- a/drivers/net/ethernet/sfc/ef10.c
+++ b/drivers/net/ethernet/sfc/ef10.c
@@ -4172,7 +4172,7 @@ found:
* recipients
*/
if (is_mc_recip) {
- MCDI_DECLARE_BUF(inbuf, MC_CMD_FILTER_OP_IN_LEN);
+ MCDI_DECLARE_BUF(inbuf, MC_CMD_FILTER_OP_EXT_IN_LEN);
unsigned int depth, i;
memset(inbuf, 0, sizeof(inbuf));
@@ -4320,7 +4320,7 @@ static int efx_ef10_filter_remove_internal(struct efx_nic *efx,
efx_ef10_filter_set_entry(table, filter_idx, NULL, 0);
} else {
efx_mcdi_display_error(efx, MC_CMD_FILTER_OP,
- MC_CMD_FILTER_OP_IN_LEN,
+ MC_CMD_FILTER_OP_EXT_IN_LEN,
NULL, 0, rc);
}
}
@@ -4453,7 +4453,7 @@ static s32 efx_ef10_filter_rfs_insert(struct efx_nic *efx,
struct efx_filter_spec *spec)
{
struct efx_ef10_filter_table *table = efx->filter_state;
- MCDI_DECLARE_BUF(inbuf, MC_CMD_FILTER_OP_IN_LEN);
+ MCDI_DECLARE_BUF(inbuf, MC_CMD_FILTER_OP_EXT_IN_LEN);
struct efx_filter_spec *saved_spec;
unsigned int hash, i, depth = 1;
bool replacing = false;
@@ -4940,7 +4940,7 @@ not_restored:
static void efx_ef10_filter_table_remove(struct efx_nic *efx)
{
struct efx_ef10_filter_table *table = efx->filter_state;
- MCDI_DECLARE_BUF(inbuf, MC_CMD_FILTER_OP_IN_LEN);
+ MCDI_DECLARE_BUF(inbuf, MC_CMD_FILTER_OP_EXT_IN_LEN);
struct efx_filter_spec *spec;
unsigned int filter_idx;
int rc;
@@ -5105,6 +5105,7 @@ static int efx_ef10_filter_insert_addr_list(struct efx_nic *efx,
/* Insert/renew filters */
for (i = 0; i < addr_count; i++) {
+ EFX_WARN_ON_PARANOID(ids[i] != EFX_EF10_FILTER_ID_INVALID);
efx_filter_init_rx(&spec, EFX_FILTER_PRI_AUTO, filter_flags, 0);
efx_filter_set_eth_local(&spec, vlan->vid, addr_list[i].addr);
rc = efx_ef10_filter_insert(efx, &spec, true);
@@ -5122,11 +5123,11 @@ static int efx_ef10_filter_insert_addr_list(struct efx_nic *efx,
}
return rc;
} else {
- /* mark as not inserted, and carry on */
- rc = EFX_EF10_FILTER_ID_INVALID;
+ /* keep invalid ID, and carry on */
}
+ } else {
+ ids[i] = efx_ef10_filter_get_unsafe_id(rc);
}
- ids[i] = efx_ef10_filter_get_unsafe_id(rc);
}
if (multicast && rollback) {
diff --git a/drivers/net/ethernet/sfc/ef10_sriov.c b/drivers/net/ethernet/sfc/ef10_sriov.c
index b7e4345c990d..019cef1d3cf7 100644
--- a/drivers/net/ethernet/sfc/ef10_sriov.c
+++ b/drivers/net/ethernet/sfc/ef10_sriov.c
@@ -661,8 +661,6 @@ restore_filters:
up_write(&vf->efx->filter_sem);
mutex_unlock(&vf->efx->mac_lock);
- up_write(&vf->efx->filter_sem);
-
rc2 = efx_net_open(vf->efx->net_dev);
if (rc2)
goto reset_nic;
diff --git a/drivers/net/ethernet/stmicro/stmmac/altr_tse_pcs.c b/drivers/net/ethernet/stmicro/stmmac/altr_tse_pcs.c
index 489ef146201e..6a9c954492f2 100644
--- a/drivers/net/ethernet/stmicro/stmmac/altr_tse_pcs.c
+++ b/drivers/net/ethernet/stmicro/stmmac/altr_tse_pcs.c
@@ -37,6 +37,7 @@
#define TSE_PCS_CONTROL_AN_EN_MASK BIT(12)
#define TSE_PCS_CONTROL_REG 0x00
#define TSE_PCS_CONTROL_RESTART_AN_MASK BIT(9)
+#define TSE_PCS_CTRL_AUTONEG_SGMII 0x1140
#define TSE_PCS_IF_MODE_REG 0x28
#define TSE_PCS_LINK_TIMER_0_REG 0x24
#define TSE_PCS_LINK_TIMER_1_REG 0x26
@@ -65,6 +66,7 @@
#define TSE_PCS_SW_RESET_TIMEOUT 100
#define TSE_PCS_USE_SGMII_AN_MASK BIT(1)
#define TSE_PCS_USE_SGMII_ENA BIT(0)
+#define TSE_PCS_IF_USE_SGMII 0x03
#define SGMII_ADAPTER_CTRL_REG 0x00
#define SGMII_ADAPTER_DISABLE 0x0001
@@ -101,7 +103,9 @@ int tse_pcs_init(void __iomem *base, struct tse_pcs *pcs)
{
int ret = 0;
- writew(TSE_PCS_USE_SGMII_ENA, base + TSE_PCS_IF_MODE_REG);
+ writew(TSE_PCS_IF_USE_SGMII, base + TSE_PCS_IF_MODE_REG);
+
+ writew(TSE_PCS_CTRL_AUTONEG_SGMII, base + TSE_PCS_CONTROL_REG);
writew(TSE_PCS_SGMII_LINK_TIMER_0, base + TSE_PCS_LINK_TIMER_0_REG);
writew(TSE_PCS_SGMII_LINK_TIMER_1, base + TSE_PCS_LINK_TIMER_1_REG);
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac4_descs.c b/drivers/net/ethernet/stmicro/stmmac/dwmac4_descs.c
index aa6476439aee..e0ef02f9503b 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac4_descs.c
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac4_descs.c
@@ -214,13 +214,13 @@ static int dwmac4_wrback_get_tx_timestamp_status(struct dma_desc *p)
{
/* Context type from W/B descriptor must be zero */
if (le32_to_cpu(p->des3) & TDES3_CONTEXT_TYPE)
- return -EINVAL;
+ return 0;
/* Tx Timestamp Status is 1 so des0 and des1'll have valid values */
if (le32_to_cpu(p->des3) & TDES3_TIMESTAMP_STATUS)
- return 0;
+ return 1;
- return 1;
+ return 0;
}
static inline u64 dwmac4_get_timestamp(void *desc, u32 ats)
@@ -282,7 +282,10 @@ static int dwmac4_wrback_get_rx_timestamp_status(void *desc, u32 ats)
}
}
exit:
- return ret;
+ if (likely(ret == 0))
+ return 1;
+
+ return 0;
}
static void dwmac4_rd_init_rx_desc(struct dma_desc *p, int disable_rx_ic,
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
index a74c481401c4..6e4cbc6ce0ef 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
@@ -434,14 +434,14 @@ static void stmmac_get_tx_hwtstamp(struct stmmac_priv *priv,
return;
/* check tx tstamp status */
- if (!priv->hw->desc->get_tx_timestamp_status(p)) {
+ if (priv->hw->desc->get_tx_timestamp_status(p)) {
/* get the valid tstamp */
ns = priv->hw->desc->get_timestamp(p, priv->adv_ts);
memset(&shhwtstamp, 0, sizeof(struct skb_shared_hwtstamps));
shhwtstamp.hwtstamp = ns_to_ktime(ns);
- netdev_info(priv->dev, "get valid TX hw timestamp %llu\n", ns);
+ netdev_dbg(priv->dev, "get valid TX hw timestamp %llu\n", ns);
/* pass tstamp to stack */
skb_tstamp_tx(skb, &shhwtstamp);
}
@@ -468,19 +468,19 @@ static void stmmac_get_rx_hwtstamp(struct stmmac_priv *priv, struct dma_desc *p,
return;
/* Check if timestamp is available */
- if (!priv->hw->desc->get_rx_timestamp_status(p, priv->adv_ts)) {
+ if (priv->hw->desc->get_rx_timestamp_status(p, priv->adv_ts)) {
/* For GMAC4, the valid timestamp is from CTX next desc. */
if (priv->plat->has_gmac4)
ns = priv->hw->desc->get_timestamp(np, priv->adv_ts);
else
ns = priv->hw->desc->get_timestamp(p, priv->adv_ts);
- netdev_info(priv->dev, "get valid RX hw timestamp %llu\n", ns);
+ netdev_dbg(priv->dev, "get valid RX hw timestamp %llu\n", ns);
shhwtstamp = skb_hwtstamps(skb);
memset(shhwtstamp, 0, sizeof(struct skb_shared_hwtstamps));
shhwtstamp->hwtstamp = ns_to_ktime(ns);
} else {
- netdev_err(priv->dev, "cannot get RX hw timestamp\n");
+ netdev_dbg(priv->dev, "cannot get RX hw timestamp\n");
}
}
@@ -546,7 +546,10 @@ static int stmmac_hwtstamp_ioctl(struct net_device *dev, struct ifreq *ifr)
/* PTP v1, UDP, any kind of event packet */
config.rx_filter = HWTSTAMP_FILTER_PTP_V1_L4_EVENT;
/* take time stamp for all event messages */
- snap_type_sel = PTP_TCR_SNAPTYPSEL_1;
+ if (priv->plat->has_gmac4)
+ snap_type_sel = PTP_GMAC4_TCR_SNAPTYPSEL_1;
+ else
+ snap_type_sel = PTP_TCR_SNAPTYPSEL_1;
ptp_over_ipv4_udp = PTP_TCR_TSIPV4ENA;
ptp_over_ipv6_udp = PTP_TCR_TSIPV6ENA;
@@ -578,7 +581,10 @@ static int stmmac_hwtstamp_ioctl(struct net_device *dev, struct ifreq *ifr)
config.rx_filter = HWTSTAMP_FILTER_PTP_V2_L4_EVENT;
ptp_v2 = PTP_TCR_TSVER2ENA;
/* take time stamp for all event messages */
- snap_type_sel = PTP_TCR_SNAPTYPSEL_1;
+ if (priv->plat->has_gmac4)
+ snap_type_sel = PTP_GMAC4_TCR_SNAPTYPSEL_1;
+ else
+ snap_type_sel = PTP_TCR_SNAPTYPSEL_1;
ptp_over_ipv4_udp = PTP_TCR_TSIPV4ENA;
ptp_over_ipv6_udp = PTP_TCR_TSIPV6ENA;
@@ -612,7 +618,10 @@ static int stmmac_hwtstamp_ioctl(struct net_device *dev, struct ifreq *ifr)
config.rx_filter = HWTSTAMP_FILTER_PTP_V2_EVENT;
ptp_v2 = PTP_TCR_TSVER2ENA;
/* take time stamp for all event messages */
- snap_type_sel = PTP_TCR_SNAPTYPSEL_1;
+ if (priv->plat->has_gmac4)
+ snap_type_sel = PTP_GMAC4_TCR_SNAPTYPSEL_1;
+ else
+ snap_type_sel = PTP_TCR_SNAPTYPSEL_1;
ptp_over_ipv4_udp = PTP_TCR_TSIPV4ENA;
ptp_over_ipv6_udp = PTP_TCR_TSIPV6ENA;
@@ -1208,7 +1217,7 @@ static int init_dma_rx_desc_rings(struct net_device *dev, gfp_t flags)
u32 rx_count = priv->plat->rx_queues_to_use;
unsigned int bfsize = 0;
int ret = -ENOMEM;
- u32 queue;
+ int queue;
int i;
if (priv->hw->mode->set_16kib_bfsize)
@@ -2724,7 +2733,7 @@ static void stmmac_tso_allocator(struct stmmac_priv *priv, unsigned int des,
priv->hw->desc->prepare_tso_tx_desc(desc, 0, buff_size,
0, 1,
- (last_segment) && (buff_size < TSO_MAX_BUFF_SIZE),
+ (last_segment) && (tmp_len <= TSO_MAX_BUFF_SIZE),
0, 0);
tmp_len -= TSO_MAX_BUFF_SIZE;
@@ -2822,7 +2831,6 @@ static netdev_tx_t stmmac_tso_xmit(struct sk_buff *skb, struct net_device *dev)
tx_q->tx_skbuff_dma[first_entry].buf = des;
tx_q->tx_skbuff_dma[first_entry].len = skb_headlen(skb);
- tx_q->tx_skbuff[first_entry] = skb;
first->des0 = cpu_to_le32(des);
@@ -2856,6 +2864,14 @@ static netdev_tx_t stmmac_tso_xmit(struct sk_buff *skb, struct net_device *dev)
tx_q->tx_skbuff_dma[tx_q->cur_tx].last_segment = true;
+ /* Only the last descriptor gets to point to the skb. */
+ tx_q->tx_skbuff[tx_q->cur_tx] = skb;
+
+ /* We've used all descriptors we need for this skb, however,
+ * advance cur_tx so that it references a fresh descriptor.
+ * ndo_start_xmit will fill this descriptor the next time it's
+ * called and stmmac_tx_clean may clean up to this descriptor.
+ */
tx_q->cur_tx = STMMAC_GET_ENTRY(tx_q->cur_tx, DMA_TX_SIZE);
if (unlikely(stmmac_tx_avail(priv, queue) <= (MAX_SKB_FRAGS + 1))) {
@@ -2947,7 +2963,8 @@ static netdev_tx_t stmmac_xmit(struct sk_buff *skb, struct net_device *dev)
int i, csum_insertion = 0, is_jumbo = 0;
u32 queue = skb_get_queue_mapping(skb);
int nfrags = skb_shinfo(skb)->nr_frags;
- unsigned int entry, first_entry;
+ int entry;
+ unsigned int first_entry;
struct dma_desc *desc, *first;
struct stmmac_tx_queue *tx_q;
unsigned int enh_desc;
@@ -2988,8 +3005,6 @@ static netdev_tx_t stmmac_xmit(struct sk_buff *skb, struct net_device *dev)
first = desc;
- tx_q->tx_skbuff[first_entry] = skb;
-
enh_desc = priv->plat->enh_desc;
/* To program the descriptors according to the size of the frame */
if (enh_desc)
@@ -3037,8 +3052,15 @@ static netdev_tx_t stmmac_xmit(struct sk_buff *skb, struct net_device *dev)
skb->len);
}
- entry = STMMAC_GET_ENTRY(entry, DMA_TX_SIZE);
+ /* Only the last descriptor gets to point to the skb. */
+ tx_q->tx_skbuff[entry] = skb;
+ /* We've used all descriptors we need for this skb, however,
+ * advance cur_tx so that it references a fresh descriptor.
+ * ndo_start_xmit will fill this descriptor the next time it's
+ * called and stmmac_tx_clean may clean up to this descriptor.
+ */
+ entry = STMMAC_GET_ENTRY(entry, DMA_TX_SIZE);
tx_q->cur_tx = entry;
if (netif_msg_pktdata(priv)) {
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_ptp.h b/drivers/net/ethernet/stmicro/stmmac/stmmac_ptp.h
index 48fb72fc423c..f4b31d69f60e 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_ptp.h
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_ptp.h
@@ -59,7 +59,8 @@
/* Enable Snapshot for Messages Relevant to Master */
#define PTP_TCR_TSMSTRENA BIT(15)
/* Select PTP packets for Taking Snapshots */
-#define PTP_TCR_SNAPTYPSEL_1 GENMASK(17, 16)
+#define PTP_TCR_SNAPTYPSEL_1 BIT(16)
+#define PTP_GMAC4_TCR_SNAPTYPSEL_1 GENMASK(17, 16)
/* Enable MAC address for PTP Frame Filtering */
#define PTP_TCR_TSENMACADDR BIT(18)
diff --git a/drivers/net/ethernet/ti/cpsw-common.c b/drivers/net/ethernet/ti/cpsw-common.c
index 1562ab4151e1..56ba411421f0 100644
--- a/drivers/net/ethernet/ti/cpsw-common.c
+++ b/drivers/net/ethernet/ti/cpsw-common.c
@@ -90,7 +90,7 @@ int ti_cm_get_macid(struct device *dev, int slave, u8 *mac_addr)
if (of_device_is_compatible(dev->of_node, "ti,dm816-emac"))
return cpsw_am33xx_cm_get_macid(dev, 0x30, slave, mac_addr);
- if (of_machine_is_compatible("ti,am4372"))
+ if (of_machine_is_compatible("ti,am43"))
return cpsw_am33xx_cm_get_macid(dev, 0x630, slave, mac_addr);
if (of_machine_is_compatible("ti,dra7"))
diff --git a/drivers/net/geneve.c b/drivers/net/geneve.c
index dec5d563ab19..199459bd6961 100644
--- a/drivers/net/geneve.c
+++ b/drivers/net/geneve.c
@@ -1007,7 +1007,7 @@ static void geneve_setup(struct net_device *dev)
dev->netdev_ops = &geneve_netdev_ops;
dev->ethtool_ops = &geneve_ethtool_ops;
- dev->destructor = free_netdev;
+ dev->needs_free_netdev = true;
SET_NETDEV_DEVTYPE(dev, &geneve_type);
@@ -1133,7 +1133,7 @@ static int geneve_configure(struct net *net, struct net_device *dev,
/* make enough headroom for basic scenario */
encap_len = GENEVE_BASE_HLEN + ETH_HLEN;
- if (ip_tunnel_info_af(info) == AF_INET) {
+ if (!metadata && ip_tunnel_info_af(info) == AF_INET) {
encap_len += sizeof(struct iphdr);
dev->max_mtu -= sizeof(struct iphdr);
} else {
@@ -1293,7 +1293,7 @@ static int geneve_fill_info(struct sk_buff *skb, const struct net_device *dev)
if (nla_put_u32(skb, IFLA_GENEVE_ID, vni))
goto nla_put_failure;
- if (ip_tunnel_info_af(info) == AF_INET) {
+ if (rtnl_dereference(geneve->sock4)) {
if (nla_put_in_addr(skb, IFLA_GENEVE_REMOTE,
info->key.u.ipv4.dst))
goto nla_put_failure;
@@ -1302,8 +1302,10 @@ static int geneve_fill_info(struct sk_buff *skb, const struct net_device *dev)
!!(info->key.tun_flags & TUNNEL_CSUM)))
goto nla_put_failure;
+ }
+
#if IS_ENABLED(CONFIG_IPV6)
- } else {
+ if (rtnl_dereference(geneve->sock6)) {
if (nla_put_in6_addr(skb, IFLA_GENEVE_REMOTE6,
&info->key.u.ipv6.dst))
goto nla_put_failure;
@@ -1315,8 +1317,8 @@ static int geneve_fill_info(struct sk_buff *skb, const struct net_device *dev)
if (nla_put_u8(skb, IFLA_GENEVE_UDP_ZERO_CSUM6_RX,
!geneve->use_udp6_rx_checksums))
goto nla_put_failure;
-#endif
}
+#endif
if (nla_put_u8(skb, IFLA_GENEVE_TTL, info->key.ttl) ||
nla_put_u8(skb, IFLA_GENEVE_TOS, info->key.tos) ||
diff --git a/drivers/net/gtp.c b/drivers/net/gtp.c
index 4fea1b3dfbb4..ca110cd2a4e4 100644
--- a/drivers/net/gtp.c
+++ b/drivers/net/gtp.c
@@ -611,7 +611,7 @@ static const struct net_device_ops gtp_netdev_ops = {
static void gtp_link_setup(struct net_device *dev)
{
dev->netdev_ops = &gtp_netdev_ops;
- dev->destructor = free_netdev;
+ dev->needs_free_netdev = true;
dev->hard_header_len = 0;
dev->addr_len = 0;
@@ -873,7 +873,7 @@ static struct gtp_dev *gtp_find_dev(struct net *src_net, struct nlattr *nla[])
/* Check if there's an existing gtpX device to configure */
dev = dev_get_by_index_rcu(net, nla_get_u32(nla[GTPA_LINK]));
- if (dev->netdev_ops == &gtp_netdev_ops)
+ if (dev && dev->netdev_ops == &gtp_netdev_ops)
gtp = netdev_priv(dev);
put_net(net);
diff --git a/drivers/net/hamradio/6pack.c b/drivers/net/hamradio/6pack.c
index 922bf440e9f1..021a8ec411ab 100644
--- a/drivers/net/hamradio/6pack.c
+++ b/drivers/net/hamradio/6pack.c
@@ -311,7 +311,7 @@ static void sp_setup(struct net_device *dev)
{
/* Finish setting up the DEVICE info. */
dev->netdev_ops = &sp_netdev_ops;
- dev->destructor = free_netdev;
+ dev->needs_free_netdev = true;
dev->mtu = SIXP_MTU;
dev->hard_header_len = AX25_MAX_HEADER_LEN;
dev->header_ops = &ax25_header_ops;
diff --git a/drivers/net/hamradio/bpqether.c b/drivers/net/hamradio/bpqether.c
index f62e7f325cf9..78a6414c5fd9 100644
--- a/drivers/net/hamradio/bpqether.c
+++ b/drivers/net/hamradio/bpqether.c
@@ -476,7 +476,7 @@ static const struct net_device_ops bpq_netdev_ops = {
static void bpq_setup(struct net_device *dev)
{
dev->netdev_ops = &bpq_netdev_ops;
- dev->destructor = free_netdev;
+ dev->needs_free_netdev = true;
memcpy(dev->broadcast, &ax25_bcast, AX25_ADDR_LEN);
memcpy(dev->dev_addr, &ax25_defaddr, AX25_ADDR_LEN);
diff --git a/drivers/net/hamradio/hdlcdrv.c b/drivers/net/hamradio/hdlcdrv.c
index 8c3633c1d078..97e3bc60c3e7 100644
--- a/drivers/net/hamradio/hdlcdrv.c
+++ b/drivers/net/hamradio/hdlcdrv.c
@@ -576,6 +576,8 @@ static int hdlcdrv_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
case HDLCDRVCTL_CALIBRATE:
if(!capable(CAP_SYS_RAWIO))
return -EPERM;
+ if (s->par.bitrate <= 0)
+ return -EINVAL;
if (bi.data.calibrate > INT_MAX / s->par.bitrate)
return -EINVAL;
s->hdlctx.calibrate = bi.data.calibrate * s->par.bitrate / 16;
diff --git a/drivers/net/hyperv/hyperv_net.h b/drivers/net/hyperv/hyperv_net.h
index 262b2ea576a3..6066f1bcaf2d 100644
--- a/drivers/net/hyperv/hyperv_net.h
+++ b/drivers/net/hyperv/hyperv_net.h
@@ -171,6 +171,8 @@ struct rndis_device {
spinlock_t request_lock;
struct list_head req_list;
+ struct work_struct mcast_work;
+
u8 hw_mac_adr[ETH_ALEN];
u8 rss_key[NETVSC_HASH_KEYLEN];
u16 ind_table[ITAB_NUM];
@@ -201,6 +203,7 @@ int rndis_filter_open(struct netvsc_device *nvdev);
int rndis_filter_close(struct netvsc_device *nvdev);
int rndis_filter_device_add(struct hv_device *dev,
struct netvsc_device_info *info);
+void rndis_filter_update(struct netvsc_device *nvdev);
void rndis_filter_device_remove(struct hv_device *dev,
struct netvsc_device *nvdev);
int rndis_filter_set_rss_param(struct rndis_device *rdev,
@@ -211,7 +214,6 @@ int rndis_filter_receive(struct net_device *ndev,
struct vmbus_channel *channel,
void *data, u32 buflen);
-int rndis_filter_set_packet_filter(struct rndis_device *dev, u32 new_filter);
int rndis_filter_set_device_mac(struct net_device *ndev, char *mac);
void netvsc_switch_datapath(struct net_device *nv_dev, bool vf);
@@ -696,7 +698,6 @@ struct net_device_context {
/* list protection */
spinlock_t lock;
- struct work_struct work;
u32 msg_enable; /* debug level */
u32 tx_checksum_mask;
diff --git a/drivers/net/hyperv/netvsc_drv.c b/drivers/net/hyperv/netvsc_drv.c
index 4421a6d00375..643c539a08ba 100644
--- a/drivers/net/hyperv/netvsc_drv.c
+++ b/drivers/net/hyperv/netvsc_drv.c
@@ -56,37 +56,12 @@ static int debug = -1;
module_param(debug, int, S_IRUGO);
MODULE_PARM_DESC(debug, "Debug level (0=none,...,16=all)");
-static void do_set_multicast(struct work_struct *w)
-{
- struct net_device_context *ndevctx =
- container_of(w, struct net_device_context, work);
- struct hv_device *device_obj = ndevctx->device_ctx;
- struct net_device *ndev = hv_get_drvdata(device_obj);
- struct netvsc_device *nvdev = rcu_dereference(ndevctx->nvdev);
- struct rndis_device *rdev;
-
- if (!nvdev)
- return;
-
- rdev = nvdev->extension;
- if (rdev == NULL)
- return;
-
- if (ndev->flags & IFF_PROMISC)
- rndis_filter_set_packet_filter(rdev,
- NDIS_PACKET_TYPE_PROMISCUOUS);
- else
- rndis_filter_set_packet_filter(rdev,
- NDIS_PACKET_TYPE_BROADCAST |
- NDIS_PACKET_TYPE_ALL_MULTICAST |
- NDIS_PACKET_TYPE_DIRECTED);
-}
-
static void netvsc_set_multicast_list(struct net_device *net)
{
struct net_device_context *net_device_ctx = netdev_priv(net);
+ struct netvsc_device *nvdev = rtnl_dereference(net_device_ctx->nvdev);
- schedule_work(&net_device_ctx->work);
+ rndis_filter_update(nvdev);
}
static int netvsc_open(struct net_device *net)
@@ -123,8 +98,6 @@ static int netvsc_close(struct net_device *net)
netif_tx_disable(net);
- /* Make sure netvsc_set_multicast_list doesn't re-enable filter! */
- cancel_work_sync(&net_device_ctx->work);
ret = rndis_filter_close(nvdev);
if (ret != 0) {
netdev_err(net, "unable to close device (ret %d).\n", ret);
@@ -803,7 +776,7 @@ static int netvsc_set_channels(struct net_device *net,
channels->rx_count || channels->tx_count || channels->other_count)
return -EINVAL;
- if (count > net->num_tx_queues || count > net->num_rx_queues)
+ if (count > net->num_tx_queues || count > VRSS_CHANNEL_MAX)
return -EINVAL;
if (!nvdev || nvdev->destroy)
@@ -1028,7 +1001,7 @@ static const struct {
static int netvsc_get_sset_count(struct net_device *dev, int string_set)
{
struct net_device_context *ndc = netdev_priv(dev);
- struct netvsc_device *nvdev = rcu_dereference(ndc->nvdev);
+ struct netvsc_device *nvdev = rtnl_dereference(ndc->nvdev);
if (!nvdev)
return -ENODEV;
@@ -1158,11 +1131,22 @@ netvsc_get_rxnfc(struct net_device *dev, struct ethtool_rxnfc *info,
}
#ifdef CONFIG_NET_POLL_CONTROLLER
-static void netvsc_poll_controller(struct net_device *net)
+static void netvsc_poll_controller(struct net_device *dev)
{
- /* As netvsc_start_xmit() works synchronous we don't have to
- * trigger anything here.
- */
+ struct net_device_context *ndc = netdev_priv(dev);
+ struct netvsc_device *ndev;
+ int i;
+
+ rcu_read_lock();
+ ndev = rcu_dereference(ndc->nvdev);
+ if (ndev) {
+ for (i = 0; i < ndev->num_chn; i++) {
+ struct netvsc_channel *nvchan = &ndev->chan_table[i];
+
+ napi_schedule(&nvchan->napi);
+ }
+ }
+ rcu_read_unlock();
}
#endif
@@ -1219,7 +1203,7 @@ static int netvsc_set_rxfh(struct net_device *dev, const u32 *indir,
rndis_dev = ndev->extension;
if (indir) {
for (i = 0; i < ITAB_NUM; i++)
- if (indir[i] >= dev->num_rx_queues)
+ if (indir[i] >= VRSS_CHANNEL_MAX)
return -EINVAL;
for (i = 0; i < ITAB_NUM; i++)
@@ -1552,7 +1536,6 @@ static int netvsc_probe(struct hv_device *dev,
hv_set_drvdata(dev, net);
INIT_DELAYED_WORK(&net_device_ctx->dwork, netvsc_link_change);
- INIT_WORK(&net_device_ctx->work, do_set_multicast);
spin_lock_init(&net_device_ctx->lock);
INIT_LIST_HEAD(&net_device_ctx->reconfig_events);
@@ -1622,7 +1605,6 @@ static int netvsc_remove(struct hv_device *dev)
netif_device_detach(net);
cancel_delayed_work_sync(&ndev_ctx->dwork);
- cancel_work_sync(&ndev_ctx->work);
/*
* Call to the vsc driver to let it know that the device is being
diff --git a/drivers/net/hyperv/rndis_filter.c b/drivers/net/hyperv/rndis_filter.c
index f9d5b0b8209a..cb79cd081f42 100644
--- a/drivers/net/hyperv/rndis_filter.c
+++ b/drivers/net/hyperv/rndis_filter.c
@@ -31,6 +31,7 @@
#include "hyperv_net.h"
+static void rndis_set_multicast(struct work_struct *w);
#define RNDIS_EXT_LEN PAGE_SIZE
struct rndis_request {
@@ -76,6 +77,7 @@ static struct rndis_device *get_rndis_device(void)
spin_lock_init(&device->request_lock);
INIT_LIST_HEAD(&device->req_list);
+ INIT_WORK(&device->mcast_work, rndis_set_multicast);
device->state = RNDIS_DEV_UNINITIALIZED;
@@ -815,7 +817,8 @@ static int rndis_filter_query_link_speed(struct rndis_device *dev)
return ret;
}
-int rndis_filter_set_packet_filter(struct rndis_device *dev, u32 new_filter)
+static int rndis_filter_set_packet_filter(struct rndis_device *dev,
+ u32 new_filter)
{
struct rndis_request *request;
struct rndis_set_request *set;
@@ -846,6 +849,28 @@ int rndis_filter_set_packet_filter(struct rndis_device *dev, u32 new_filter)
return ret;
}
+static void rndis_set_multicast(struct work_struct *w)
+{
+ struct rndis_device *rdev
+ = container_of(w, struct rndis_device, mcast_work);
+
+ if (rdev->ndev->flags & IFF_PROMISC)
+ rndis_filter_set_packet_filter(rdev,
+ NDIS_PACKET_TYPE_PROMISCUOUS);
+ else
+ rndis_filter_set_packet_filter(rdev,
+ NDIS_PACKET_TYPE_BROADCAST |
+ NDIS_PACKET_TYPE_ALL_MULTICAST |
+ NDIS_PACKET_TYPE_DIRECTED);
+}
+
+void rndis_filter_update(struct netvsc_device *nvdev)
+{
+ struct rndis_device *rdev = nvdev->extension;
+
+ schedule_work(&rdev->mcast_work);
+}
+
static int rndis_filter_init_device(struct rndis_device *dev)
{
struct rndis_request *request;
@@ -973,6 +998,9 @@ static int rndis_filter_close_device(struct rndis_device *dev)
if (dev->state != RNDIS_DEV_DATAINITIALIZED)
return 0;
+ /* Make sure rndis_set_multicast doesn't re-enable filter! */
+ cancel_work_sync(&dev->mcast_work);
+
ret = rndis_filter_set_packet_filter(dev, 0);
if (ret == -ENODEV)
ret = 0;
diff --git a/drivers/net/ifb.c b/drivers/net/ifb.c
index 312fce7302d3..144ea5ae8ab4 100644
--- a/drivers/net/ifb.c
+++ b/drivers/net/ifb.c
@@ -207,7 +207,6 @@ static void ifb_dev_free(struct net_device *dev)
__skb_queue_purge(&txp->tq);
}
kfree(dp->tx_private);
- free_netdev(dev);
}
static void ifb_setup(struct net_device *dev)
@@ -230,7 +229,8 @@ static void ifb_setup(struct net_device *dev)
dev->priv_flags &= ~IFF_TX_SKB_SHARING;
netif_keep_dst(dev);
eth_hw_addr_random(dev);
- dev->destructor = ifb_dev_free;
+ dev->needs_free_netdev = true;
+ dev->priv_destructor = ifb_dev_free;
}
static netdev_tx_t ifb_xmit(struct sk_buff *skb, struct net_device *dev)
diff --git a/drivers/net/ipvlan/ipvlan_main.c b/drivers/net/ipvlan/ipvlan_main.c
index 618ed88fad0f..7c7680c8f0e3 100644
--- a/drivers/net/ipvlan/ipvlan_main.c
+++ b/drivers/net/ipvlan/ipvlan_main.c
@@ -632,7 +632,7 @@ void ipvlan_link_setup(struct net_device *dev)
dev->priv_flags &= ~(IFF_XMIT_DST_RELEASE | IFF_TX_SKB_SHARING);
dev->priv_flags |= IFF_UNICAST_FLT | IFF_NO_QUEUE;
dev->netdev_ops = &ipvlan_netdev_ops;
- dev->destructor = free_netdev;
+ dev->needs_free_netdev = true;
dev->header_ops = &ipvlan_header_ops;
dev->ethtool_ops = &ipvlan_ethtool_ops;
}
diff --git a/drivers/net/loopback.c b/drivers/net/loopback.c
index 224f65cb576b..30612497643c 100644
--- a/drivers/net/loopback.c
+++ b/drivers/net/loopback.c
@@ -159,7 +159,6 @@ static void loopback_dev_free(struct net_device *dev)
{
dev_net(dev)->loopback_dev = NULL;
free_percpu(dev->lstats);
- free_netdev(dev);
}
static const struct net_device_ops loopback_ops = {
@@ -196,7 +195,8 @@ static void loopback_setup(struct net_device *dev)
dev->ethtool_ops = &loopback_ethtool_ops;
dev->header_ops = &eth_header_ops;
dev->netdev_ops = &loopback_ops;
- dev->destructor = loopback_dev_free;
+ dev->needs_free_netdev = true;
+ dev->priv_destructor = loopback_dev_free;
}
/* Setup and register the loopback device. */
diff --git a/drivers/net/macsec.c b/drivers/net/macsec.c
index cdc347be68f2..79411675f0e6 100644
--- a/drivers/net/macsec.c
+++ b/drivers/net/macsec.c
@@ -2996,7 +2996,6 @@ static void macsec_free_netdev(struct net_device *dev)
free_percpu(macsec->secy.tx_sc.stats);
dev_put(real_dev);
- free_netdev(dev);
}
static void macsec_setup(struct net_device *dev)
@@ -3006,7 +3005,8 @@ static void macsec_setup(struct net_device *dev)
dev->max_mtu = ETH_MAX_MTU;
dev->priv_flags |= IFF_NO_QUEUE;
dev->netdev_ops = &macsec_netdev_ops;
- dev->destructor = macsec_free_netdev;
+ dev->needs_free_netdev = true;
+ dev->priv_destructor = macsec_free_netdev;
SET_NETDEV_DEVTYPE(dev, &macsec_type);
eth_zero_addr(dev->broadcast);
diff --git a/drivers/net/macvlan.c b/drivers/net/macvlan.c
index 346ad2ff3998..72b801803aa4 100644
--- a/drivers/net/macvlan.c
+++ b/drivers/net/macvlan.c
@@ -39,16 +39,20 @@
#define MACVLAN_HASH_SIZE (1<<MACVLAN_HASH_BITS)
#define MACVLAN_BC_QUEUE_LEN 1000
+#define MACVLAN_F_PASSTHRU 1
+#define MACVLAN_F_ADDRCHANGE 2
+
struct macvlan_port {
struct net_device *dev;
struct hlist_head vlan_hash[MACVLAN_HASH_SIZE];
struct list_head vlans;
struct sk_buff_head bc_queue;
struct work_struct bc_work;
- bool passthru;
+ u32 flags;
int count;
struct hlist_head vlan_source_hash[MACVLAN_HASH_SIZE];
DECLARE_BITMAP(mc_filter, MACVLAN_MC_FILTER_SZ);
+ unsigned char perm_addr[ETH_ALEN];
};
struct macvlan_source_entry {
@@ -66,6 +70,31 @@ struct macvlan_skb_cb {
static void macvlan_port_destroy(struct net_device *dev);
+static inline bool macvlan_passthru(const struct macvlan_port *port)
+{
+ return port->flags & MACVLAN_F_PASSTHRU;
+}
+
+static inline void macvlan_set_passthru(struct macvlan_port *port)
+{
+ port->flags |= MACVLAN_F_PASSTHRU;
+}
+
+static inline bool macvlan_addr_change(const struct macvlan_port *port)
+{
+ return port->flags & MACVLAN_F_ADDRCHANGE;
+}
+
+static inline void macvlan_set_addr_change(struct macvlan_port *port)
+{
+ port->flags |= MACVLAN_F_ADDRCHANGE;
+}
+
+static inline void macvlan_clear_addr_change(struct macvlan_port *port)
+{
+ port->flags &= ~MACVLAN_F_ADDRCHANGE;
+}
+
/* Hash Ethernet address */
static u32 macvlan_eth_hash(const unsigned char *addr)
{
@@ -181,11 +210,12 @@ static void macvlan_hash_change_addr(struct macvlan_dev *vlan,
static bool macvlan_addr_busy(const struct macvlan_port *port,
const unsigned char *addr)
{
- /* Test to see if the specified multicast address is
+ /* Test to see if the specified address is
* currently in use by the underlying device or
* another macvlan.
*/
- if (ether_addr_equal_64bits(port->dev->dev_addr, addr))
+ if (!macvlan_passthru(port) && !macvlan_addr_change(port) &&
+ ether_addr_equal_64bits(port->dev->dev_addr, addr))
return true;
if (macvlan_hash_lookup(port, addr))
@@ -445,7 +475,7 @@ static rx_handler_result_t macvlan_handle_frame(struct sk_buff **pskb)
}
macvlan_forward_source(skb, port, eth->h_source);
- if (port->passthru)
+ if (macvlan_passthru(port))
vlan = list_first_or_null_rcu(&port->vlans,
struct macvlan_dev, list);
else
@@ -574,7 +604,7 @@ static int macvlan_open(struct net_device *dev)
struct net_device *lowerdev = vlan->lowerdev;
int err;
- if (vlan->port->passthru) {
+ if (macvlan_passthru(vlan->port)) {
if (!(vlan->flags & MACVLAN_FLAG_NOPROMISC)) {
err = dev_set_promiscuity(lowerdev, 1);
if (err < 0)
@@ -649,7 +679,7 @@ static int macvlan_stop(struct net_device *dev)
dev_uc_unsync(lowerdev, dev);
dev_mc_unsync(lowerdev, dev);
- if (vlan->port->passthru) {
+ if (macvlan_passthru(vlan->port)) {
if (!(vlan->flags & MACVLAN_FLAG_NOPROMISC))
dev_set_promiscuity(lowerdev, -1);
goto hash_del;
@@ -672,6 +702,7 @@ static int macvlan_sync_address(struct net_device *dev, unsigned char *addr)
{
struct macvlan_dev *vlan = netdev_priv(dev);
struct net_device *lowerdev = vlan->lowerdev;
+ struct macvlan_port *port = vlan->port;
int err;
if (!(dev->flags & IFF_UP)) {
@@ -682,7 +713,7 @@ static int macvlan_sync_address(struct net_device *dev, unsigned char *addr)
if (macvlan_addr_busy(vlan->port, addr))
return -EBUSY;
- if (!vlan->port->passthru) {
+ if (!macvlan_passthru(port)) {
err = dev_uc_add(lowerdev, addr);
if (err)
return err;
@@ -692,6 +723,15 @@ static int macvlan_sync_address(struct net_device *dev, unsigned char *addr)
macvlan_hash_change_addr(vlan, addr);
}
+ if (macvlan_passthru(port) && !macvlan_addr_change(port)) {
+ /* Since addr_change isn't set, we are here due to lower
+ * device change. Save the lower-dev address so we can
+ * restore it later.
+ */
+ ether_addr_copy(vlan->port->perm_addr,
+ lowerdev->dev_addr);
+ }
+ macvlan_clear_addr_change(port);
return 0;
}
@@ -703,7 +743,12 @@ static int macvlan_set_mac_address(struct net_device *dev, void *p)
if (!is_valid_ether_addr(addr->sa_data))
return -EADDRNOTAVAIL;
+ /* If the addresses are the same, this is a no-op */
+ if (ether_addr_equal(dev->dev_addr, addr->sa_data))
+ return 0;
+
if (vlan->mode == MACVLAN_MODE_PASSTHRU) {
+ macvlan_set_addr_change(vlan->port);
dev_set_mac_address(vlan->lowerdev, addr);
return 0;
}
@@ -928,7 +973,7 @@ static int macvlan_fdb_add(struct ndmsg *ndm, struct nlattr *tb[],
/* Support unicast filter only on passthru devices.
* Multicast filter should be allowed on all devices.
*/
- if (!vlan->port->passthru && is_unicast_ether_addr(addr))
+ if (!macvlan_passthru(vlan->port) && is_unicast_ether_addr(addr))
return -EOPNOTSUPP;
if (flags & NLM_F_REPLACE)
@@ -952,7 +997,7 @@ static int macvlan_fdb_del(struct ndmsg *ndm, struct nlattr *tb[],
/* Support unicast filter only on passthru devices.
* Multicast filter should be allowed on all devices.
*/
- if (!vlan->port->passthru && is_unicast_ether_addr(addr))
+ if (!macvlan_passthru(vlan->port) && is_unicast_ether_addr(addr))
return -EOPNOTSUPP;
if (is_unicast_ether_addr(addr))
@@ -1092,7 +1137,7 @@ void macvlan_common_setup(struct net_device *dev)
netif_keep_dst(dev);
dev->priv_flags |= IFF_UNICAST_FLT;
dev->netdev_ops = &macvlan_netdev_ops;
- dev->destructor = free_netdev;
+ dev->needs_free_netdev = true;
dev->header_ops = &macvlan_hard_header_ops;
dev->ethtool_ops = &macvlan_ethtool_ops;
}
@@ -1120,8 +1165,8 @@ static int macvlan_port_create(struct net_device *dev)
if (port == NULL)
return -ENOMEM;
- port->passthru = false;
port->dev = dev;
+ ether_addr_copy(port->perm_addr, dev->dev_addr);
INIT_LIST_HEAD(&port->vlans);
for (i = 0; i < MACVLAN_HASH_SIZE; i++)
INIT_HLIST_HEAD(&port->vlan_hash[i]);
@@ -1161,6 +1206,18 @@ static void macvlan_port_destroy(struct net_device *dev)
kfree_skb(skb);
}
+ /* If the lower device address has been changed by passthru
+ * macvlan, put it back.
+ */
+ if (macvlan_passthru(port) &&
+ !ether_addr_equal(port->dev->dev_addr, port->perm_addr)) {
+ struct sockaddr sa;
+
+ sa.sa_family = port->dev->type;
+ memcpy(&sa.sa_data, port->perm_addr, port->dev->addr_len);
+ dev_set_mac_address(port->dev, &sa);
+ }
+
kfree(port);
}
@@ -1326,7 +1383,7 @@ int macvlan_common_newlink(struct net *src_net, struct net_device *dev,
port = macvlan_port_get_rtnl(lowerdev);
/* Only 1 macvlan device can be created in passthru mode */
- if (port->passthru) {
+ if (macvlan_passthru(port)) {
/* The macvlan port must be not created this time,
* still goto destroy_macvlan_port for readability.
*/
@@ -1352,7 +1409,7 @@ int macvlan_common_newlink(struct net *src_net, struct net_device *dev,
err = -EINVAL;
goto destroy_macvlan_port;
}
- port->passthru = true;
+ macvlan_set_passthru(port);
eth_hw_addr_inherit(dev, lowerdev);
}
@@ -1434,7 +1491,7 @@ static int macvlan_changelink(struct net_device *dev,
if (data && data[IFLA_MACVLAN_FLAGS]) {
__u16 flags = nla_get_u16(data[IFLA_MACVLAN_FLAGS]);
bool promisc = (flags ^ vlan->flags) & MACVLAN_FLAG_NOPROMISC;
- if (vlan->port->passthru && promisc) {
+ if (macvlan_passthru(vlan->port) && promisc) {
int err;
if (flags & MACVLAN_FLAG_NOPROMISC)
@@ -1597,7 +1654,7 @@ static int macvlan_device_event(struct notifier_block *unused,
}
break;
case NETDEV_CHANGEADDR:
- if (!port->passthru)
+ if (!macvlan_passthru(port))
return NOTIFY_DONE;
vlan = list_first_entry_or_null(&port->vlans,
diff --git a/drivers/net/netconsole.c b/drivers/net/netconsole.c
index 06ee6395117f..0e27920c2b6b 100644
--- a/drivers/net/netconsole.c
+++ b/drivers/net/netconsole.c
@@ -358,7 +358,7 @@ static ssize_t enabled_store(struct config_item *item,
if (err)
goto out_unlock;
- pr_info("netconsole: network logging started\n");
+ pr_info("network logging started\n");
} else { /* false */
/* We need to disable the netconsole before cleaning it up
* otherwise we might end up in write_msg() with
diff --git a/drivers/net/nlmon.c b/drivers/net/nlmon.c
index b91603835d26..c4b3362da4a2 100644
--- a/drivers/net/nlmon.c
+++ b/drivers/net/nlmon.c
@@ -113,7 +113,7 @@ static void nlmon_setup(struct net_device *dev)
dev->netdev_ops = &nlmon_ops;
dev->ethtool_ops = &nlmon_ethtool_ops;
- dev->destructor = free_netdev;
+ dev->needs_free_netdev = true;
dev->features = NETIF_F_SG | NETIF_F_FRAGLIST |
NETIF_F_HIGHDMA | NETIF_F_LLTX;
diff --git a/drivers/net/phy/Kconfig b/drivers/net/phy/Kconfig
index 60ffc9da6a28..3ab6c58d4be6 100644
--- a/drivers/net/phy/Kconfig
+++ b/drivers/net/phy/Kconfig
@@ -108,7 +108,7 @@ config MDIO_MOXART
config MDIO_OCTEON
tristate "Octeon and some ThunderX SOCs MDIO buses"
depends on 64BIT
- depends on HAS_IOMEM
+ depends on HAS_IOMEM && OF_MDIO
select MDIO_CAVIUM
help
This module provides a driver for the Octeon and ThunderX MDIO
@@ -127,6 +127,7 @@ config MDIO_THUNDER
tristate "ThunderX SOCs MDIO buses"
depends on 64BIT
depends on PCI
+ depends on !(MDIO_DEVICE=y && PHYLIB=m)
select MDIO_CAVIUM
help
This driver supports the MDIO interfaces found on Cavium
diff --git a/drivers/net/phy/dp83640.c b/drivers/net/phy/dp83640.c
index ed0d10f54f26..c3065236ffcc 100644
--- a/drivers/net/phy/dp83640.c
+++ b/drivers/net/phy/dp83640.c
@@ -908,7 +908,7 @@ static void decode_txts(struct dp83640_private *dp83640,
if (overflow) {
pr_debug("tx timestamp queue overflow, count %d\n", overflow);
while (skb) {
- skb_complete_tx_timestamp(skb, NULL);
+ kfree_skb(skb);
skb = skb_dequeue(&dp83640->tx_queue);
}
return;
diff --git a/drivers/net/phy/marvell.c b/drivers/net/phy/marvell.c
index 272b051a0199..57297ba23987 100644
--- a/drivers/net/phy/marvell.c
+++ b/drivers/net/phy/marvell.c
@@ -255,34 +255,6 @@ static int marvell_config_aneg(struct phy_device *phydev)
{
int err;
- /* The Marvell PHY has an errata which requires
- * that certain registers get written in order
- * to restart autonegotiation */
- err = phy_write(phydev, MII_BMCR, BMCR_RESET);
-
- if (err < 0)
- return err;
-
- err = phy_write(phydev, 0x1d, 0x1f);
- if (err < 0)
- return err;
-
- err = phy_write(phydev, 0x1e, 0x200c);
- if (err < 0)
- return err;
-
- err = phy_write(phydev, 0x1d, 0x5);
- if (err < 0)
- return err;
-
- err = phy_write(phydev, 0x1e, 0);
- if (err < 0)
- return err;
-
- err = phy_write(phydev, 0x1e, 0x100);
- if (err < 0)
- return err;
-
err = marvell_set_polarity(phydev, phydev->mdix_ctrl);
if (err < 0)
return err;
@@ -316,6 +288,42 @@ static int marvell_config_aneg(struct phy_device *phydev)
return 0;
}
+static int m88e1101_config_aneg(struct phy_device *phydev)
+{
+ int err;
+
+ /* This Marvell PHY has an errata which requires
+ * that certain registers get written in order
+ * to restart autonegotiation
+ */
+ err = phy_write(phydev, MII_BMCR, BMCR_RESET);
+
+ if (err < 0)
+ return err;
+
+ err = phy_write(phydev, 0x1d, 0x1f);
+ if (err < 0)
+ return err;
+
+ err = phy_write(phydev, 0x1e, 0x200c);
+ if (err < 0)
+ return err;
+
+ err = phy_write(phydev, 0x1d, 0x5);
+ if (err < 0)
+ return err;
+
+ err = phy_write(phydev, 0x1e, 0);
+ if (err < 0)
+ return err;
+
+ err = phy_write(phydev, 0x1e, 0x100);
+ if (err < 0)
+ return err;
+
+ return marvell_config_aneg(phydev);
+}
+
static int m88e1111_config_aneg(struct phy_device *phydev)
{
int err;
@@ -1119,8 +1127,6 @@ static int marvell_read_status_page(struct phy_device *phydev, int page)
if (adv < 0)
return adv;
- lpa &= adv;
-
if (status & MII_M1011_PHY_STATUS_FULLDUPLEX)
phydev->duplex = DUPLEX_FULL;
else
@@ -1892,7 +1898,7 @@ static struct phy_driver marvell_drivers[] = {
.flags = PHY_HAS_INTERRUPT,
.probe = marvell_probe,
.config_init = &marvell_config_init,
- .config_aneg = &marvell_config_aneg,
+ .config_aneg = &m88e1101_config_aneg,
.read_status = &genphy_read_status,
.ack_interrupt = &marvell_ack_interrupt,
.config_intr = &marvell_config_intr,
diff --git a/drivers/net/phy/mdio_bus.c b/drivers/net/phy/mdio_bus.c
index 8e73f5f36e71..f99c21f78b63 100644
--- a/drivers/net/phy/mdio_bus.c
+++ b/drivers/net/phy/mdio_bus.c
@@ -658,6 +658,18 @@ static int mdio_bus_match(struct device *dev, struct device_driver *drv)
return 0;
}
+static int mdio_uevent(struct device *dev, struct kobj_uevent_env *env)
+{
+ int rc;
+
+ /* Some devices have extra OF data and an OF-style MODALIAS */
+ rc = of_device_uevent_modalias(dev, env);
+ if (rc != -ENODEV)
+ return rc;
+
+ return 0;
+}
+
#ifdef CONFIG_PM
static int mdio_bus_suspend(struct device *dev)
{
@@ -708,6 +720,7 @@ static const struct dev_pm_ops mdio_bus_pm_ops = {
struct bus_type mdio_bus_type = {
.name = "mdio_bus",
.match = mdio_bus_match,
+ .uevent = mdio_uevent,
.pm = MDIO_BUS_PM_OPS,
};
EXPORT_SYMBOL(mdio_bus_type);
diff --git a/drivers/net/phy/micrel.c b/drivers/net/phy/micrel.c
index 6a5fd18f062c..8b2038844ba9 100644
--- a/drivers/net/phy/micrel.c
+++ b/drivers/net/phy/micrel.c
@@ -268,23 +268,12 @@ out:
return ret;
}
-static int kszphy_config_init(struct phy_device *phydev)
+/* Some config bits need to be set again on resume, handle them here. */
+static int kszphy_config_reset(struct phy_device *phydev)
{
struct kszphy_priv *priv = phydev->priv;
- const struct kszphy_type *type;
int ret;
- if (!priv)
- return 0;
-
- type = priv->type;
-
- if (type->has_broadcast_disable)
- kszphy_broadcast_disable(phydev);
-
- if (type->has_nand_tree_disable)
- kszphy_nand_tree_disable(phydev);
-
if (priv->rmii_ref_clk_sel) {
ret = kszphy_rmii_clk_sel(phydev, priv->rmii_ref_clk_sel_val);
if (ret) {
@@ -295,11 +284,30 @@ static int kszphy_config_init(struct phy_device *phydev)
}
if (priv->led_mode >= 0)
- kszphy_setup_led(phydev, type->led_mode_reg, priv->led_mode);
+ kszphy_setup_led(phydev, priv->type->led_mode_reg, priv->led_mode);
return 0;
}
+static int kszphy_config_init(struct phy_device *phydev)
+{
+ struct kszphy_priv *priv = phydev->priv;
+ const struct kszphy_type *type;
+
+ if (!priv)
+ return 0;
+
+ type = priv->type;
+
+ if (type->has_broadcast_disable)
+ kszphy_broadcast_disable(phydev);
+
+ if (type->has_nand_tree_disable)
+ kszphy_nand_tree_disable(phydev);
+
+ return kszphy_config_reset(phydev);
+}
+
static int ksz8041_config_init(struct phy_device *phydev)
{
struct device_node *of_node = phydev->mdio.dev.of_node;
@@ -611,6 +619,8 @@ static int ksz9031_read_status(struct phy_device *phydev)
if ((regval & 0xFF) == 0xFF) {
phy_init_hw(phydev);
phydev->link = 0;
+ if (phydev->drv->config_intr && phy_interrupt_is_valid(phydev))
+ phydev->drv->config_intr(phydev);
}
return 0;
@@ -700,8 +710,14 @@ static int kszphy_suspend(struct phy_device *phydev)
static int kszphy_resume(struct phy_device *phydev)
{
+ int ret;
+
genphy_resume(phydev);
+ ret = kszphy_config_reset(phydev);
+ if (ret)
+ return ret;
+
/* Enable PHY Interrupts */
if (phy_interrupt_is_valid(phydev)) {
phydev->interrupts = PHY_INTERRUPT_ENABLED;
diff --git a/drivers/net/phy/phy.c b/drivers/net/phy/phy.c
index 82ab8fb82587..eebb0e1c70ff 100644
--- a/drivers/net/phy/phy.c
+++ b/drivers/net/phy/phy.c
@@ -54,6 +54,8 @@ static const char *phy_speed_to_str(int speed)
return "5Gbps";
case SPEED_10000:
return "10Gbps";
+ case SPEED_14000:
+ return "14Gbps";
case SPEED_20000:
return "20Gbps";
case SPEED_25000:
@@ -241,7 +243,7 @@ static const struct phy_setting settings[] = {
* phy_lookup_setting - lookup a PHY setting
* @speed: speed to match
* @duplex: duplex to match
- * @feature: allowed link modes
+ * @features: allowed link modes
* @exact: an exact match is required
*
* Search the settings array for a setting that matches the speed and
diff --git a/drivers/net/slip/slip.c b/drivers/net/slip/slip.c
index 1da31dc47f86..74b907206aa7 100644
--- a/drivers/net/slip/slip.c
+++ b/drivers/net/slip/slip.c
@@ -629,7 +629,7 @@ static void sl_uninit(struct net_device *dev)
static void sl_free_netdev(struct net_device *dev)
{
int i = dev->base_addr;
- free_netdev(dev);
+
slip_devs[i] = NULL;
}
@@ -651,7 +651,8 @@ static const struct net_device_ops sl_netdev_ops = {
static void sl_setup(struct net_device *dev)
{
dev->netdev_ops = &sl_netdev_ops;
- dev->destructor = sl_free_netdev;
+ dev->needs_free_netdev = true;
+ dev->priv_destructor = sl_free_netdev;
dev->hard_header_len = 0;
dev->addr_len = 0;
@@ -1369,8 +1370,6 @@ static void __exit slip_exit(void)
if (sl->tty) {
printk(KERN_ERR "%s: tty discipline still running\n",
dev->name);
- /* Intentionally leak the control block. */
- dev->destructor = NULL;
}
unregister_netdev(dev);
diff --git a/drivers/net/team/team.c b/drivers/net/team/team.c
index 6c5d5ef46f75..fba8c136aa7c 100644
--- a/drivers/net/team/team.c
+++ b/drivers/net/team/team.c
@@ -1643,7 +1643,6 @@ static void team_destructor(struct net_device *dev)
struct team *team = netdev_priv(dev);
free_percpu(team->pcpu_stats);
- free_netdev(dev);
}
static int team_open(struct net_device *dev)
@@ -2079,7 +2078,8 @@ static void team_setup(struct net_device *dev)
dev->netdev_ops = &team_netdev_ops;
dev->ethtool_ops = &team_ethtool_ops;
- dev->destructor = team_destructor;
+ dev->needs_free_netdev = true;
+ dev->priv_destructor = team_destructor;
dev->priv_flags &= ~(IFF_XMIT_DST_RELEASE | IFF_TX_SKB_SHARING);
dev->priv_flags |= IFF_NO_QUEUE;
dev->priv_flags |= IFF_TEAM;
diff --git a/drivers/net/tun.c b/drivers/net/tun.c
index bbd707b9ef7a..9ee7d4275640 100644
--- a/drivers/net/tun.c
+++ b/drivers/net/tun.c
@@ -1560,7 +1560,6 @@ static void tun_free_netdev(struct net_device *dev)
free_percpu(tun->pcpu_stats);
tun_flow_uninit(tun);
security_tun_dev_free_security(tun->security);
- free_netdev(dev);
}
static void tun_setup(struct net_device *dev)
@@ -1571,7 +1570,8 @@ static void tun_setup(struct net_device *dev)
tun->group = INVALID_GID;
dev->ethtool_ops = &tun_ethtool_ops;
- dev->destructor = tun_free_netdev;
+ dev->needs_free_netdev = true;
+ dev->priv_destructor = tun_free_netdev;
/* We prefer our own queue length */
dev->tx_queue_len = TUN_READQ_SIZE;
}
diff --git a/drivers/net/usb/ax88179_178a.c b/drivers/net/usb/ax88179_178a.c
index 51cf60092a18..4037ab27734a 100644
--- a/drivers/net/usb/ax88179_178a.c
+++ b/drivers/net/usb/ax88179_178a.c
@@ -1722,6 +1722,18 @@ static const struct driver_info lenovo_info = {
.tx_fixup = ax88179_tx_fixup,
};
+static const struct driver_info belkin_info = {
+ .description = "Belkin USB Ethernet Adapter",
+ .bind = ax88179_bind,
+ .unbind = ax88179_unbind,
+ .status = ax88179_status,
+ .link_reset = ax88179_link_reset,
+ .reset = ax88179_reset,
+ .flags = FLAG_ETHER | FLAG_FRAMING_AX,
+ .rx_fixup = ax88179_rx_fixup,
+ .tx_fixup = ax88179_tx_fixup,
+};
+
static const struct usb_device_id products[] = {
{
/* ASIX AX88179 10/100/1000 */
@@ -1751,6 +1763,10 @@ static const struct usb_device_id products[] = {
/* Lenovo OneLinkDock Gigabit LAN */
USB_DEVICE(0x17ef, 0x304b),
.driver_info = (unsigned long)&lenovo_info,
+}, {
+ /* Belkin B2B128 USB 3.0 Hub + Gigabit Ethernet Adapter */
+ USB_DEVICE(0x050d, 0x0128),
+ .driver_info = (unsigned long)&belkin_info,
},
{ },
};
diff --git a/drivers/net/usb/cdc-phonet.c b/drivers/net/usb/cdc-phonet.c
index eb52de8205f0..c7a350bbaaa7 100644
--- a/drivers/net/usb/cdc-phonet.c
+++ b/drivers/net/usb/cdc-phonet.c
@@ -298,7 +298,7 @@ static void usbpn_setup(struct net_device *dev)
dev->addr_len = 1;
dev->tx_queue_len = 3;
- dev->destructor = free_netdev;
+ dev->needs_free_netdev = true;
}
/*
diff --git a/drivers/net/usb/cdc_ether.c b/drivers/net/usb/cdc_ether.c
index f3ae88fdf332..8ab281b478f2 100644
--- a/drivers/net/usb/cdc_ether.c
+++ b/drivers/net/usb/cdc_ether.c
@@ -310,6 +310,26 @@ skip:
return -ENODEV;
}
+ return 0;
+
+bad_desc:
+ dev_info(&dev->udev->dev, "bad CDC descriptors\n");
+ return -ENODEV;
+}
+EXPORT_SYMBOL_GPL(usbnet_generic_cdc_bind);
+
+
+/* like usbnet_generic_cdc_bind() but handles filter initialization
+ * correctly
+ */
+int usbnet_ether_cdc_bind(struct usbnet *dev, struct usb_interface *intf)
+{
+ int rv;
+
+ rv = usbnet_generic_cdc_bind(dev, intf);
+ if (rv < 0)
+ goto bail_out;
+
/* Some devices don't initialise properly. In particular
* the packet filter is not reset. There are devices that
* don't do reset all the way. So the packet filter should
@@ -317,13 +337,10 @@ skip:
*/
usbnet_cdc_update_filter(dev);
- return 0;
-
-bad_desc:
- dev_info(&dev->udev->dev, "bad CDC descriptors\n");
- return -ENODEV;
+bail_out:
+ return rv;
}
-EXPORT_SYMBOL_GPL(usbnet_generic_cdc_bind);
+EXPORT_SYMBOL_GPL(usbnet_ether_cdc_bind);
void usbnet_cdc_unbind(struct usbnet *dev, struct usb_interface *intf)
{
@@ -417,7 +434,7 @@ int usbnet_cdc_bind(struct usbnet *dev, struct usb_interface *intf)
BUILD_BUG_ON((sizeof(((struct usbnet *)0)->data)
< sizeof(struct cdc_state)));
- status = usbnet_generic_cdc_bind(dev, intf);
+ status = usbnet_ether_cdc_bind(dev, intf);
if (status < 0)
return status;
diff --git a/drivers/net/usb/qmi_wwan.c b/drivers/net/usb/qmi_wwan.c
index 8f923a147fa9..32a22f4e8356 100644
--- a/drivers/net/usb/qmi_wwan.c
+++ b/drivers/net/usb/qmi_wwan.c
@@ -123,7 +123,7 @@ static void qmimux_setup(struct net_device *dev)
dev->addr_len = 0;
dev->flags = IFF_POINTOPOINT | IFF_NOARP | IFF_MULTICAST;
dev->netdev_ops = &qmimux_netdev_ops;
- dev->destructor = free_netdev;
+ dev->needs_free_netdev = true;
}
static struct net_device *qmimux_find_dev(struct usbnet *dev, u8 mux_id)
@@ -1192,6 +1192,8 @@ static const struct usb_device_id products[] = {
{QMI_FIXED_INTF(0x1199, 0x9056, 8)}, /* Sierra Wireless Modem */
{QMI_FIXED_INTF(0x1199, 0x9057, 8)},
{QMI_FIXED_INTF(0x1199, 0x9061, 8)}, /* Sierra Wireless Modem */
+ {QMI_FIXED_INTF(0x1199, 0x9063, 8)}, /* Sierra Wireless EM7305 */
+ {QMI_FIXED_INTF(0x1199, 0x9063, 10)}, /* Sierra Wireless EM7305 */
{QMI_FIXED_INTF(0x1199, 0x9071, 8)}, /* Sierra Wireless MC74xx */
{QMI_FIXED_INTF(0x1199, 0x9071, 10)}, /* Sierra Wireless MC74xx */
{QMI_FIXED_INTF(0x1199, 0x9079, 8)}, /* Sierra Wireless EM74xx */
@@ -1206,6 +1208,8 @@ static const struct usb_device_id products[] = {
{QMI_FIXED_INTF(0x1bc7, 0x1100, 3)}, /* Telit ME910 */
{QMI_FIXED_INTF(0x1bc7, 0x1200, 5)}, /* Telit LE920 */
{QMI_QUIRK_SET_DTR(0x1bc7, 0x1201, 2)}, /* Telit LE920, LE920A4 */
+ {QMI_FIXED_INTF(0x1c9e, 0x9801, 3)}, /* Telewell TW-3G HSPA+ */
+ {QMI_FIXED_INTF(0x1c9e, 0x9803, 4)}, /* Telewell TW-3G HSPA+ */
{QMI_FIXED_INTF(0x1c9e, 0x9b01, 3)}, /* XS Stick W100-2 from 4G Systems */
{QMI_FIXED_INTF(0x0b3c, 0xc000, 4)}, /* Olivetti Olicard 100 */
{QMI_FIXED_INTF(0x0b3c, 0xc001, 4)}, /* Olivetti Olicard 120 */
diff --git a/drivers/net/usb/r8152.c b/drivers/net/usb/r8152.c
index ddc62cb69be8..1a419a45e2a2 100644
--- a/drivers/net/usb/r8152.c
+++ b/drivers/net/usb/r8152.c
@@ -4368,6 +4368,8 @@ static u8 rtl_get_version(struct usb_interface *intf)
break;
}
+ dev_dbg(&intf->dev, "Detected version 0x%04x\n", version);
+
return version;
}
diff --git a/drivers/net/usb/smsc95xx.c b/drivers/net/usb/smsc95xx.c
index 765400b62168..2dfca96a63b6 100644
--- a/drivers/net/usb/smsc95xx.c
+++ b/drivers/net/usb/smsc95xx.c
@@ -681,7 +681,7 @@ static int smsc95xx_set_features(struct net_device *netdev,
if (ret < 0)
return ret;
- if (features & NETIF_F_HW_CSUM)
+ if (features & NETIF_F_IP_CSUM)
read_buf |= Tx_COE_EN_;
else
read_buf &= ~Tx_COE_EN_;
@@ -1279,12 +1279,19 @@ static int smsc95xx_bind(struct usbnet *dev, struct usb_interface *intf)
spin_lock_init(&pdata->mac_cr_lock);
+ /* LAN95xx devices do not alter the computed checksum of 0 to 0xffff.
+ * RFC 2460, ipv6 UDP calculated checksum yields a result of zero must
+ * be changed to 0xffff. RFC 768, ipv4 UDP computed checksum is zero,
+ * it is transmitted as all ones. The zero transmitted checksum means
+ * transmitter generated no checksum. Hence, enable csum offload only
+ * for ipv4 packets.
+ */
if (DEFAULT_TX_CSUM_ENABLE)
- dev->net->features |= NETIF_F_HW_CSUM;
+ dev->net->features |= NETIF_F_IP_CSUM;
if (DEFAULT_RX_CSUM_ENABLE)
dev->net->features |= NETIF_F_RXCSUM;
- dev->net->hw_features = NETIF_F_HW_CSUM | NETIF_F_RXCSUM;
+ dev->net->hw_features = NETIF_F_IP_CSUM | NETIF_F_RXCSUM;
smsc95xx_init_mac_address(dev);
diff --git a/drivers/net/veth.c b/drivers/net/veth.c
index 38f0f03a29c8..364fa9d11d1a 100644
--- a/drivers/net/veth.c
+++ b/drivers/net/veth.c
@@ -222,7 +222,6 @@ static int veth_dev_init(struct net_device *dev)
static void veth_dev_free(struct net_device *dev)
{
free_percpu(dev->vstats);
- free_netdev(dev);
}
#ifdef CONFIG_NET_POLL_CONTROLLER
@@ -317,7 +316,8 @@ static void veth_setup(struct net_device *dev)
NETIF_F_HW_VLAN_STAG_TX |
NETIF_F_HW_VLAN_CTAG_RX |
NETIF_F_HW_VLAN_STAG_RX);
- dev->destructor = veth_dev_free;
+ dev->needs_free_netdev = true;
+ dev->priv_destructor = veth_dev_free;
dev->max_mtu = ETH_MAX_MTU;
dev->hw_features = VETH_FEATURES;
@@ -383,7 +383,7 @@ static int veth_newlink(struct net *src_net, struct net_device *dev,
tbp = tb;
}
- if (tbp[IFLA_IFNAME]) {
+ if (ifmp && tbp[IFLA_IFNAME]) {
nla_strlcpy(ifname, tbp[IFLA_IFNAME], IFNAMSIZ);
name_assign_type = NET_NAME_USER;
} else {
@@ -402,7 +402,7 @@ static int veth_newlink(struct net *src_net, struct net_device *dev,
return PTR_ERR(peer);
}
- if (tbp[IFLA_ADDRESS] == NULL)
+ if (!ifmp || !tbp[IFLA_ADDRESS])
eth_hw_addr_random(peer);
if (ifmp && (dev->ifindex != 0))
diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c
index 9320d96a1632..143d8a95a60d 100644
--- a/drivers/net/virtio_net.c
+++ b/drivers/net/virtio_net.c
@@ -869,7 +869,7 @@ static unsigned int get_mergeable_buf_len(struct receive_queue *rq,
unsigned int len;
len = hdr_len + clamp_t(unsigned int, ewma_pkt_len_read(avg_pkt_len),
- rq->min_buf_len - hdr_len, PAGE_SIZE - hdr_len);
+ rq->min_buf_len, PAGE_SIZE - hdr_len);
return ALIGN(len, L1_CACHE_BYTES);
}
@@ -1797,6 +1797,7 @@ static void virtnet_freeze_down(struct virtio_device *vdev)
flush_work(&vi->config_work);
netif_device_detach(vi->dev);
+ netif_tx_disable(vi->dev);
cancel_delayed_work_sync(&vi->refill);
if (netif_running(vi->dev)) {
@@ -1989,6 +1990,7 @@ static const struct net_device_ops virtnet_netdev = {
.ndo_poll_controller = virtnet_netpoll,
#endif
.ndo_xdp = virtnet_xdp,
+ .ndo_features_check = passthru_features_check,
};
static void virtnet_config_changed_work(struct work_struct *work)
@@ -2143,7 +2145,8 @@ static unsigned int mergeable_min_buf_len(struct virtnet_info *vi, struct virtqu
unsigned int buf_len = hdr_len + ETH_HLEN + VLAN_HLEN + packet_len;
unsigned int min_buf_len = DIV_ROUND_UP(buf_len, rq_size);
- return max(min_buf_len, hdr_len);
+ return max(max(min_buf_len, hdr_len) - hdr_len,
+ (unsigned int)GOOD_PACKET_LEN);
}
static int virtnet_find_vqs(struct virtnet_info *vi)
diff --git a/drivers/net/vrf.c b/drivers/net/vrf.c
index db882493875c..022c0b5f9844 100644
--- a/drivers/net/vrf.c
+++ b/drivers/net/vrf.c
@@ -36,12 +36,14 @@
#include <net/addrconf.h>
#include <net/l3mdev.h>
#include <net/fib_rules.h>
+#include <net/netns/generic.h>
#define DRV_NAME "vrf"
#define DRV_VERSION "1.0"
#define FIB_RULE_PREF 1000 /* default preference for FIB rules */
-static bool add_fib_rules = true;
+
+static unsigned int vrf_net_id;
struct net_vrf {
struct rtable __rcu *rth;
@@ -1348,7 +1350,7 @@ static void vrf_setup(struct net_device *dev)
dev->netdev_ops = &vrf_netdev_ops;
dev->l3mdev_ops = &vrf_l3mdev_ops;
dev->ethtool_ops = &vrf_ethtool_ops;
- dev->destructor = free_netdev;
+ dev->needs_free_netdev = true;
/* Fill in device structure with ethernet-generic values. */
eth_hw_addr_random(dev);
@@ -1394,6 +1396,8 @@ static int vrf_newlink(struct net *src_net, struct net_device *dev,
struct nlattr *tb[], struct nlattr *data[])
{
struct net_vrf *vrf = netdev_priv(dev);
+ bool *add_fib_rules;
+ struct net *net;
int err;
if (!data || !data[IFLA_VRF_TABLE])
@@ -1409,13 +1413,15 @@ static int vrf_newlink(struct net *src_net, struct net_device *dev,
if (err)
goto out;
- if (add_fib_rules) {
+ net = dev_net(dev);
+ add_fib_rules = net_generic(net, vrf_net_id);
+ if (*add_fib_rules) {
err = vrf_add_fib_rules(dev);
if (err) {
unregister_netdevice(dev);
goto out;
}
- add_fib_rules = false;
+ *add_fib_rules = false;
}
out:
@@ -1498,16 +1504,38 @@ static struct notifier_block vrf_notifier_block __read_mostly = {
.notifier_call = vrf_device_event,
};
+/* Initialize per network namespace state */
+static int __net_init vrf_netns_init(struct net *net)
+{
+ bool *add_fib_rules = net_generic(net, vrf_net_id);
+
+ *add_fib_rules = true;
+
+ return 0;
+}
+
+static struct pernet_operations vrf_net_ops __net_initdata = {
+ .init = vrf_netns_init,
+ .id = &vrf_net_id,
+ .size = sizeof(bool),
+};
+
static int __init vrf_init_module(void)
{
int rc;
register_netdevice_notifier(&vrf_notifier_block);
- rc = rtnl_link_register(&vrf_link_ops);
+ rc = register_pernet_subsys(&vrf_net_ops);
if (rc < 0)
goto error;
+ rc = rtnl_link_register(&vrf_link_ops);
+ if (rc < 0) {
+ unregister_pernet_subsys(&vrf_net_ops);
+ goto error;
+ }
+
return 0;
error:
diff --git a/drivers/net/vsockmon.c b/drivers/net/vsockmon.c
index 7f0136f2dd9d..c28bdce14fd5 100644
--- a/drivers/net/vsockmon.c
+++ b/drivers/net/vsockmon.c
@@ -135,7 +135,7 @@ static void vsockmon_setup(struct net_device *dev)
dev->netdev_ops = &vsockmon_ops;
dev->ethtool_ops = &vsockmon_ethtool_ops;
- dev->destructor = free_netdev;
+ dev->needs_free_netdev = true;
dev->features = NETIF_F_SG | NETIF_F_FRAGLIST |
NETIF_F_HIGHDMA | NETIF_F_LLTX;
diff --git a/drivers/net/vxlan.c b/drivers/net/vxlan.c
index 328b4712683c..5fa798a5c9a6 100644
--- a/drivers/net/vxlan.c
+++ b/drivers/net/vxlan.c
@@ -59,6 +59,8 @@ static const u8 all_zeros_mac[ETH_ALEN + 2];
static int vxlan_sock_add(struct vxlan_dev *vxlan);
+static void vxlan_vs_del_dev(struct vxlan_dev *vxlan);
+
/* per-network namespace private data for this module */
struct vxlan_net {
struct list_head vxlan_list;
@@ -740,6 +742,22 @@ static void vxlan_fdb_destroy(struct vxlan_dev *vxlan, struct vxlan_fdb *f)
call_rcu(&f->rcu, vxlan_fdb_free);
}
+static void vxlan_dst_free(struct rcu_head *head)
+{
+ struct vxlan_rdst *rd = container_of(head, struct vxlan_rdst, rcu);
+
+ dst_cache_destroy(&rd->dst_cache);
+ kfree(rd);
+}
+
+static void vxlan_fdb_dst_destroy(struct vxlan_dev *vxlan, struct vxlan_fdb *f,
+ struct vxlan_rdst *rd)
+{
+ list_del_rcu(&rd->list);
+ vxlan_fdb_notify(vxlan, f, rd, RTM_DELNEIGH);
+ call_rcu(&rd->rcu, vxlan_dst_free);
+}
+
static int vxlan_fdb_parse(struct nlattr *tb[], struct vxlan_dev *vxlan,
union vxlan_addr *ip, __be16 *port, __be32 *src_vni,
__be32 *vni, u32 *ifindex)
@@ -864,9 +882,7 @@ static int __vxlan_fdb_delete(struct vxlan_dev *vxlan,
* otherwise destroy the fdb entry
*/
if (rd && !list_is_singular(&f->remotes)) {
- list_del_rcu(&rd->list);
- vxlan_fdb_notify(vxlan, f, rd, RTM_DELNEIGH);
- kfree_rcu(rd, rcu);
+ vxlan_fdb_dst_destroy(vxlan, f, rd);
goto out;
}
@@ -1067,6 +1083,8 @@ static void vxlan_sock_release(struct vxlan_dev *vxlan)
rcu_assign_pointer(vxlan->vn4_sock, NULL);
synchronize_net();
+ vxlan_vs_del_dev(vxlan);
+
if (__vxlan_sock_release_prep(sock4)) {
udp_tunnel_sock_release(sock4->sock);
kfree(sock4);
@@ -2342,6 +2360,15 @@ static void vxlan_cleanup(unsigned long arg)
mod_timer(&vxlan->age_timer, next_timer);
}
+static void vxlan_vs_del_dev(struct vxlan_dev *vxlan)
+{
+ struct vxlan_net *vn = net_generic(vxlan->net, vxlan_net_id);
+
+ spin_lock(&vn->sock_lock);
+ hlist_del_init_rcu(&vxlan->hlist);
+ spin_unlock(&vn->sock_lock);
+}
+
static void vxlan_vs_add_dev(struct vxlan_sock *vs, struct vxlan_dev *vxlan)
{
struct vxlan_net *vn = net_generic(vxlan->net, vxlan_net_id);
@@ -2584,7 +2611,7 @@ static void vxlan_setup(struct net_device *dev)
eth_hw_addr_random(dev);
ether_setup(dev);
- dev->destructor = free_netdev;
+ dev->needs_free_netdev = true;
SET_NETDEV_DEVTYPE(dev, &vxlan_type);
dev->features |= NETIF_F_LLTX;
@@ -3286,15 +3313,9 @@ static int vxlan_changelink(struct net_device *dev, struct nlattr *tb[],
static void vxlan_dellink(struct net_device *dev, struct list_head *head)
{
struct vxlan_dev *vxlan = netdev_priv(dev);
- struct vxlan_net *vn = net_generic(vxlan->net, vxlan_net_id);
vxlan_flush(vxlan, true);
- spin_lock(&vn->sock_lock);
- if (!hlist_unhashed(&vxlan->hlist))
- hlist_del_rcu(&vxlan->hlist);
- spin_unlock(&vn->sock_lock);
-
gro_cells_destroy(&vxlan->gro_cells);
list_del(&vxlan->next);
unregister_netdevice_queue(dev, head);
diff --git a/drivers/net/wan/dlci.c b/drivers/net/wan/dlci.c
index 65ee2a6f248c..a0d76f70c428 100644
--- a/drivers/net/wan/dlci.c
+++ b/drivers/net/wan/dlci.c
@@ -475,7 +475,7 @@ static void dlci_setup(struct net_device *dev)
dev->flags = 0;
dev->header_ops = &dlci_header_ops;
dev->netdev_ops = &dlci_netdev_ops;
- dev->destructor = free_netdev;
+ dev->needs_free_netdev = true;
dlp->receive = dlci_receive;
diff --git a/drivers/net/wan/hdlc_fr.c b/drivers/net/wan/hdlc_fr.c
index eb915281197e..78596e42a3f3 100644
--- a/drivers/net/wan/hdlc_fr.c
+++ b/drivers/net/wan/hdlc_fr.c
@@ -1106,7 +1106,7 @@ static int fr_add_pvc(struct net_device *frad, unsigned int dlci, int type)
return -EIO;
}
- dev->destructor = free_netdev;
+ dev->needs_free_netdev = true;
*get_dev_p(pvc, type) = dev;
if (!used) {
state(hdlc)->dce_changed = 1;
diff --git a/drivers/net/wan/lapbether.c b/drivers/net/wan/lapbether.c
index 9df9ed62beff..63f749078a1f 100644
--- a/drivers/net/wan/lapbether.c
+++ b/drivers/net/wan/lapbether.c
@@ -306,7 +306,7 @@ static const struct net_device_ops lapbeth_netdev_ops = {
static void lapbeth_setup(struct net_device *dev)
{
dev->netdev_ops = &lapbeth_netdev_ops;
- dev->destructor = free_netdev;
+ dev->needs_free_netdev = true;
dev->type = ARPHRD_X25;
dev->hard_header_len = 3;
dev->mtu = 1000;
diff --git a/drivers/net/wireless/ath/ath6kl/main.c b/drivers/net/wireless/ath/ath6kl/main.c
index 91ee542de3d7..b90c77ef792e 100644
--- a/drivers/net/wireless/ath/ath6kl/main.c
+++ b/drivers/net/wireless/ath/ath6kl/main.c
@@ -1287,7 +1287,7 @@ void init_netdev(struct net_device *dev)
struct ath6kl *ar = ath6kl_priv(dev);
dev->netdev_ops = &ath6kl_netdev_ops;
- dev->destructor = free_netdev;
+ dev->needs_free_netdev = true;
dev->watchdog_timeo = ATH6KL_TX_TIMEOUT;
dev->needed_headroom = ETH_HLEN;
diff --git a/drivers/net/wireless/ath/wcn36xx/main.c b/drivers/net/wireless/ath/wcn36xx/main.c
index d5e993dc9b23..517a315e259b 100644
--- a/drivers/net/wireless/ath/wcn36xx/main.c
+++ b/drivers/net/wireless/ath/wcn36xx/main.c
@@ -1271,6 +1271,8 @@ static int wcn36xx_remove(struct platform_device *pdev)
qcom_smem_state_put(wcn->tx_enable_state);
qcom_smem_state_put(wcn->tx_rings_empty_state);
+ rpmsg_destroy_ept(wcn->smd_channel);
+
iounmap(wcn->dxe_base);
iounmap(wcn->ccu_base);
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c
index cd1d6730eab7..617199c0e5a0 100644
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c
@@ -5225,7 +5225,6 @@ void brcmf_cfg80211_free_netdev(struct net_device *ndev)
if (vif)
brcmf_free_vif(vif);
- free_netdev(ndev);
}
static bool brcmf_is_linkup(const struct brcmf_event_msg *e)
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c
index a3d82368f1a9..511d190c6cca 100644
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c
@@ -624,7 +624,8 @@ struct brcmf_if *brcmf_add_if(struct brcmf_pub *drvr, s32 bsscfgidx, s32 ifidx,
if (!ndev)
return ERR_PTR(-ENOMEM);
- ndev->destructor = brcmf_cfg80211_free_netdev;
+ ndev->needs_free_netdev = true;
+ ndev->priv_destructor = brcmf_cfg80211_free_netdev;
ifp = netdev_priv(ndev);
ifp->ndev = ndev;
/* store mapping ifidx to bsscfgidx */
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/firmware.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/firmware.c
index c7c1e9906500..d231042f19d6 100644
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/firmware.c
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/firmware.c
@@ -442,7 +442,7 @@ struct brcmf_fw {
const char *nvram_name;
u16 domain_nr;
u16 bus_nr;
- void (*done)(struct device *dev, const struct firmware *fw,
+ void (*done)(struct device *dev, int err, const struct firmware *fw,
void *nvram_image, u32 nvram_len);
};
@@ -477,52 +477,51 @@ static void brcmf_fw_request_nvram_done(const struct firmware *fw, void *ctx)
if (!nvram && !(fwctx->flags & BRCMF_FW_REQ_NV_OPTIONAL))
goto fail;
- fwctx->done(fwctx->dev, fwctx->code, nvram, nvram_length);
+ fwctx->done(fwctx->dev, 0, fwctx->code, nvram, nvram_length);
kfree(fwctx);
return;
fail:
brcmf_dbg(TRACE, "failed: dev=%s\n", dev_name(fwctx->dev));
release_firmware(fwctx->code);
- device_release_driver(fwctx->dev);
+ fwctx->done(fwctx->dev, -ENOENT, NULL, NULL, 0);
kfree(fwctx);
}
static void brcmf_fw_request_code_done(const struct firmware *fw, void *ctx)
{
struct brcmf_fw *fwctx = ctx;
- int ret;
+ int ret = 0;
brcmf_dbg(TRACE, "enter: dev=%s\n", dev_name(fwctx->dev));
- if (!fw)
+ if (!fw) {
+ ret = -ENOENT;
goto fail;
-
- /* only requested code so done here */
- if (!(fwctx->flags & BRCMF_FW_REQUEST_NVRAM)) {
- fwctx->done(fwctx->dev, fw, NULL, 0);
- kfree(fwctx);
- return;
}
+ /* only requested code so done here */
+ if (!(fwctx->flags & BRCMF_FW_REQUEST_NVRAM))
+ goto done;
+
fwctx->code = fw;
ret = request_firmware_nowait(THIS_MODULE, true, fwctx->nvram_name,
fwctx->dev, GFP_KERNEL, fwctx,
brcmf_fw_request_nvram_done);
- if (!ret)
- return;
-
- brcmf_fw_request_nvram_done(NULL, fwctx);
+ /* pass NULL to nvram callback for bcm47xx fallback */
+ if (ret)
+ brcmf_fw_request_nvram_done(NULL, fwctx);
return;
fail:
brcmf_dbg(TRACE, "failed: dev=%s\n", dev_name(fwctx->dev));
- device_release_driver(fwctx->dev);
+done:
+ fwctx->done(fwctx->dev, ret, fw, NULL, 0);
kfree(fwctx);
}
int brcmf_fw_get_firmwares_pcie(struct device *dev, u16 flags,
const char *code, const char *nvram,
- void (*fw_cb)(struct device *dev,
+ void (*fw_cb)(struct device *dev, int err,
const struct firmware *fw,
void *nvram_image, u32 nvram_len),
u16 domain_nr, u16 bus_nr)
@@ -555,7 +554,7 @@ int brcmf_fw_get_firmwares_pcie(struct device *dev, u16 flags,
int brcmf_fw_get_firmwares(struct device *dev, u16 flags,
const char *code, const char *nvram,
- void (*fw_cb)(struct device *dev,
+ void (*fw_cb)(struct device *dev, int err,
const struct firmware *fw,
void *nvram_image, u32 nvram_len))
{
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/firmware.h b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/firmware.h
index d3c9f0d52ae3..8fa4b7e1ab3d 100644
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/firmware.h
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/firmware.h
@@ -73,13 +73,13 @@ void brcmf_fw_nvram_free(void *nvram);
*/
int brcmf_fw_get_firmwares_pcie(struct device *dev, u16 flags,
const char *code, const char *nvram,
- void (*fw_cb)(struct device *dev,
+ void (*fw_cb)(struct device *dev, int err,
const struct firmware *fw,
void *nvram_image, u32 nvram_len),
u16 domain_nr, u16 bus_nr);
int brcmf_fw_get_firmwares(struct device *dev, u16 flags,
const char *code, const char *nvram,
- void (*fw_cb)(struct device *dev,
+ void (*fw_cb)(struct device *dev, int err,
const struct firmware *fw,
void *nvram_image, u32 nvram_len));
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwsignal.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwsignal.c
index 72373e59308e..f59642b2c935 100644
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwsignal.c
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwsignal.c
@@ -2145,7 +2145,7 @@ void brcmf_fws_add_interface(struct brcmf_if *ifp)
struct brcmf_fws_info *fws = drvr_to_fws(ifp->drvr);
struct brcmf_fws_mac_descriptor *entry;
- if (!ifp->ndev || fws->fcmode == BRCMF_FWS_FCMODE_NONE)
+ if (!ifp->ndev || !brcmf_fws_queue_skbs(fws))
return;
entry = &fws->desc.iface[ifp->ifidx];
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c
index f36b96dc6acd..f878706613e6 100644
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c
@@ -1650,16 +1650,23 @@ static const struct brcmf_buscore_ops brcmf_pcie_buscore_ops = {
.write32 = brcmf_pcie_buscore_write32,
};
-static void brcmf_pcie_setup(struct device *dev, const struct firmware *fw,
+static void brcmf_pcie_setup(struct device *dev, int ret,
+ const struct firmware *fw,
void *nvram, u32 nvram_len)
{
- struct brcmf_bus *bus = dev_get_drvdata(dev);
- struct brcmf_pciedev *pcie_bus_dev = bus->bus_priv.pcie;
- struct brcmf_pciedev_info *devinfo = pcie_bus_dev->devinfo;
+ struct brcmf_bus *bus;
+ struct brcmf_pciedev *pcie_bus_dev;
+ struct brcmf_pciedev_info *devinfo;
struct brcmf_commonring **flowrings;
- int ret;
u32 i;
+ /* check firmware loading result */
+ if (ret)
+ goto fail;
+
+ bus = dev_get_drvdata(dev);
+ pcie_bus_dev = bus->bus_priv.pcie;
+ devinfo = pcie_bus_dev->devinfo;
brcmf_pcie_attach(devinfo);
/* Some of the firmwares have the size of the memory of the device
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c
index fc64b8913aa6..5653d6dd38f6 100644
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c
@@ -3422,7 +3422,7 @@ static int brcmf_sdio_bus_preinit(struct device *dev)
/* otherwise, set txglomalign */
value = sdiodev->settings->bus.sdio.sd_sgentry_align;
/* SDIO ADMA requires at least 32 bit alignment */
- value = max_t(u32, value, 4);
+ value = max_t(u32, value, ALIGNMENT);
err = brcmf_iovar_data_set(dev, "bus:txglomalign", &value,
sizeof(u32));
}
@@ -3982,21 +3982,26 @@ static const struct brcmf_bus_ops brcmf_sdio_bus_ops = {
.get_memdump = brcmf_sdio_bus_get_memdump,
};
-static void brcmf_sdio_firmware_callback(struct device *dev,
+static void brcmf_sdio_firmware_callback(struct device *dev, int err,
const struct firmware *code,
void *nvram, u32 nvram_len)
{
- struct brcmf_bus *bus_if = dev_get_drvdata(dev);
- struct brcmf_sdio_dev *sdiodev = bus_if->bus_priv.sdio;
- struct brcmf_sdio *bus = sdiodev->bus;
- int err = 0;
+ struct brcmf_bus *bus_if;
+ struct brcmf_sdio_dev *sdiodev;
+ struct brcmf_sdio *bus;
u8 saveclk;
- brcmf_dbg(TRACE, "Enter: dev=%s\n", dev_name(dev));
+ brcmf_dbg(TRACE, "Enter: dev=%s, err=%d\n", dev_name(dev), err);
+ bus_if = dev_get_drvdata(dev);
+ sdiodev = bus_if->bus_priv.sdio;
+ if (err)
+ goto fail;
if (!bus_if->drvr)
return;
+ bus = sdiodev->bus;
+
/* try to download image and nvram to the dongle */
bus->alp_only = true;
err = brcmf_sdio_download_firmware(bus, code, nvram, nvram_len);
@@ -4083,6 +4088,7 @@ release:
fail:
brcmf_dbg(TRACE, "failed: dev=%s, err=%d\n", dev_name(dev), err);
device_release_driver(dev);
+ device_release_driver(&sdiodev->func[2]->dev);
}
struct brcmf_sdio *brcmf_sdio_probe(struct brcmf_sdio_dev *sdiodev)
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/usb.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/usb.c
index e4d545f9edee..0eea48e73331 100644
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/usb.c
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/usb.c
@@ -1159,17 +1159,18 @@ fail:
return ret;
}
-static void brcmf_usb_probe_phase2(struct device *dev,
+static void brcmf_usb_probe_phase2(struct device *dev, int ret,
const struct firmware *fw,
void *nvram, u32 nvlen)
{
struct brcmf_bus *bus = dev_get_drvdata(dev);
- struct brcmf_usbdev_info *devinfo;
- int ret;
+ struct brcmf_usbdev_info *devinfo = bus->bus_priv.usb->devinfo;
+
+ if (ret)
+ goto error;
brcmf_dbg(USB, "Start fw downloading\n");
- devinfo = bus->bus_priv.usb->devinfo;
ret = check_file(fw->data);
if (ret < 0) {
brcmf_err("invalid firmware\n");
diff --git a/drivers/net/wireless/cisco/airo.c b/drivers/net/wireless/cisco/airo.c
index 1b7e125a28e2..6a13303af2b7 100644
--- a/drivers/net/wireless/cisco/airo.c
+++ b/drivers/net/wireless/cisco/airo.c
@@ -3066,7 +3066,7 @@ static int airo_thread(void *data) {
if (ai->jobs) {
locked = down_interruptible(&ai->sem);
} else {
- wait_queue_t wait;
+ wait_queue_entry_t wait;
init_waitqueue_entry(&wait, current);
add_wait_queue(&ai->thr_wait, &wait);
diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-7000.c b/drivers/net/wireless/intel/iwlwifi/iwl-7000.c
index 3b3e076571d6..45e2efc70d19 100644
--- a/drivers/net/wireless/intel/iwlwifi/iwl-7000.c
+++ b/drivers/net/wireless/intel/iwlwifi/iwl-7000.c
@@ -79,8 +79,8 @@
/* Lowest firmware API version supported */
#define IWL7260_UCODE_API_MIN 17
#define IWL7265_UCODE_API_MIN 17
-#define IWL7265D_UCODE_API_MIN 17
-#define IWL3168_UCODE_API_MIN 20
+#define IWL7265D_UCODE_API_MIN 22
+#define IWL3168_UCODE_API_MIN 22
/* NVM versions */
#define IWL7260_NVM_VERSION 0x0a1d
diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-8000.c b/drivers/net/wireless/intel/iwlwifi/iwl-8000.c
index b9718c0cf174..89137717c1fc 100644
--- a/drivers/net/wireless/intel/iwlwifi/iwl-8000.c
+++ b/drivers/net/wireless/intel/iwlwifi/iwl-8000.c
@@ -74,8 +74,8 @@
#define IWL8265_UCODE_API_MAX 30
/* Lowest firmware API version supported */
-#define IWL8000_UCODE_API_MIN 17
-#define IWL8265_UCODE_API_MIN 20
+#define IWL8000_UCODE_API_MIN 22
+#define IWL8265_UCODE_API_MIN 22
/* NVM versions */
#define IWL8000_NVM_VERSION 0x0a1d
diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-prph.h b/drivers/net/wireless/intel/iwlwifi/iwl-prph.h
index 306bc967742e..77efbb78e867 100644
--- a/drivers/net/wireless/intel/iwlwifi/iwl-prph.h
+++ b/drivers/net/wireless/intel/iwlwifi/iwl-prph.h
@@ -370,6 +370,7 @@
#define MON_DMARB_RD_DATA_ADDR (0xa03c5c)
#define DBGC_IN_SAMPLE (0xa03c00)
+#define DBGC_OUT_CTRL (0xa03c0c)
/* enable the ID buf for read */
#define WFPM_PS_CTL_CLR 0xA0300C
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/fw-api-rs.h b/drivers/net/wireless/intel/iwlwifi/mvm/fw-api-rs.h
index 1b7d265ffb0a..a10c6aae9ab9 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/fw-api-rs.h
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/fw-api-rs.h
@@ -307,6 +307,11 @@ enum {
/* Bit 1-3: LQ command color. Used to match responses to LQ commands */
#define LQ_FLAG_COLOR_POS 1
#define LQ_FLAG_COLOR_MSK (7 << LQ_FLAG_COLOR_POS)
+#define LQ_FLAG_COLOR_GET(_f) (((_f) & LQ_FLAG_COLOR_MSK) >>\
+ LQ_FLAG_COLOR_POS)
+#define LQ_FLAGS_COLOR_INC(_c) ((((_c) + 1) << LQ_FLAG_COLOR_POS) &\
+ LQ_FLAG_COLOR_MSK)
+#define LQ_FLAG_COLOR_SET(_f, _c) ((_c) | ((_f) & ~LQ_FLAG_COLOR_MSK))
/* Bit 4-5: Tx RTS BW Signalling
* (0) No RTS BW signalling
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/fw-api-tx.h b/drivers/net/wireless/intel/iwlwifi/mvm/fw-api-tx.h
index 81b98915b1a4..1360ebfdc51b 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/fw-api-tx.h
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/fw-api-tx.h
@@ -519,8 +519,11 @@ struct agg_tx_status {
* bit-7 invalid rate indication
*/
#define TX_RES_INIT_RATE_INDEX_MSK 0x0f
+#define TX_RES_RATE_TABLE_COLOR_POS 4
#define TX_RES_RATE_TABLE_COLOR_MSK 0x70
#define TX_RES_INV_RATE_INDEX_MSK 0x80
+#define TX_RES_RATE_TABLE_COL_GET(_f) (((_f) & TX_RES_RATE_TABLE_COLOR_MSK) >>\
+ TX_RES_RATE_TABLE_COLOR_POS)
#define IWL_MVM_TX_RES_GET_TID(_ra_tid) ((_ra_tid) & 0x0f)
#define IWL_MVM_TX_RES_GET_RA(_ra_tid) ((_ra_tid) >> 4)
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/fw-dbg.c b/drivers/net/wireless/intel/iwlwifi/mvm/fw-dbg.c
index 7b86a4f1b574..c8712e6eea74 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/fw-dbg.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/fw-dbg.c
@@ -1002,14 +1002,6 @@ int iwl_mvm_fw_dbg_collect_trig(struct iwl_mvm *mvm,
return 0;
}
-static inline void iwl_mvm_restart_early_start(struct iwl_mvm *mvm)
-{
- if (mvm->cfg->device_family == IWL_DEVICE_FAMILY_7000)
- iwl_clear_bits_prph(mvm->trans, MON_BUFF_SAMPLE_CTL, 0x100);
- else
- iwl_write_prph(mvm->trans, DBGC_IN_SAMPLE, 1);
-}
-
int iwl_mvm_start_fw_dbg_conf(struct iwl_mvm *mvm, u8 conf_id)
{
u8 *ptr;
@@ -1023,10 +1015,8 @@ int iwl_mvm_start_fw_dbg_conf(struct iwl_mvm *mvm, u8 conf_id)
/* EARLY START - firmware's configuration is hard coded */
if ((!mvm->fw->dbg_conf_tlv[conf_id] ||
!mvm->fw->dbg_conf_tlv[conf_id]->num_of_hcmds) &&
- conf_id == FW_DBG_START_FROM_ALIVE) {
- iwl_mvm_restart_early_start(mvm);
+ conf_id == FW_DBG_START_FROM_ALIVE)
return 0;
- }
if (!mvm->fw->dbg_conf_tlv[conf_id])
return -EINVAL;
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mac-ctxt.c b/drivers/net/wireless/intel/iwlwifi/mvm/mac-ctxt.c
index 0f1831b41915..fd2fc46e2fe5 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/mac-ctxt.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/mac-ctxt.c
@@ -1040,7 +1040,7 @@ static int iwl_mvm_mac_ctxt_send_beacon(struct iwl_mvm *mvm,
struct iwl_mac_beacon_cmd_v6 beacon_cmd_v6;
struct iwl_mac_beacon_cmd_v7 beacon_cmd;
} u = {};
- struct iwl_mac_beacon_cmd beacon_cmd;
+ struct iwl_mac_beacon_cmd beacon_cmd = {};
struct ieee80211_tx_info *info;
u32 beacon_skb_len;
u32 rate, tx_flags;
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h b/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h
index 4e74a6b90e70..52f8d7a6a7dc 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h
@@ -1730,8 +1730,11 @@ int iwl_mvm_find_free_queue(struct iwl_mvm *mvm, u8 sta_id, u8 minq, u8 maxq);
*/
static inline u32 iwl_mvm_flushable_queues(struct iwl_mvm *mvm)
{
+ u32 cmd_queue = iwl_mvm_is_dqa_supported(mvm) ? IWL_MVM_DQA_CMD_QUEUE :
+ IWL_MVM_CMD_QUEUE;
+
return ((BIT(mvm->cfg->base_params->num_of_queues) - 1) &
- ~BIT(IWL_MVM_CMD_QUEUE));
+ ~BIT(cmd_queue));
}
static inline
@@ -1753,6 +1756,7 @@ static inline void iwl_mvm_stop_device(struct iwl_mvm *mvm)
if (!iwl_mvm_has_new_tx_api(mvm))
iwl_free_fw_paging(mvm);
mvm->ucode_loaded = false;
+ mvm->fw_dbg_conf = FW_DBG_INVALID;
iwl_trans_stop_device(mvm->trans);
}
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/ops.c b/drivers/net/wireless/intel/iwlwifi/mvm/ops.c
index 9ffff6ed8133..3da5ec40aaea 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/ops.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/ops.c
@@ -1149,21 +1149,37 @@ static void iwl_mvm_fw_error_dump_wk(struct work_struct *work)
mutex_lock(&mvm->mutex);
- /* stop recording */
if (mvm->cfg->device_family == IWL_DEVICE_FAMILY_7000) {
+ /* stop recording */
iwl_set_bits_prph(mvm->trans, MON_BUFF_SAMPLE_CTL, 0x100);
+
+ iwl_mvm_fw_error_dump(mvm);
+
+ /* start recording again if the firmware is not crashed */
+ if (!test_bit(STATUS_FW_ERROR, &mvm->trans->status) &&
+ mvm->fw->dbg_dest_tlv)
+ iwl_clear_bits_prph(mvm->trans,
+ MON_BUFF_SAMPLE_CTL, 0x100);
} else {
+ u32 in_sample = iwl_read_prph(mvm->trans, DBGC_IN_SAMPLE);
+ u32 out_ctrl = iwl_read_prph(mvm->trans, DBGC_OUT_CTRL);
+
+ /* stop recording */
iwl_write_prph(mvm->trans, DBGC_IN_SAMPLE, 0);
- /* wait before we collect the data till the DBGC stop */
udelay(100);
- }
+ iwl_write_prph(mvm->trans, DBGC_OUT_CTRL, 0);
+ /* wait before we collect the data till the DBGC stop */
+ udelay(500);
- iwl_mvm_fw_error_dump(mvm);
+ iwl_mvm_fw_error_dump(mvm);
- /* start recording again if the firmware is not crashed */
- WARN_ON_ONCE((!test_bit(STATUS_FW_ERROR, &mvm->trans->status)) &&
- mvm->fw->dbg_dest_tlv &&
- iwl_mvm_start_fw_dbg_conf(mvm, mvm->fw_dbg_conf));
+ /* start recording again if the firmware is not crashed */
+ if (!test_bit(STATUS_FW_ERROR, &mvm->trans->status) &&
+ mvm->fw->dbg_dest_tlv) {
+ iwl_write_prph(mvm->trans, DBGC_IN_SAMPLE, in_sample);
+ iwl_write_prph(mvm->trans, DBGC_OUT_CTRL, out_ctrl);
+ }
+ }
mutex_unlock(&mvm->mutex);
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/rs.c b/drivers/net/wireless/intel/iwlwifi/mvm/rs.c
index 7788eefcd2bd..aa785cf3cf68 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/rs.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/rs.c
@@ -2,7 +2,7 @@
*
* Copyright(c) 2005 - 2014 Intel Corporation. All rights reserved.
* Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH
- * Copyright(c) 2016 Intel Deutschland GmbH
+ * Copyright(c) 2016 - 2017 Intel Deutschland GmbH
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of version 2 of the GNU General Public License as
@@ -1083,34 +1083,6 @@ static void rs_get_lower_rate_down_column(struct iwl_lq_sta *lq_sta,
rs_get_lower_rate_in_column(lq_sta, rate);
}
-/* Check if both rates are identical
- * allow_ant_mismatch enables matching a SISO rate on ANT_A or ANT_B
- * with a rate indicating STBC/BFER and ANT_AB.
- */
-static inline bool rs_rate_equal(struct rs_rate *a,
- struct rs_rate *b,
- bool allow_ant_mismatch)
-
-{
- bool ant_match = (a->ant == b->ant) && (a->stbc == b->stbc) &&
- (a->bfer == b->bfer);
-
- if (allow_ant_mismatch) {
- if (a->stbc || a->bfer) {
- WARN_ONCE(a->ant != ANT_AB, "stbc %d bfer %d ant %d",
- a->stbc, a->bfer, a->ant);
- ant_match |= (b->ant == ANT_A || b->ant == ANT_B);
- } else if (b->stbc || b->bfer) {
- WARN_ONCE(b->ant != ANT_AB, "stbc %d bfer %d ant %d",
- b->stbc, b->bfer, b->ant);
- ant_match |= (a->ant == ANT_A || a->ant == ANT_B);
- }
- }
-
- return (a->type == b->type) && (a->bw == b->bw) && (a->sgi == b->sgi) &&
- (a->ldpc == b->ldpc) && (a->index == b->index) && ant_match;
-}
-
/* Check if both rates share the same column */
static inline bool rs_rate_column_match(struct rs_rate *a,
struct rs_rate *b)
@@ -1182,12 +1154,12 @@ void iwl_mvm_rs_tx_status(struct iwl_mvm *mvm, struct ieee80211_sta *sta,
u32 lq_hwrate;
struct rs_rate lq_rate, tx_resp_rate;
struct iwl_scale_tbl_info *curr_tbl, *other_tbl, *tmp_tbl;
- u8 reduced_txp = (uintptr_t)info->status.status_driver_data[0];
+ u32 tlc_info = (uintptr_t)info->status.status_driver_data[0];
+ u8 reduced_txp = tlc_info & RS_DRV_DATA_TXP_MSK;
+ u8 lq_color = RS_DRV_DATA_LQ_COLOR_GET(tlc_info);
u32 tx_resp_hwrate = (uintptr_t)info->status.status_driver_data[1];
struct iwl_mvm_sta *mvmsta = iwl_mvm_sta_from_mac80211(sta);
struct iwl_lq_sta *lq_sta = &mvmsta->lq_sta;
- bool allow_ant_mismatch = fw_has_api(&mvm->fw->ucode_capa,
- IWL_UCODE_TLV_API_LQ_SS_PARAMS);
/* Treat uninitialized rate scaling data same as non-existing. */
if (!lq_sta) {
@@ -1262,10 +1234,10 @@ void iwl_mvm_rs_tx_status(struct iwl_mvm *mvm, struct ieee80211_sta *sta,
rs_rate_from_ucode_rate(lq_hwrate, info->band, &lq_rate);
/* Here we actually compare this rate to the latest LQ command */
- if (!rs_rate_equal(&tx_resp_rate, &lq_rate, allow_ant_mismatch)) {
+ if (lq_color != LQ_FLAG_COLOR_GET(table->flags)) {
IWL_DEBUG_RATE(mvm,
- "initial tx resp rate 0x%x does not match 0x%x\n",
- tx_resp_hwrate, lq_hwrate);
+ "tx resp color 0x%x does not match 0x%x\n",
+ lq_color, LQ_FLAG_COLOR_GET(table->flags));
/*
* Since rates mis-match, the last LQ command may have failed.
@@ -3326,6 +3298,7 @@ static void rs_build_rates_table(struct iwl_mvm *mvm,
u8 valid_tx_ant = 0;
struct iwl_lq_cmd *lq_cmd = &lq_sta->lq;
bool toggle_ant = false;
+ u32 color;
memcpy(&rate, initial_rate, sizeof(rate));
@@ -3380,6 +3353,9 @@ static void rs_build_rates_table(struct iwl_mvm *mvm,
num_rates, num_retries, valid_tx_ant,
toggle_ant);
+ /* update the color of the LQ command (as a counter at bits 1-3) */
+ color = LQ_FLAGS_COLOR_INC(LQ_FLAG_COLOR_GET(lq_cmd->flags));
+ lq_cmd->flags = LQ_FLAG_COLOR_SET(lq_cmd->flags, color);
}
struct rs_bfer_active_iter_data {
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/rs.h b/drivers/net/wireless/intel/iwlwifi/mvm/rs.h
index ee207f2c0a90..3abde1cb0303 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/rs.h
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/rs.h
@@ -2,6 +2,7 @@
*
* Copyright(c) 2003 - 2014 Intel Corporation. All rights reserved.
* Copyright(c) 2015 Intel Mobile Communications GmbH
+ * Copyright(c) 2017 Intel Deutschland GmbH
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of version 2 of the GNU General Public License as
@@ -357,6 +358,20 @@ struct iwl_lq_sta {
} pers;
};
+/* ieee80211_tx_info's status_driver_data[0] is packed with lq color and txp
+ * Note, it's iwlmvm <-> mac80211 interface.
+ * bits 0-7: reduced tx power
+ * bits 8-10: LQ command's color
+ */
+#define RS_DRV_DATA_TXP_MSK 0xff
+#define RS_DRV_DATA_LQ_COLOR_POS 8
+#define RS_DRV_DATA_LQ_COLOR_MSK (7 << RS_DRV_DATA_LQ_COLOR_POS)
+#define RS_DRV_DATA_LQ_COLOR_GET(_f) (((_f) & RS_DRV_DATA_LQ_COLOR_MSK) >>\
+ RS_DRV_DATA_LQ_COLOR_POS)
+#define RS_DRV_DATA_PACK(_c, _p) ((void *)(uintptr_t)\
+ (((uintptr_t)_p) |\
+ ((_c) << RS_DRV_DATA_LQ_COLOR_POS)))
+
/* Initialize station's rate scaling information after adding station */
void iwl_mvm_rs_rate_init(struct iwl_mvm *mvm, struct ieee80211_sta *sta,
enum nl80211_band band, bool init);
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/sta.c b/drivers/net/wireless/intel/iwlwifi/mvm/sta.c
index f5c786ddc526..614d67810d05 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/sta.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/sta.c
@@ -2120,7 +2120,8 @@ int iwl_mvm_add_mcast_sta(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
if (!iwl_mvm_is_dqa_supported(mvm))
return 0;
- if (WARN_ON(vif->type != NL80211_IFTYPE_AP))
+ if (WARN_ON(vif->type != NL80211_IFTYPE_AP &&
+ vif->type != NL80211_IFTYPE_ADHOC))
return -ENOTSUPP;
/*
@@ -2155,6 +2156,16 @@ int iwl_mvm_add_mcast_sta(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
mvmvif->cab_queue = queue;
} else if (!fw_has_api(&mvm->fw->ucode_capa,
IWL_UCODE_TLV_API_STA_TYPE)) {
+ /*
+ * In IBSS, ieee80211_check_queues() sets the cab_queue to be
+ * invalid, so make sure we use the queue we want.
+ * Note that this is done here as we want to avoid making DQA
+ * changes in mac80211 layer.
+ */
+ if (vif->type == NL80211_IFTYPE_ADHOC) {
+ vif->cab_queue = IWL_MVM_DQA_GCAST_QUEUE;
+ mvmvif->cab_queue = vif->cab_queue;
+ }
iwl_mvm_enable_txq(mvm, vif->cab_queue, vif->cab_queue, 0,
&cfg, timeout);
}
@@ -3321,18 +3332,15 @@ int iwl_mvm_remove_sta_key(struct iwl_mvm *mvm,
/* Get the station from the mvm local station table */
mvm_sta = iwl_mvm_get_key_sta(mvm, vif, sta);
- if (!mvm_sta) {
- IWL_ERR(mvm, "Failed to find station\n");
- return -EINVAL;
- }
- sta_id = mvm_sta->sta_id;
+ if (mvm_sta)
+ sta_id = mvm_sta->sta_id;
IWL_DEBUG_WEP(mvm, "mvm remove dynamic key: idx=%d sta=%d\n",
keyconf->keyidx, sta_id);
- if (keyconf->cipher == WLAN_CIPHER_SUITE_AES_CMAC ||
- keyconf->cipher == WLAN_CIPHER_SUITE_BIP_GMAC_128 ||
- keyconf->cipher == WLAN_CIPHER_SUITE_BIP_GMAC_256)
+ if (mvm_sta && (keyconf->cipher == WLAN_CIPHER_SUITE_AES_CMAC ||
+ keyconf->cipher == WLAN_CIPHER_SUITE_BIP_GMAC_128 ||
+ keyconf->cipher == WLAN_CIPHER_SUITE_BIP_GMAC_256))
return iwl_mvm_send_sta_igtk(mvm, keyconf, sta_id, true);
if (!__test_and_clear_bit(keyconf->hw_key_idx, mvm->fw_key_table)) {
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/sta.h b/drivers/net/wireless/intel/iwlwifi/mvm/sta.h
index 2716cb5483bf..ad62b67dceb2 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/sta.h
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/sta.h
@@ -313,6 +313,7 @@ enum iwl_mvm_agg_state {
* This is basically (last acked packet++).
* @rate_n_flags: Rate at which Tx was attempted. Holds the data between the
* Tx response (TX_CMD), and the block ack notification (COMPRESSED_BA).
+ * @lq_color: the color of the LQ command as it appears in tx response.
* @amsdu_in_ampdu_allowed: true if A-MSDU in A-MPDU is allowed.
* @state: state of the BA agreement establishment / tear down.
* @txq_id: Tx queue used by the BA session / DQA
@@ -331,6 +332,7 @@ struct iwl_mvm_tid_data {
u16 next_reclaimed;
/* The rest is Tx AGG related */
u32 rate_n_flags;
+ u8 lq_color;
bool amsdu_in_ampdu_allowed;
enum iwl_mvm_agg_state state;
u16 txq_id;
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/tt.c b/drivers/net/wireless/intel/iwlwifi/mvm/tt.c
index f9cbd197246f..506d58104e1c 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/tt.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/tt.c
@@ -790,11 +790,13 @@ static int iwl_mvm_tcool_set_cur_state(struct thermal_cooling_device *cdev,
struct iwl_mvm *mvm = (struct iwl_mvm *)(cdev->devdata);
int ret;
- if (!mvm->ucode_loaded || !(mvm->cur_ucode == IWL_UCODE_REGULAR))
- return -EIO;
-
mutex_lock(&mvm->mutex);
+ if (!mvm->ucode_loaded || !(mvm->cur_ucode == IWL_UCODE_REGULAR)) {
+ ret = -EIO;
+ goto unlock;
+ }
+
if (new_state >= ARRAY_SIZE(iwl_mvm_cdev_budgets)) {
ret = -EINVAL;
goto unlock;
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/tx.c b/drivers/net/wireless/intel/iwlwifi/mvm/tx.c
index bcaceb64a6e8..f21901cd4a4f 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/tx.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/tx.c
@@ -1323,6 +1323,7 @@ static void iwl_mvm_rx_tx_cmd_single(struct iwl_mvm *mvm,
struct iwl_mvm_sta *mvmsta;
struct sk_buff_head skbs;
u8 skb_freed = 0;
+ u8 lq_color;
u16 next_reclaimed, seq_ctl;
bool is_ndp = false;
@@ -1405,8 +1406,9 @@ static void iwl_mvm_rx_tx_cmd_single(struct iwl_mvm *mvm,
info->status.tx_time =
le16_to_cpu(tx_resp->wireless_media_time);
BUILD_BUG_ON(ARRAY_SIZE(info->status.status_driver_data) < 1);
+ lq_color = TX_RES_RATE_TABLE_COL_GET(tx_resp->tlc_info);
info->status.status_driver_data[0] =
- (void *)(uintptr_t)tx_resp->reduced_tpc;
+ RS_DRV_DATA_PACK(lq_color, tx_resp->reduced_tpc);
ieee80211_tx_status(mvm->hw, skb);
}
@@ -1638,6 +1640,9 @@ static void iwl_mvm_rx_tx_cmd_agg(struct iwl_mvm *mvm,
le32_to_cpu(tx_resp->initial_rate);
mvmsta->tid_data[tid].tx_time =
le16_to_cpu(tx_resp->wireless_media_time);
+ mvmsta->tid_data[tid].lq_color =
+ (tx_resp->tlc_info & TX_RES_RATE_TABLE_COLOR_MSK) >>
+ TX_RES_RATE_TABLE_COLOR_POS;
}
rcu_read_unlock();
@@ -1707,6 +1712,11 @@ static void iwl_mvm_tx_reclaim(struct iwl_mvm *mvm, int sta_id, int tid,
iwl_mvm_check_ratid_empty(mvm, sta, tid);
freed = 0;
+
+ /* pack lq color from tid_data along the reduced txp */
+ ba_info->status.status_driver_data[0] =
+ RS_DRV_DATA_PACK(tid_data->lq_color,
+ ba_info->status.status_driver_data[0]);
ba_info->status.status_driver_data[1] = (void *)(uintptr_t)rate;
skb_queue_walk(&reclaimed_skbs, skb) {
diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/trans.c b/drivers/net/wireless/intel/iwlwifi/pcie/trans.c
index 70acf850a9f1..93cbc7a69bcd 100644
--- a/drivers/net/wireless/intel/iwlwifi/pcie/trans.c
+++ b/drivers/net/wireless/intel/iwlwifi/pcie/trans.c
@@ -2803,7 +2803,8 @@ static struct iwl_trans_dump_data
#ifdef CONFIG_PM_SLEEP
static int iwl_trans_pcie_suspend(struct iwl_trans *trans)
{
- if (trans->runtime_pm_mode == IWL_PLAT_PM_MODE_D0I3)
+ if (trans->runtime_pm_mode == IWL_PLAT_PM_MODE_D0I3 &&
+ (trans->system_pm_mode == IWL_PLAT_PM_MODE_D0I3))
return iwl_pci_fw_enter_d0i3(trans);
return 0;
@@ -2811,7 +2812,8 @@ static int iwl_trans_pcie_suspend(struct iwl_trans *trans)
static void iwl_trans_pcie_resume(struct iwl_trans *trans)
{
- if (trans->runtime_pm_mode == IWL_PLAT_PM_MODE_D0I3)
+ if (trans->runtime_pm_mode == IWL_PLAT_PM_MODE_D0I3 &&
+ (trans->system_pm_mode == IWL_PLAT_PM_MODE_D0I3))
iwl_pci_fw_exit_d0i3(trans);
}
#endif /* CONFIG_PM_SLEEP */
diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/tx-gen2.c b/drivers/net/wireless/intel/iwlwifi/pcie/tx-gen2.c
index 9fb46a6f47cf..9c9bfbbabdf1 100644
--- a/drivers/net/wireless/intel/iwlwifi/pcie/tx-gen2.c
+++ b/drivers/net/wireless/intel/iwlwifi/pcie/tx-gen2.c
@@ -906,7 +906,7 @@ int iwl_trans_pcie_dyn_txq_alloc(struct iwl_trans *trans,
if (WARN_ON(iwl_rx_packet_payload_len(hcmd.resp_pkt) != sizeof(*rsp))) {
ret = -EINVAL;
- goto error;
+ goto error_free_resp;
}
rsp = (void *)hcmd.resp_pkt->data;
@@ -915,13 +915,13 @@ int iwl_trans_pcie_dyn_txq_alloc(struct iwl_trans *trans,
if (qid > ARRAY_SIZE(trans_pcie->txq)) {
WARN_ONCE(1, "queue index %d unsupported", qid);
ret = -EIO;
- goto error;
+ goto error_free_resp;
}
if (test_and_set_bit(qid, trans_pcie->queue_used)) {
WARN_ONCE(1, "queue %d already used", qid);
ret = -EIO;
- goto error;
+ goto error_free_resp;
}
txq->id = qid;
@@ -934,8 +934,11 @@ int iwl_trans_pcie_dyn_txq_alloc(struct iwl_trans *trans,
(txq->write_ptr) | (qid << 16));
IWL_DEBUG_TX_QUEUES(trans, "Activate queue %d\n", qid);
+ iwl_free_resp(&hcmd);
return qid;
+error_free_resp:
+ iwl_free_resp(&hcmd);
error:
iwl_pcie_gen2_txq_free_memory(trans, txq);
return ret;
diff --git a/drivers/net/wireless/intersil/hostap/hostap_ioctl.c b/drivers/net/wireless/intersil/hostap/hostap_ioctl.c
index b2c6b065b542..ff153ce29539 100644
--- a/drivers/net/wireless/intersil/hostap/hostap_ioctl.c
+++ b/drivers/net/wireless/intersil/hostap/hostap_ioctl.c
@@ -2544,7 +2544,7 @@ static int prism2_ioctl_priv_prism2_param(struct net_device *dev,
ret = -EINVAL;
}
if (local->iw_mode == IW_MODE_MASTER) {
- wait_queue_t __wait;
+ wait_queue_entry_t __wait;
init_waitqueue_entry(&__wait, current);
add_wait_queue(&local->hostscan_wq, &__wait);
set_current_state(TASK_INTERRUPTIBLE);
diff --git a/drivers/net/wireless/intersil/hostap/hostap_main.c b/drivers/net/wireless/intersil/hostap/hostap_main.c
index 544fc09dcb62..1372b20f931e 100644
--- a/drivers/net/wireless/intersil/hostap/hostap_main.c
+++ b/drivers/net/wireless/intersil/hostap/hostap_main.c
@@ -73,7 +73,7 @@ struct net_device * hostap_add_interface(struct local_info *local,
dev->mem_end = mdev->mem_end;
hostap_setup_dev(dev, local, type);
- dev->destructor = free_netdev;
+ dev->needs_free_netdev = true;
sprintf(dev->name, "%s%s", prefix, name);
if (!rtnl_locked)
diff --git a/drivers/net/wireless/mac80211_hwsim.c b/drivers/net/wireless/mac80211_hwsim.c
index 002b25cff5b6..c854a557998b 100644
--- a/drivers/net/wireless/mac80211_hwsim.c
+++ b/drivers/net/wireless/mac80211_hwsim.c
@@ -2861,7 +2861,7 @@ static const struct net_device_ops hwsim_netdev_ops = {
static void hwsim_mon_setup(struct net_device *dev)
{
dev->netdev_ops = &hwsim_netdev_ops;
- dev->destructor = free_netdev;
+ dev->needs_free_netdev = true;
ether_setup(dev);
dev->priv_flags |= IFF_NO_QUEUE;
dev->type = ARPHRD_IEEE80211_RADIOTAP;
diff --git a/drivers/net/wireless/marvell/libertas/main.c b/drivers/net/wireless/marvell/libertas/main.c
index e3500203715c..dde065d0d5c1 100644
--- a/drivers/net/wireless/marvell/libertas/main.c
+++ b/drivers/net/wireless/marvell/libertas/main.c
@@ -453,7 +453,7 @@ static int lbs_thread(void *data)
{
struct net_device *dev = data;
struct lbs_private *priv = dev->ml_priv;
- wait_queue_t wait;
+ wait_queue_entry_t wait;
lbs_deb_enter(LBS_DEB_THREAD);
diff --git a/drivers/net/wireless/marvell/mwifiex/main.c b/drivers/net/wireless/marvell/mwifiex/main.c
index dd87b9ff64c3..39b6b5e3f6e0 100644
--- a/drivers/net/wireless/marvell/mwifiex/main.c
+++ b/drivers/net/wireless/marvell/mwifiex/main.c
@@ -1280,7 +1280,7 @@ void mwifiex_init_priv_params(struct mwifiex_private *priv,
struct net_device *dev)
{
dev->netdev_ops = &mwifiex_netdev_ops;
- dev->destructor = free_netdev;
+ dev->needs_free_netdev = true;
/* Initialize private structure */
priv->current_key_index = 0;
priv->media_connected = false;
diff --git a/drivers/net/xen-netback/common.h b/drivers/net/xen-netback/common.h
index 530586be05b4..5b1d2e8402d9 100644
--- a/drivers/net/xen-netback/common.h
+++ b/drivers/net/xen-netback/common.h
@@ -199,6 +199,7 @@ struct xenvif_queue { /* Per-queue data for xenvif */
unsigned long remaining_credit;
struct timer_list credit_timeout;
u64 credit_window_start;
+ bool rate_limited;
/* Statistics */
struct xenvif_stats stats;
diff --git a/drivers/net/xen-netback/interface.c b/drivers/net/xen-netback/interface.c
index 8397f6c92451..e322a862ddfe 100644
--- a/drivers/net/xen-netback/interface.c
+++ b/drivers/net/xen-netback/interface.c
@@ -106,7 +106,11 @@ static int xenvif_poll(struct napi_struct *napi, int budget)
if (work_done < budget) {
napi_complete_done(napi, work_done);
- xenvif_napi_schedule_or_enable_events(queue);
+ /* If the queue is rate-limited, it shall be
+ * rescheduled in the timer callback.
+ */
+ if (likely(!queue->rate_limited))
+ xenvif_napi_schedule_or_enable_events(queue);
}
return work_done;
diff --git a/drivers/net/xen-netback/netback.c b/drivers/net/xen-netback/netback.c
index 602d408fa25e..5042ff8d449a 100644
--- a/drivers/net/xen-netback/netback.c
+++ b/drivers/net/xen-netback/netback.c
@@ -180,6 +180,7 @@ static void tx_add_credit(struct xenvif_queue *queue)
max_credit = ULONG_MAX; /* wrapped: clamp to ULONG_MAX */
queue->remaining_credit = min(max_credit, max_burst);
+ queue->rate_limited = false;
}
void xenvif_tx_credit_callback(unsigned long data)
@@ -686,8 +687,10 @@ static bool tx_credit_exceeded(struct xenvif_queue *queue, unsigned size)
msecs_to_jiffies(queue->credit_usec / 1000);
/* Timer could already be pending in rare cases. */
- if (timer_pending(&queue->credit_timeout))
+ if (timer_pending(&queue->credit_timeout)) {
+ queue->rate_limited = true;
return true;
+ }
/* Passed the point where we can replenish credit? */
if (time_after_eq64(now, next_credit)) {
@@ -702,6 +705,7 @@ static bool tx_credit_exceeded(struct xenvif_queue *queue, unsigned size)
mod_timer(&queue->credit_timeout,
next_credit);
queue->credit_window_start = next_credit;
+ queue->rate_limited = true;
return true;
}
diff --git a/drivers/ntb/hw/intel/ntb_hw_intel.c b/drivers/ntb/hw/intel/ntb_hw_intel.c
index c00238491673..7b3b6fd63d7d 100644
--- a/drivers/ntb/hw/intel/ntb_hw_intel.c
+++ b/drivers/ntb/hw/intel/ntb_hw_intel.c
@@ -2878,7 +2878,7 @@ static const struct intel_ntb_reg skx_reg = {
.link_is_up = xeon_link_is_up,
.db_ioread = skx_db_ioread,
.db_iowrite = skx_db_iowrite,
- .db_size = sizeof(u64),
+ .db_size = sizeof(u32),
.ntb_ctl = SKX_NTBCNTL_OFFSET,
.mw_bar = {2, 4},
};
diff --git a/drivers/ntb/ntb_transport.c b/drivers/ntb/ntb_transport.c
index 02ca45fdd892..10e5bf460139 100644
--- a/drivers/ntb/ntb_transport.c
+++ b/drivers/ntb/ntb_transport.c
@@ -177,14 +177,12 @@ struct ntb_transport_qp {
u64 rx_err_ver;
u64 rx_memcpy;
u64 rx_async;
- u64 dma_rx_prep_err;
u64 tx_bytes;
u64 tx_pkts;
u64 tx_ring_full;
u64 tx_err_no_buf;
u64 tx_memcpy;
u64 tx_async;
- u64 dma_tx_prep_err;
};
struct ntb_transport_mw {
@@ -254,8 +252,6 @@ enum {
#define QP_TO_MW(nt, qp) ((qp) % nt->mw_count)
#define NTB_QP_DEF_NUM_ENTRIES 100
#define NTB_LINK_DOWN_TIMEOUT 10
-#define DMA_RETRIES 20
-#define DMA_OUT_RESOURCE_TO msecs_to_jiffies(50)
static void ntb_transport_rxc_db(unsigned long data);
static const struct ntb_ctx_ops ntb_transport_ops;
@@ -516,12 +512,6 @@ static ssize_t debugfs_read(struct file *filp, char __user *ubuf, size_t count,
out_offset += snprintf(buf + out_offset, out_count - out_offset,
"free tx - \t%u\n",
ntb_transport_tx_free_entry(qp));
- out_offset += snprintf(buf + out_offset, out_count - out_offset,
- "DMA tx prep err - \t%llu\n",
- qp->dma_tx_prep_err);
- out_offset += snprintf(buf + out_offset, out_count - out_offset,
- "DMA rx prep err - \t%llu\n",
- qp->dma_rx_prep_err);
out_offset += snprintf(buf + out_offset, out_count - out_offset,
"\n");
@@ -623,7 +613,7 @@ static int ntb_transport_setup_qp_mw(struct ntb_transport_ctx *nt,
if (!mw->virt_addr)
return -ENOMEM;
- if (qp_count % mw_count && mw_num + 1 < qp_count / mw_count)
+ if (mw_num < qp_count % mw_count)
num_qps_mw = qp_count / mw_count + 1;
else
num_qps_mw = qp_count / mw_count;
@@ -768,8 +758,6 @@ static void ntb_qp_link_down_reset(struct ntb_transport_qp *qp)
qp->tx_err_no_buf = 0;
qp->tx_memcpy = 0;
qp->tx_async = 0;
- qp->dma_tx_prep_err = 0;
- qp->dma_rx_prep_err = 0;
}
static void ntb_qp_link_cleanup(struct ntb_transport_qp *qp)
@@ -1000,7 +988,7 @@ static int ntb_transport_init_queue(struct ntb_transport_ctx *nt,
qp->event_handler = NULL;
ntb_qp_link_down_reset(qp);
- if (qp_count % mw_count && mw_num + 1 < qp_count / mw_count)
+ if (mw_num < qp_count % mw_count)
num_qps_mw = qp_count / mw_count + 1;
else
num_qps_mw = qp_count / mw_count;
@@ -1128,8 +1116,8 @@ static int ntb_transport_probe(struct ntb_client *self, struct ntb_dev *ndev)
qp_count = ilog2(qp_bitmap);
if (max_num_clients && max_num_clients < qp_count)
qp_count = max_num_clients;
- else if (mw_count < qp_count)
- qp_count = mw_count;
+ else if (nt->mw_count < qp_count)
+ qp_count = nt->mw_count;
qp_bitmap &= BIT_ULL(qp_count) - 1;
@@ -1317,7 +1305,6 @@ static int ntb_async_rx_submit(struct ntb_queue_entry *entry, void *offset)
struct dmaengine_unmap_data *unmap;
dma_cookie_t cookie;
void *buf = entry->buf;
- int retries = 0;
len = entry->len;
device = chan->device;
@@ -1346,22 +1333,11 @@ static int ntb_async_rx_submit(struct ntb_queue_entry *entry, void *offset)
unmap->from_cnt = 1;
- for (retries = 0; retries < DMA_RETRIES; retries++) {
- txd = device->device_prep_dma_memcpy(chan,
- unmap->addr[1],
- unmap->addr[0], len,
- DMA_PREP_INTERRUPT);
- if (txd)
- break;
-
- set_current_state(TASK_INTERRUPTIBLE);
- schedule_timeout(DMA_OUT_RESOURCE_TO);
- }
-
- if (!txd) {
- qp->dma_rx_prep_err++;
+ txd = device->device_prep_dma_memcpy(chan, unmap->addr[1],
+ unmap->addr[0], len,
+ DMA_PREP_INTERRUPT);
+ if (!txd)
goto err_get_unmap;
- }
txd->callback_result = ntb_rx_copy_callback;
txd->callback_param = entry;
@@ -1606,7 +1582,6 @@ static int ntb_async_tx_submit(struct ntb_transport_qp *qp,
struct dmaengine_unmap_data *unmap;
dma_addr_t dest;
dma_cookie_t cookie;
- int retries = 0;
device = chan->device;
dest = qp->tx_mw_phys + qp->tx_max_frame * entry->tx_index;
@@ -1628,21 +1603,10 @@ static int ntb_async_tx_submit(struct ntb_transport_qp *qp,
unmap->to_cnt = 1;
- for (retries = 0; retries < DMA_RETRIES; retries++) {
- txd = device->device_prep_dma_memcpy(chan, dest,
- unmap->addr[0], len,
- DMA_PREP_INTERRUPT);
- if (txd)
- break;
-
- set_current_state(TASK_INTERRUPTIBLE);
- schedule_timeout(DMA_OUT_RESOURCE_TO);
- }
-
- if (!txd) {
- qp->dma_tx_prep_err++;
+ txd = device->device_prep_dma_memcpy(chan, dest, unmap->addr[0], len,
+ DMA_PREP_INTERRUPT);
+ if (!txd)
goto err_get_unmap;
- }
txd->callback_result = ntb_tx_copy_callback;
txd->callback_param = entry;
diff --git a/drivers/ntb/test/ntb_perf.c b/drivers/ntb/test/ntb_perf.c
index 434e1d474f33..5cab2831ce99 100644
--- a/drivers/ntb/test/ntb_perf.c
+++ b/drivers/ntb/test/ntb_perf.c
@@ -90,11 +90,11 @@ MODULE_PARM_DESC(max_mw_size, "Limit size of large memory windows");
static unsigned int seg_order = 19; /* 512K */
module_param(seg_order, uint, 0644);
-MODULE_PARM_DESC(seg_order, "size order [n^2] of buffer segment for testing");
+MODULE_PARM_DESC(seg_order, "size order [2^n] of buffer segment for testing");
static unsigned int run_order = 32; /* 4G */
module_param(run_order, uint, 0644);
-MODULE_PARM_DESC(run_order, "size order [n^2] of total data to transfer");
+MODULE_PARM_DESC(run_order, "size order [2^n] of total data to transfer");
static bool use_dma; /* default to 0 */
module_param(use_dma, bool, 0644);
diff --git a/drivers/nubus/nubus.c b/drivers/nubus/nubus.c
index 77a48a5164ff..df431e8a0631 100644
--- a/drivers/nubus/nubus.c
+++ b/drivers/nubus/nubus.c
@@ -13,7 +13,6 @@
#include <linux/nubus.h>
#include <linux/errno.h>
#include <linux/init.h>
-#include <linux/delay.h>
#include <linux/module.h>
#include <linux/slab.h>
#include <asm/setup.h>
@@ -34,14 +33,6 @@ extern void oss_nubus_init(void);
#define NUBUS_TEST_PATTERN 0x5A932BC7
-/* Define this if you like to live dangerously - it is known not to
- work on pretty much every machine except the Quadra 630 and the LC
- III. */
-#undef I_WANT_TO_PROBE_SLOT_ZERO
-
-/* This sometimes helps combat failure to boot */
-#undef TRY_TO_DODGE_WSOD
-
/* Globals */
struct nubus_dev *nubus_devices;
@@ -101,9 +92,6 @@ static void nubus_rewind(unsigned char **ptr, int len, int map)
{
unsigned char *p = *ptr;
- /* Sanity check */
- if (len > 65536)
- pr_err("rewind of 0x%08x!\n", len);
while (len) {
do {
p--;
@@ -117,8 +105,6 @@ static void nubus_advance(unsigned char **ptr, int len, int map)
{
unsigned char *p = *ptr;
- if (len > 65536)
- pr_err("advance of 0x%08x!\n", len);
while (len) {
while (not_useful(p, map))
p++;
@@ -130,10 +116,15 @@ static void nubus_advance(unsigned char **ptr, int len, int map)
static void nubus_move(unsigned char **ptr, int len, int map)
{
+ unsigned long slot_space = (unsigned long)*ptr & 0xFF000000;
+
if (len > 0)
nubus_advance(ptr, len, map);
else if (len < 0)
nubus_rewind(ptr, -len, map);
+
+ if (((unsigned long)*ptr & 0xFF000000) != slot_space)
+ pr_err("%s: moved out of slot address space!\n", __func__);
}
/* Now, functions to read the sResource tree */
@@ -454,10 +445,6 @@ nubus_get_functional_resource(struct nubus_board *board, int slot,
pr_info(" Function 0x%02x:\n", parent->type);
nubus_get_subdir(parent, &dir);
- /* Apple seems to have botched the ROM on the IIx */
- if (slot == 0 && (unsigned long)dir.base % 2)
- dir.base += 1;
-
pr_debug("%s: parent is 0x%p, dir is 0x%p\n",
__func__, parent->base, dir.base);
@@ -691,83 +678,6 @@ static int __init nubus_get_board_resource(struct nubus_board *board, int slot,
return 0;
}
-/* Attempt to bypass the somewhat non-obvious arrangement of
- sResources in the motherboard ROM */
-static void __init nubus_find_rom_dir(struct nubus_board* board)
-{
- unsigned char *rp;
- unsigned char *romdir;
- struct nubus_dir dir;
- struct nubus_dirent ent;
-
- /* Check for the extra directory just under the format block */
- rp = board->fblock;
- nubus_rewind(&rp, 4, board->lanes);
- if (nubus_get_rom(&rp, 4, board->lanes) != NUBUS_TEST_PATTERN) {
- /* OK, the ROM was telling the truth */
- board->directory = board->fblock;
- nubus_move(&board->directory,
- nubus_expand32(board->doffset),
- board->lanes);
- return;
- }
-
- /* On "slot zero", you have to walk down a few more
- directories to get to the equivalent of a real card's root
- directory. We don't know what they were smoking when they
- came up with this. */
- romdir = nubus_rom_addr(board->slot);
- nubus_rewind(&romdir, ROM_DIR_OFFSET, board->lanes);
- dir.base = dir.ptr = romdir;
- dir.done = 0;
- dir.mask = board->lanes;
-
- /* This one points to an "Unknown Macintosh" directory */
- if (nubus_readdir(&dir, &ent) == -1)
- goto badrom;
-
- if (console_loglevel >= CONSOLE_LOGLEVEL_DEBUG)
- printk(KERN_INFO "nubus_get_rom_dir: entry %02x %06x\n", ent.type, ent.data);
- /* This one takes us to where we want to go. */
- if (nubus_readdir(&dir, &ent) == -1)
- goto badrom;
- if (console_loglevel >= CONSOLE_LOGLEVEL_DEBUG)
- printk(KERN_DEBUG "nubus_get_rom_dir: entry %02x %06x\n", ent.type, ent.data);
- nubus_get_subdir(&ent, &dir);
-
- /* Resource ID 01, also an "Unknown Macintosh" */
- if (nubus_readdir(&dir, &ent) == -1)
- goto badrom;
- if (console_loglevel >= CONSOLE_LOGLEVEL_DEBUG)
- printk(KERN_DEBUG "nubus_get_rom_dir: entry %02x %06x\n", ent.type, ent.data);
-
- /* FIXME: the first one is *not* always the right one. We
- suspect this has something to do with the ROM revision.
- "The HORROR ROM" (LC-series) uses 0x7e, while "The HORROR
- Continues" (Q630) uses 0x7b. The DAFB Macs evidently use
- something else. Please run "Slots" on your Mac (see
- include/linux/nubus.h for where to get this program) and
- tell us where the 'SiDirPtr' for Slot 0 is. If you feel
- brave, you should also use MacsBug to walk down the ROM
- directories like this function does and try to find the
- path to that address... */
- if (nubus_readdir(&dir, &ent) == -1)
- goto badrom;
- if (console_loglevel >= CONSOLE_LOGLEVEL_DEBUG)
- printk(KERN_DEBUG "nubus_get_rom_dir: entry %02x %06x\n", ent.type, ent.data);
-
- /* Bwahahahaha... */
- nubus_get_subdir(&ent, &dir);
- board->directory = dir.base;
- return;
-
- /* Even more evil laughter... */
- badrom:
- board->directory = board->fblock;
- nubus_move(&board->directory, nubus_expand32(board->doffset), board->lanes);
- printk(KERN_ERR "nubus_get_rom_dir: ROM weirdness! Notify the developers...\n");
-}
-
/* Add a board (might be many devices) to the list */
static struct nubus_board * __init nubus_add_board(int slot, int bytelanes)
{
@@ -828,8 +738,11 @@ static struct nubus_board * __init nubus_add_board(int slot, int bytelanes)
* since the initial Macintosh ROM releases skipped the check.
*/
- /* Attempt to work around slot zero weirdness */
- nubus_find_rom_dir(board);
+ /* Set up the directory pointer */
+ board->directory = board->fblock;
+ nubus_move(&board->directory, nubus_expand32(board->doffset),
+ board->lanes);
+
nubus_get_root_dir(board, &dir);
/* We're ready to rock */
@@ -849,9 +762,6 @@ static struct nubus_board * __init nubus_add_board(int slot, int bytelanes)
nubus_get_board_resource(board, slot, &ent);
}
- /* Aaaarrrrgghh! The LC III motherboard has *two* board
- resources. I have no idea WTF to do about this. */
-
while (nubus_readdir(&dir, &ent) != -1) {
struct nubus_dev *dev;
struct nubus_dev **devp;
@@ -898,8 +808,6 @@ void __init nubus_probe_slot(int slot)
continue;
dp = *rp;
- if(dp == 0)
- continue;
/* The last byte of the format block consists of two
nybbles which are "mirror images" of each other.
@@ -908,7 +816,7 @@ void __init nubus_probe_slot(int slot)
continue;
/* Check that this value is actually *on* one of the
bytelanes it claims are valid! */
- if ((dp & 0x0F) >= (1 << i))
+ if (not_useful(rp, dp))
continue;
/* Looks promising. Let's put it on the list. */
@@ -922,10 +830,6 @@ void __init nubus_scan_bus(void)
{
int slot;
- /* This might not work on your machine */
-#ifdef I_WANT_TO_PROBE_SLOT_ZERO
- nubus_probe_slot(0);
-#endif
for (slot = 9; slot < 15; slot++) {
nubus_probe_slot(slot);
}
@@ -943,13 +847,6 @@ static int __init nubus_init(void)
via_nubus_init();
}
-#ifdef TRY_TO_DODGE_WSOD
- /* Rogue Ethernet interrupts can kill the machine if we don't
- do this. Obviously this is bogus. Hopefully the local VIA
- gurus can fix the real cause of the problem. */
- mdelay(1000);
-#endif
-
/* And probe */
pr_info("NuBus: Scanning NuBus slots.\n");
nubus_devices = NULL;
diff --git a/drivers/nvdimm/blk.c b/drivers/nvdimm/blk.c
index 822198a75e96..f12d23c49771 100644
--- a/drivers/nvdimm/blk.c
+++ b/drivers/nvdimm/blk.c
@@ -186,7 +186,7 @@ static blk_qc_t nd_blk_make_request(struct request_queue *q, struct bio *bio)
* another kernel subsystem, and we just pass it through.
*/
if (bio_integrity_enabled(bio) && bio_integrity_prep(bio)) {
- bio->bi_error = -EIO;
+ bio->bi_status = BLK_STS_IOERR;
goto out;
}
@@ -205,7 +205,7 @@ static blk_qc_t nd_blk_make_request(struct request_queue *q, struct bio *bio)
"io error in %s sector %lld, len %d,\n",
(rw == READ) ? "READ" : "WRITE",
(unsigned long long) iter.bi_sector, len);
- bio->bi_error = err;
+ bio->bi_status = errno_to_blk_status(err);
break;
}
}
@@ -273,7 +273,6 @@ static int nsblk_attach_disk(struct nd_namespace_blk *nsblk)
blk_queue_make_request(q, nd_blk_make_request);
blk_queue_max_hw_sectors(q, UINT_MAX);
- blk_queue_bounce_limit(q, BLK_BOUNCE_ANY);
blk_queue_logical_block_size(q, nsblk_sector_size(nsblk));
queue_flag_set_unlocked(QUEUE_FLAG_NONROT, q);
q->queuedata = nsblk;
diff --git a/drivers/nvdimm/btt.c b/drivers/nvdimm/btt.c
index 983718b8fd9b..b6ba0618ea46 100644
--- a/drivers/nvdimm/btt.c
+++ b/drivers/nvdimm/btt.c
@@ -1210,7 +1210,7 @@ static blk_qc_t btt_make_request(struct request_queue *q, struct bio *bio)
* another kernel subsystem, and we just pass it through.
*/
if (bio_integrity_enabled(bio) && bio_integrity_prep(bio)) {
- bio->bi_error = -EIO;
+ bio->bi_status = BLK_STS_IOERR;
goto out;
}
@@ -1232,7 +1232,7 @@ static blk_qc_t btt_make_request(struct request_queue *q, struct bio *bio)
(op_is_write(bio_op(bio))) ? "WRITE" :
"READ",
(unsigned long long) iter.bi_sector, len);
- bio->bi_error = err;
+ bio->bi_status = errno_to_blk_status(err);
break;
}
}
@@ -1297,7 +1297,6 @@ static int btt_blk_init(struct btt *btt)
blk_queue_make_request(btt->btt_queue, btt_make_request);
blk_queue_logical_block_size(btt->btt_queue, btt->sector_size);
blk_queue_max_hw_sectors(btt->btt_queue, UINT_MAX);
- blk_queue_bounce_limit(btt->btt_queue, BLK_BOUNCE_ANY);
queue_flag_set_unlocked(QUEUE_FLAG_NONROT, btt->btt_queue);
btt->btt_queue->queuedata = btt;
diff --git a/drivers/nvdimm/btt_devs.c b/drivers/nvdimm/btt_devs.c
index ae00dc0d9791..4c989bb9a8a0 100644
--- a/drivers/nvdimm/btt_devs.c
+++ b/drivers/nvdimm/btt_devs.c
@@ -222,13 +222,6 @@ struct device *nd_btt_create(struct nd_region *nd_region)
return dev;
}
-static bool uuid_is_null(u8 *uuid)
-{
- static const u8 null_uuid[16];
-
- return (memcmp(uuid, null_uuid, 16) == 0);
-}
-
/**
* nd_btt_arena_is_valid - check if the metadata layout is valid
* @nd_btt: device with BTT geometry and backing device info
@@ -249,7 +242,7 @@ bool nd_btt_arena_is_valid(struct nd_btt *nd_btt, struct btt_sb *super)
if (memcmp(super->signature, BTT_SIG, BTT_SIG_LEN) != 0)
return false;
- if (!uuid_is_null(super->parent_uuid))
+ if (!guid_is_null((guid_t *)&super->parent_uuid))
if (memcmp(super->parent_uuid, parent_uuid, 16) != 0)
return false;
diff --git a/drivers/nvdimm/pmem.c b/drivers/nvdimm/pmem.c
index c544d466ea51..6b577afb1d44 100644
--- a/drivers/nvdimm/pmem.c
+++ b/drivers/nvdimm/pmem.c
@@ -49,19 +49,19 @@ static struct nd_region *to_region(struct pmem_device *pmem)
return to_nd_region(to_dev(pmem)->parent);
}
-static int pmem_clear_poison(struct pmem_device *pmem, phys_addr_t offset,
- unsigned int len)
+static blk_status_t pmem_clear_poison(struct pmem_device *pmem,
+ phys_addr_t offset, unsigned int len)
{
struct device *dev = to_dev(pmem);
sector_t sector;
long cleared;
- int rc = 0;
+ blk_status_t rc = BLK_STS_OK;
sector = (offset - pmem->data_offset) / 512;
cleared = nvdimm_clear_poison(dev, pmem->phys_addr + offset, len);
if (cleared < len)
- rc = -EIO;
+ rc = BLK_STS_IOERR;
if (cleared > 0 && cleared / 512) {
cleared /= 512;
dev_dbg(dev, "%s: %#llx clear %ld sector%s\n", __func__,
@@ -84,7 +84,7 @@ static void write_pmem(void *pmem_addr, struct page *page,
kunmap_atomic(mem);
}
-static int read_pmem(struct page *page, unsigned int off,
+static blk_status_t read_pmem(struct page *page, unsigned int off,
void *pmem_addr, unsigned int len)
{
int rc;
@@ -93,15 +93,15 @@ static int read_pmem(struct page *page, unsigned int off,
rc = memcpy_mcsafe(mem + off, pmem_addr, len);
kunmap_atomic(mem);
if (rc)
- return -EIO;
- return 0;
+ return BLK_STS_IOERR;
+ return BLK_STS_OK;
}
-static int pmem_do_bvec(struct pmem_device *pmem, struct page *page,
+static blk_status_t pmem_do_bvec(struct pmem_device *pmem, struct page *page,
unsigned int len, unsigned int off, bool is_write,
sector_t sector)
{
- int rc = 0;
+ blk_status_t rc = BLK_STS_OK;
bool bad_pmem = false;
phys_addr_t pmem_off = sector * 512 + pmem->data_offset;
void *pmem_addr = pmem->virt_addr + pmem_off;
@@ -111,7 +111,7 @@ static int pmem_do_bvec(struct pmem_device *pmem, struct page *page,
if (!is_write) {
if (unlikely(bad_pmem))
- rc = -EIO;
+ rc = BLK_STS_IOERR;
else {
rc = read_pmem(page, off, pmem_addr, len);
flush_dcache_page(page);
@@ -149,7 +149,7 @@ static int pmem_do_bvec(struct pmem_device *pmem, struct page *page,
static blk_qc_t pmem_make_request(struct request_queue *q, struct bio *bio)
{
- int rc = 0;
+ blk_status_t rc = 0;
bool do_acct;
unsigned long start;
struct bio_vec bvec;
@@ -166,7 +166,7 @@ static blk_qc_t pmem_make_request(struct request_queue *q, struct bio *bio)
bvec.bv_offset, op_is_write(bio_op(bio)),
iter.bi_sector);
if (rc) {
- bio->bi_error = rc;
+ bio->bi_status = rc;
break;
}
}
@@ -184,7 +184,7 @@ static int pmem_rw_page(struct block_device *bdev, sector_t sector,
struct page *page, bool is_write)
{
struct pmem_device *pmem = bdev->bd_queue->queuedata;
- int rc;
+ blk_status_t rc;
rc = pmem_do_bvec(pmem, page, PAGE_SIZE, 0, is_write, sector);
@@ -197,7 +197,7 @@ static int pmem_rw_page(struct block_device *bdev, sector_t sector,
if (rc == 0)
page_endio(page, is_write, 0);
- return rc;
+ return blk_status_to_errno(rc);
}
/* see "strong" declaration in tools/testing/nvdimm/pmem-dax.c */
@@ -343,7 +343,6 @@ static int pmem_attach_disk(struct device *dev,
blk_queue_make_request(q, pmem_make_request);
blk_queue_physical_block_size(q, PAGE_SIZE);
blk_queue_max_hw_sectors(q, UINT_MAX);
- blk_queue_bounce_limit(q, BLK_BOUNCE_ANY);
queue_flag_set_unlocked(QUEUE_FLAG_NONROT, q);
queue_flag_set_unlocked(QUEUE_FLAG_DAX, q);
q->queuedata = pmem;
diff --git a/drivers/nvme/host/Kconfig b/drivers/nvme/host/Kconfig
index 90745a616df7..46d6cb1e03bd 100644
--- a/drivers/nvme/host/Kconfig
+++ b/drivers/nvme/host/Kconfig
@@ -13,18 +13,6 @@ config BLK_DEV_NVME
To compile this driver as a module, choose M here: the
module will be called nvme.
-config BLK_DEV_NVME_SCSI
- bool "SCSI emulation for NVMe device nodes"
- depends on NVME_CORE
- ---help---
- This adds support for the SG_IO ioctl on the NVMe character
- and block devices nodes, as well as a translation for a small
- number of selected SCSI commands to NVMe commands to the NVMe
- driver. If you don't know what this means you probably want
- to say N here, unless you run a distro that abuses the SCSI
- emulation to provide stable device names for mount by id, like
- some OpenSuSE and SLES versions.
-
config NVME_FABRICS
tristate
diff --git a/drivers/nvme/host/Makefile b/drivers/nvme/host/Makefile
index f1a7d945fbb6..cc0aacb4c8b4 100644
--- a/drivers/nvme/host/Makefile
+++ b/drivers/nvme/host/Makefile
@@ -5,7 +5,6 @@ obj-$(CONFIG_NVME_RDMA) += nvme-rdma.o
obj-$(CONFIG_NVME_FC) += nvme-fc.o
nvme-core-y := core.o
-nvme-core-$(CONFIG_BLK_DEV_NVME_SCSI) += scsi.o
nvme-core-$(CONFIG_NVM) += lightnvm.o
nvme-y += pci.o
diff --git a/drivers/nvme/host/core.c b/drivers/nvme/host/core.c
index d5e0906262ea..d70df1d0072d 100644
--- a/drivers/nvme/host/core.c
+++ b/drivers/nvme/host/core.c
@@ -27,7 +27,6 @@
#include <linux/nvme_ioctl.h>
#include <linux/t10-pi.h>
#include <linux/pm_qos.h>
-#include <scsi/sg.h>
#include <asm/unaligned.h>
#include "nvme.h"
@@ -45,7 +44,7 @@ module_param_named(io_timeout, nvme_io_timeout, byte, 0644);
MODULE_PARM_DESC(io_timeout, "timeout in seconds for I/O");
EXPORT_SYMBOL_GPL(nvme_io_timeout);
-unsigned char shutdown_timeout = 5;
+static unsigned char shutdown_timeout = 5;
module_param(shutdown_timeout, byte, 0644);
MODULE_PARM_DESC(shutdown_timeout, "timeout in seconds for controller shutdown");
@@ -56,7 +55,7 @@ MODULE_PARM_DESC(max_retries, "max number of retries a command may have");
static int nvme_char_major;
module_param(nvme_char_major, int, 0);
-static unsigned long default_ps_max_latency_us = 25000;
+static unsigned long default_ps_max_latency_us = 100000;
module_param(default_ps_max_latency_us, ulong, 0644);
MODULE_PARM_DESC(default_ps_max_latency_us,
"max power saving latency for new devices; use PM QOS to change per device");
@@ -65,34 +64,53 @@ static bool force_apst;
module_param(force_apst, bool, 0644);
MODULE_PARM_DESC(force_apst, "allow APST for newly enumerated devices even if quirked off");
+static bool streams;
+module_param(streams, bool, 0644);
+MODULE_PARM_DESC(streams, "turn on support for Streams write directives");
+
+struct workqueue_struct *nvme_wq;
+EXPORT_SYMBOL_GPL(nvme_wq);
+
static LIST_HEAD(nvme_ctrl_list);
static DEFINE_SPINLOCK(dev_list_lock);
static struct class *nvme_class;
-static int nvme_error_status(struct request *req)
+int nvme_reset_ctrl(struct nvme_ctrl *ctrl)
+{
+ if (!nvme_change_ctrl_state(ctrl, NVME_CTRL_RESETTING))
+ return -EBUSY;
+ if (!queue_work(nvme_wq, &ctrl->reset_work))
+ return -EBUSY;
+ return 0;
+}
+EXPORT_SYMBOL_GPL(nvme_reset_ctrl);
+
+static int nvme_reset_ctrl_sync(struct nvme_ctrl *ctrl)
+{
+ int ret;
+
+ ret = nvme_reset_ctrl(ctrl);
+ if (!ret)
+ flush_work(&ctrl->reset_work);
+ return ret;
+}
+
+static blk_status_t nvme_error_status(struct request *req)
{
switch (nvme_req(req)->status & 0x7ff) {
case NVME_SC_SUCCESS:
- return 0;
+ return BLK_STS_OK;
case NVME_SC_CAP_EXCEEDED:
- return -ENOSPC;
- default:
- return -EIO;
-
- /*
- * XXX: these errors are a nasty side-band protocol to
- * drivers/md/dm-mpath.c:noretry_error() that aren't documented
- * anywhere..
- */
- case NVME_SC_CMD_SEQ_ERROR:
- return -EILSEQ;
+ return BLK_STS_NOSPC;
case NVME_SC_ONCS_NOT_SUPPORTED:
- return -EOPNOTSUPP;
+ return BLK_STS_NOTSUPP;
case NVME_SC_WRITE_FAULT:
case NVME_SC_READ_ERROR:
case NVME_SC_UNWRITTEN_BLOCK:
- return -ENODATA;
+ return BLK_STS_MEDIUM;
+ default:
+ return BLK_STS_IOERR;
}
}
@@ -165,7 +183,6 @@ bool nvme_change_ctrl_state(struct nvme_ctrl *ctrl,
switch (old_state) {
case NVME_CTRL_NEW:
case NVME_CTRL_LIVE:
- case NVME_CTRL_RECONNECTING:
changed = true;
/* FALLTHRU */
default:
@@ -283,6 +300,105 @@ struct request *nvme_alloc_request(struct request_queue *q,
}
EXPORT_SYMBOL_GPL(nvme_alloc_request);
+static int nvme_toggle_streams(struct nvme_ctrl *ctrl, bool enable)
+{
+ struct nvme_command c;
+
+ memset(&c, 0, sizeof(c));
+
+ c.directive.opcode = nvme_admin_directive_send;
+ c.directive.nsid = cpu_to_le32(0xffffffff);
+ c.directive.doper = NVME_DIR_SND_ID_OP_ENABLE;
+ c.directive.dtype = NVME_DIR_IDENTIFY;
+ c.directive.tdtype = NVME_DIR_STREAMS;
+ c.directive.endir = enable ? NVME_DIR_ENDIR : 0;
+
+ return nvme_submit_sync_cmd(ctrl->admin_q, &c, NULL, 0);
+}
+
+static int nvme_disable_streams(struct nvme_ctrl *ctrl)
+{
+ return nvme_toggle_streams(ctrl, false);
+}
+
+static int nvme_enable_streams(struct nvme_ctrl *ctrl)
+{
+ return nvme_toggle_streams(ctrl, true);
+}
+
+static int nvme_get_stream_params(struct nvme_ctrl *ctrl,
+ struct streams_directive_params *s, u32 nsid)
+{
+ struct nvme_command c;
+
+ memset(&c, 0, sizeof(c));
+ memset(s, 0, sizeof(*s));
+
+ c.directive.opcode = nvme_admin_directive_recv;
+ c.directive.nsid = cpu_to_le32(nsid);
+ c.directive.numd = sizeof(*s);
+ c.directive.doper = NVME_DIR_RCV_ST_OP_PARAM;
+ c.directive.dtype = NVME_DIR_STREAMS;
+
+ return nvme_submit_sync_cmd(ctrl->admin_q, &c, s, sizeof(*s));
+}
+
+static int nvme_configure_directives(struct nvme_ctrl *ctrl)
+{
+ struct streams_directive_params s;
+ int ret;
+
+ if (!(ctrl->oacs & NVME_CTRL_OACS_DIRECTIVES))
+ return 0;
+ if (!streams)
+ return 0;
+
+ ret = nvme_enable_streams(ctrl);
+ if (ret)
+ return ret;
+
+ ret = nvme_get_stream_params(ctrl, &s, 0xffffffff);
+ if (ret)
+ return ret;
+
+ ctrl->nssa = le16_to_cpu(s.nssa);
+ if (ctrl->nssa < BLK_MAX_WRITE_HINTS - 1) {
+ dev_info(ctrl->device, "too few streams (%u) available\n",
+ ctrl->nssa);
+ nvme_disable_streams(ctrl);
+ return 0;
+ }
+
+ ctrl->nr_streams = min_t(unsigned, ctrl->nssa, BLK_MAX_WRITE_HINTS - 1);
+ dev_info(ctrl->device, "Using %u streams\n", ctrl->nr_streams);
+ return 0;
+}
+
+/*
+ * Check if 'req' has a write hint associated with it. If it does, assign
+ * a valid namespace stream to the write.
+ */
+static void nvme_assign_write_stream(struct nvme_ctrl *ctrl,
+ struct request *req, u16 *control,
+ u32 *dsmgmt)
+{
+ enum rw_hint streamid = req->write_hint;
+
+ if (streamid == WRITE_LIFE_NOT_SET || streamid == WRITE_LIFE_NONE)
+ streamid = 0;
+ else {
+ streamid--;
+ if (WARN_ON_ONCE(streamid > ctrl->nr_streams))
+ return;
+
+ *control |= NVME_RW_DTYPE_STREAMS;
+ *dsmgmt |= streamid << 16;
+ }
+
+ if (streamid < ARRAY_SIZE(req->q->write_hints))
+ req->q->write_hints[streamid] += blk_rq_bytes(req) >> 9;
+}
+
static inline void nvme_setup_flush(struct nvme_ns *ns,
struct nvme_command *cmnd)
{
@@ -291,7 +407,7 @@ static inline void nvme_setup_flush(struct nvme_ns *ns,
cmnd->common.nsid = cpu_to_le32(ns->ns_id);
}
-static inline int nvme_setup_discard(struct nvme_ns *ns, struct request *req,
+static blk_status_t nvme_setup_discard(struct nvme_ns *ns, struct request *req,
struct nvme_command *cmnd)
{
unsigned short segments = blk_rq_nr_discard_segments(req), n = 0;
@@ -300,7 +416,7 @@ static inline int nvme_setup_discard(struct nvme_ns *ns, struct request *req,
range = kmalloc_array(segments, sizeof(*range), GFP_ATOMIC);
if (!range)
- return BLK_MQ_RQ_QUEUE_BUSY;
+ return BLK_STS_RESOURCE;
__rq_for_each_bio(bio, req) {
u64 slba = nvme_block_nr(ns, bio->bi_iter.bi_sector);
@@ -314,7 +430,7 @@ static inline int nvme_setup_discard(struct nvme_ns *ns, struct request *req,
if (WARN_ON_ONCE(n != segments)) {
kfree(range);
- return BLK_MQ_RQ_QUEUE_ERROR;
+ return BLK_STS_IOERR;
}
memset(cmnd, 0, sizeof(*cmnd));
@@ -328,15 +444,26 @@ static inline int nvme_setup_discard(struct nvme_ns *ns, struct request *req,
req->special_vec.bv_len = sizeof(*range) * segments;
req->rq_flags |= RQF_SPECIAL_PAYLOAD;
- return BLK_MQ_RQ_QUEUE_OK;
+ return BLK_STS_OK;
}
-static inline void nvme_setup_rw(struct nvme_ns *ns, struct request *req,
- struct nvme_command *cmnd)
+static inline blk_status_t nvme_setup_rw(struct nvme_ns *ns,
+ struct request *req, struct nvme_command *cmnd)
{
+ struct nvme_ctrl *ctrl = ns->ctrl;
u16 control = 0;
u32 dsmgmt = 0;
+ /*
+ * If formated with metadata, require the block layer provide a buffer
+ * unless this namespace is formated such that the metadata can be
+ * stripped/generated by the controller with PRACT=1.
+ */
+ if (ns && ns->ms &&
+ (!ns->pi_type || ns->ms != sizeof(struct t10_pi_tuple)) &&
+ !blk_integrity_rq(req) && !blk_rq_is_passthrough(req))
+ return BLK_STS_NOTSUPP;
+
if (req->cmd_flags & REQ_FUA)
control |= NVME_RW_FUA;
if (req->cmd_flags & (REQ_FAILFAST_DEV | REQ_RAHEAD))
@@ -351,6 +478,9 @@ static inline void nvme_setup_rw(struct nvme_ns *ns, struct request *req,
cmnd->rw.slba = cpu_to_le64(nvme_block_nr(ns, blk_rq_pos(req)));
cmnd->rw.length = cpu_to_le16((blk_rq_bytes(req) >> ns->lba_shift) - 1);
+ if (req_op(req) == REQ_OP_WRITE && ctrl->nr_streams)
+ nvme_assign_write_stream(ctrl, req, &control, &dsmgmt);
+
if (ns->ms) {
switch (ns->pi_type) {
case NVME_NS_DPS_PI_TYPE3:
@@ -370,12 +500,13 @@ static inline void nvme_setup_rw(struct nvme_ns *ns, struct request *req,
cmnd->rw.control = cpu_to_le16(control);
cmnd->rw.dsmgmt = cpu_to_le32(dsmgmt);
+ return 0;
}
-int nvme_setup_cmd(struct nvme_ns *ns, struct request *req,
+blk_status_t nvme_setup_cmd(struct nvme_ns *ns, struct request *req,
struct nvme_command *cmd)
{
- int ret = BLK_MQ_RQ_QUEUE_OK;
+ blk_status_t ret = BLK_STS_OK;
if (!(req->rq_flags & RQF_DONTPREP)) {
nvme_req(req)->retries = 0;
@@ -398,11 +529,11 @@ int nvme_setup_cmd(struct nvme_ns *ns, struct request *req,
break;
case REQ_OP_READ:
case REQ_OP_WRITE:
- nvme_setup_rw(ns, req, cmd);
+ ret = nvme_setup_rw(ns, req, cmd);
break;
default:
WARN_ON_ONCE(1);
- return BLK_MQ_RQ_QUEUE_ERROR;
+ return BLK_STS_IOERR;
}
cmd->common.command_id = req->tag;
@@ -555,15 +686,16 @@ int nvme_submit_user_cmd(struct request_queue *q, struct nvme_command *cmd,
result, timeout);
}
-static void nvme_keep_alive_end_io(struct request *rq, int error)
+static void nvme_keep_alive_end_io(struct request *rq, blk_status_t status)
{
struct nvme_ctrl *ctrl = rq->end_io_data;
blk_mq_free_request(rq);
- if (error) {
+ if (status) {
dev_err(ctrl->device,
- "failed nvme_keep_alive_end_io error=%d\n", error);
+ "failed nvme_keep_alive_end_io error=%d\n",
+ status);
return;
}
@@ -599,7 +731,7 @@ static void nvme_keep_alive_work(struct work_struct *work)
if (nvme_keep_alive(ctrl)) {
/* allocation failure, reset the controller */
dev_err(ctrl->device, "keep-alive failed\n");
- ctrl->ops->reset_ctrl(ctrl);
+ nvme_reset_ctrl(ctrl);
return;
}
}
@@ -623,7 +755,7 @@ void nvme_stop_keep_alive(struct nvme_ctrl *ctrl)
}
EXPORT_SYMBOL_GPL(nvme_stop_keep_alive);
-int nvme_identify_ctrl(struct nvme_ctrl *dev, struct nvme_id_ctrl **id)
+static int nvme_identify_ctrl(struct nvme_ctrl *dev, struct nvme_id_ctrl **id)
{
struct nvme_command c = { };
int error;
@@ -643,6 +775,77 @@ int nvme_identify_ctrl(struct nvme_ctrl *dev, struct nvme_id_ctrl **id)
return error;
}
+static int nvme_identify_ns_descs(struct nvme_ns *ns, unsigned nsid)
+{
+ struct nvme_command c = { };
+ int status;
+ void *data;
+ int pos;
+ int len;
+
+ c.identify.opcode = nvme_admin_identify;
+ c.identify.nsid = cpu_to_le32(nsid);
+ c.identify.cns = NVME_ID_CNS_NS_DESC_LIST;
+
+ data = kzalloc(NVME_IDENTIFY_DATA_SIZE, GFP_KERNEL);
+ if (!data)
+ return -ENOMEM;
+
+ status = nvme_submit_sync_cmd(ns->ctrl->admin_q, &c, data,
+ NVME_IDENTIFY_DATA_SIZE);
+ if (status)
+ goto free_data;
+
+ for (pos = 0; pos < NVME_IDENTIFY_DATA_SIZE; pos += len) {
+ struct nvme_ns_id_desc *cur = data + pos;
+
+ if (cur->nidl == 0)
+ break;
+
+ switch (cur->nidt) {
+ case NVME_NIDT_EUI64:
+ if (cur->nidl != NVME_NIDT_EUI64_LEN) {
+ dev_warn(ns->ctrl->device,
+ "ctrl returned bogus length: %d for NVME_NIDT_EUI64\n",
+ cur->nidl);
+ goto free_data;
+ }
+ len = NVME_NIDT_EUI64_LEN;
+ memcpy(ns->eui, data + pos + sizeof(*cur), len);
+ break;
+ case NVME_NIDT_NGUID:
+ if (cur->nidl != NVME_NIDT_NGUID_LEN) {
+ dev_warn(ns->ctrl->device,
+ "ctrl returned bogus length: %d for NVME_NIDT_NGUID\n",
+ cur->nidl);
+ goto free_data;
+ }
+ len = NVME_NIDT_NGUID_LEN;
+ memcpy(ns->nguid, data + pos + sizeof(*cur), len);
+ break;
+ case NVME_NIDT_UUID:
+ if (cur->nidl != NVME_NIDT_UUID_LEN) {
+ dev_warn(ns->ctrl->device,
+ "ctrl returned bogus length: %d for NVME_NIDT_UUID\n",
+ cur->nidl);
+ goto free_data;
+ }
+ len = NVME_NIDT_UUID_LEN;
+ uuid_copy(&ns->uuid, data + pos + sizeof(*cur));
+ break;
+ default:
+ /* Skip unnkown types */
+ len = cur->nidl;
+ break;
+ }
+
+ len += sizeof(*cur);
+ }
+free_data:
+ kfree(data);
+ return status;
+}
+
static int nvme_identify_ns_list(struct nvme_ctrl *dev, unsigned nsid, __le32 *ns_list)
{
struct nvme_command c = { };
@@ -653,7 +856,7 @@ static int nvme_identify_ns_list(struct nvme_ctrl *dev, unsigned nsid, __le32 *n
return nvme_submit_sync_cmd(dev->admin_q, &c, ns_list, 0x1000);
}
-int nvme_identify_ns(struct nvme_ctrl *dev, unsigned nsid,
+static int nvme_identify_ns(struct nvme_ctrl *dev, unsigned nsid,
struct nvme_id_ns **id)
{
struct nvme_command c = { };
@@ -675,26 +878,7 @@ int nvme_identify_ns(struct nvme_ctrl *dev, unsigned nsid,
return error;
}
-int nvme_get_features(struct nvme_ctrl *dev, unsigned fid, unsigned nsid,
- void *buffer, size_t buflen, u32 *result)
-{
- struct nvme_command c;
- union nvme_result res;
- int ret;
-
- memset(&c, 0, sizeof(c));
- c.features.opcode = nvme_admin_get_features;
- c.features.nsid = cpu_to_le32(nsid);
- c.features.fid = cpu_to_le32(fid);
-
- ret = __nvme_submit_sync_cmd(dev->admin_q, &c, &res, buffer, buflen, 0,
- NVME_QID_ANY, 0, 0);
- if (ret >= 0 && result)
- *result = le32_to_cpu(res.u32);
- return ret;
-}
-
-int nvme_set_features(struct nvme_ctrl *dev, unsigned fid, unsigned dword11,
+static int nvme_set_features(struct nvme_ctrl *dev, unsigned fid, unsigned dword11,
void *buffer, size_t buflen, u32 *result)
{
struct nvme_command c;
@@ -713,28 +897,6 @@ int nvme_set_features(struct nvme_ctrl *dev, unsigned fid, unsigned dword11,
return ret;
}
-int nvme_get_log_page(struct nvme_ctrl *dev, struct nvme_smart_log **log)
-{
- struct nvme_command c = { };
- int error;
-
- c.common.opcode = nvme_admin_get_log_page,
- c.common.nsid = cpu_to_le32(0xFFFFFFFF),
- c.common.cdw10[0] = cpu_to_le32(
- (((sizeof(struct nvme_smart_log) / 4) - 1) << 16) |
- NVME_LOG_SMART),
-
- *log = kmalloc(sizeof(struct nvme_smart_log), GFP_KERNEL);
- if (!*log)
- return -ENOMEM;
-
- error = nvme_submit_sync_cmd(dev->admin_q, &c, *log,
- sizeof(struct nvme_smart_log));
- if (error)
- kfree(*log);
- return error;
-}
-
int nvme_set_queue_count(struct nvme_ctrl *ctrl, int *count)
{
u32 q_count = (*count - 1) | ((*count - 1) << 16);
@@ -752,7 +914,7 @@ int nvme_set_queue_count(struct nvme_ctrl *ctrl, int *count)
* access to the admin queue, as that might be only way to fix them up.
*/
if (status > 0) {
- dev_err(ctrl->dev, "Could not set queue count (%d)\n", status);
+ dev_err(ctrl->device, "Could not set queue count (%d)\n", status);
*count = 0;
} else {
nr_io_queues = min(result & 0xffff, result >> 16) + 1;
@@ -870,12 +1032,6 @@ static int nvme_ioctl(struct block_device *bdev, fmode_t mode,
return nvme_user_cmd(ns->ctrl, ns, (void __user *)arg);
case NVME_IOCTL_SUBMIT_IO:
return nvme_submit_io(ns, (void __user *)arg);
-#ifdef CONFIG_BLK_DEV_NVME_SCSI
- case SG_GET_VERSION_NUM:
- return nvme_sg_get_version_num((void __user *)arg);
- case SG_IO:
- return nvme_sg_io(ns, (void __user *)arg);
-#endif
default:
#ifdef CONFIG_NVM
if (ns->ndev)
@@ -892,10 +1048,6 @@ static int nvme_ioctl(struct block_device *bdev, fmode_t mode,
static int nvme_compat_ioctl(struct block_device *bdev, fmode_t mode,
unsigned int cmd, unsigned long arg)
{
- switch (cmd) {
- case SG_IO:
- return -ENOIOCTLCMD;
- }
return nvme_ioctl(bdev, mode, cmd, arg);
}
#else
@@ -925,6 +1077,29 @@ static int nvme_getgeo(struct block_device *bdev, struct hd_geometry *geo)
}
#ifdef CONFIG_BLK_DEV_INTEGRITY
+static void nvme_prep_integrity(struct gendisk *disk, struct nvme_id_ns *id,
+ u16 bs)
+{
+ struct nvme_ns *ns = disk->private_data;
+ u16 old_ms = ns->ms;
+ u8 pi_type = 0;
+
+ ns->ms = le16_to_cpu(id->lbaf[id->flbas & NVME_NS_FLBAS_LBA_MASK].ms);
+ ns->ext = ns->ms && (id->flbas & NVME_NS_FLBAS_META_EXT);
+
+ /* PI implementation requires metadata equal t10 pi tuple size */
+ if (ns->ms == sizeof(struct t10_pi_tuple))
+ pi_type = id->dps & NVME_NS_DPS_PI_MASK;
+
+ if (blk_get_integrity(disk) &&
+ (ns->pi_type != pi_type || ns->ms != old_ms ||
+ bs != queue_logical_block_size(disk->queue) ||
+ (ns->ms && ns->ext)))
+ blk_integrity_unregister(disk);
+
+ ns->pi_type = pi_type;
+}
+
static void nvme_init_integrity(struct nvme_ns *ns)
{
struct blk_integrity integrity;
@@ -951,11 +1126,21 @@ static void nvme_init_integrity(struct nvme_ns *ns)
blk_queue_max_integrity_segments(ns->queue, 1);
}
#else
+static void nvme_prep_integrity(struct gendisk *disk, struct nvme_id_ns *id,
+ u16 bs)
+{
+}
static void nvme_init_integrity(struct nvme_ns *ns)
{
}
#endif /* CONFIG_BLK_DEV_INTEGRITY */
+static void nvme_set_chunk_size(struct nvme_ns *ns)
+{
+ u32 chunk_size = (((u32)ns->noiob) << (ns->lba_shift - 9));
+ blk_queue_chunk_sectors(ns->queue, rounddown_pow_of_two(chunk_size));
+}
+
static void nvme_config_discard(struct nvme_ns *ns)
{
struct nvme_ctrl *ctrl = ns->ctrl;
@@ -964,8 +1149,15 @@ static void nvme_config_discard(struct nvme_ns *ns)
BUILD_BUG_ON(PAGE_SIZE / sizeof(struct nvme_dsm_range) <
NVME_DSM_MAX_RANGES);
- ns->queue->limits.discard_alignment = logical_block_size;
- ns->queue->limits.discard_granularity = logical_block_size;
+ if (ctrl->nr_streams && ns->sws && ns->sgs) {
+ unsigned int sz = logical_block_size * ns->sws * ns->sgs;
+
+ ns->queue->limits.discard_alignment = sz;
+ ns->queue->limits.discard_granularity = sz;
+ } else {
+ ns->queue->limits.discard_alignment = logical_block_size;
+ ns->queue->limits.discard_granularity = logical_block_size;
+ }
blk_queue_max_discard_sectors(ns->queue, UINT_MAX);
blk_queue_max_discard_segments(ns->queue, NVME_DSM_MAX_RANGES);
queue_flag_set_unlocked(QUEUE_FLAG_DISCARD, ns->queue);
@@ -989,7 +1181,15 @@ static int nvme_revalidate_ns(struct nvme_ns *ns, struct nvme_id_ns **id)
if (ns->ctrl->vs >= NVME_VS(1, 1, 0))
memcpy(ns->eui, (*id)->eui64, sizeof(ns->eui));
if (ns->ctrl->vs >= NVME_VS(1, 2, 0))
- memcpy(ns->uuid, (*id)->nguid, sizeof(ns->uuid));
+ memcpy(ns->nguid, (*id)->nguid, sizeof(ns->nguid));
+ if (ns->ctrl->vs >= NVME_VS(1, 3, 0)) {
+ /* Don't treat error as fatal we potentially
+ * already have a NGUID or EUI-64
+ */
+ if (nvme_identify_ns_descs(ns, ns->ns_id))
+ dev_warn(ns->ctrl->device,
+ "%s: Identify Descriptors failed\n", __func__);
+ }
return 0;
}
@@ -997,37 +1197,26 @@ static int nvme_revalidate_ns(struct nvme_ns *ns, struct nvme_id_ns **id)
static void __nvme_revalidate_disk(struct gendisk *disk, struct nvme_id_ns *id)
{
struct nvme_ns *ns = disk->private_data;
- u8 lbaf, pi_type;
- u16 old_ms;
- unsigned short bs;
-
- old_ms = ns->ms;
- lbaf = id->flbas & NVME_NS_FLBAS_LBA_MASK;
- ns->lba_shift = id->lbaf[lbaf].ds;
- ns->ms = le16_to_cpu(id->lbaf[lbaf].ms);
- ns->ext = ns->ms && (id->flbas & NVME_NS_FLBAS_META_EXT);
+ struct nvme_ctrl *ctrl = ns->ctrl;
+ u16 bs;
/*
* If identify namespace failed, use default 512 byte block size so
* block layer can use before failing read/write for 0 capacity.
*/
+ ns->lba_shift = id->lbaf[id->flbas & NVME_NS_FLBAS_LBA_MASK].ds;
if (ns->lba_shift == 0)
ns->lba_shift = 9;
bs = 1 << ns->lba_shift;
- /* XXX: PI implementation requires metadata equal t10 pi tuple size */
- pi_type = ns->ms == sizeof(struct t10_pi_tuple) ?
- id->dps & NVME_NS_DPS_PI_MASK : 0;
+ ns->noiob = le16_to_cpu(id->noiob);
blk_mq_freeze_queue(disk->queue);
- if (blk_get_integrity(disk) && (ns->pi_type != pi_type ||
- ns->ms != old_ms ||
- bs != queue_logical_block_size(disk->queue) ||
- (ns->ms && ns->ext)))
- blk_integrity_unregister(disk);
- ns->pi_type = pi_type;
+ if (ctrl->ops->flags & NVME_F_METADATA_SUPPORTED)
+ nvme_prep_integrity(disk, id, bs);
blk_queue_logical_block_size(ns->queue, bs);
-
+ if (ns->noiob)
+ nvme_set_chunk_size(ns);
if (ns->ms && !blk_get_integrity(disk) && !ns->ext)
nvme_init_integrity(ns);
if (ns->ms && !(ns->ms == 8 && ns->pi_type) && !blk_get_integrity(disk))
@@ -1035,7 +1224,7 @@ static void __nvme_revalidate_disk(struct gendisk *disk, struct nvme_id_ns *id)
else
set_capacity(disk, le64_to_cpup(&id->nsze) << (ns->lba_shift - 9));
- if (ns->ctrl->oncs & NVME_CTRL_ONCS_DSM)
+ if (ctrl->oncs & NVME_CTRL_ONCS_DSM)
nvme_config_discard(ns);
blk_mq_unfreeze_queue(disk->queue);
}
@@ -1271,7 +1460,7 @@ EXPORT_SYMBOL_GPL(nvme_enable_ctrl);
int nvme_shutdown_ctrl(struct nvme_ctrl *ctrl)
{
- unsigned long timeout = SHUTDOWN_TIMEOUT + jiffies;
+ unsigned long timeout = jiffies + (shutdown_timeout * HZ);
u32 csts;
int ret;
@@ -1330,7 +1519,7 @@ static void nvme_configure_apst(struct nvme_ctrl *ctrl)
* transitioning between power states. Therefore, when running
* in any given state, we will enter the next lower-power
* non-operational state after waiting 50 * (enlat + exlat)
- * microseconds, as long as that state's total latency is under
+ * microseconds, as long as that state's exit latency is under
* the requested maximum latency.
*
* We will not autonomously enter any non-operational state for
@@ -1360,7 +1549,7 @@ static void nvme_configure_apst(struct nvme_ctrl *ctrl)
if (!table)
return;
- if (ctrl->ps_max_latency_us == 0) {
+ if (!ctrl->apst_enabled || ctrl->ps_max_latency_us == 0) {
/* Turn off APST. */
apste = 0;
dev_dbg(ctrl->device, "APST disabled\n");
@@ -1375,7 +1564,7 @@ static void nvme_configure_apst(struct nvme_ctrl *ctrl)
* lowest-power state, not the number of states.
*/
for (state = (int)ctrl->npss; state >= 0; state--) {
- u64 total_latency_us, transition_ms;
+ u64 total_latency_us, exit_latency_us, transition_ms;
if (target)
table->entries[state] = target;
@@ -1396,12 +1585,15 @@ static void nvme_configure_apst(struct nvme_ctrl *ctrl)
NVME_PS_FLAGS_NON_OP_STATE))
continue;
- total_latency_us =
- (u64)le32_to_cpu(ctrl->psd[state].entry_lat) +
- + le32_to_cpu(ctrl->psd[state].exit_lat);
- if (total_latency_us > ctrl->ps_max_latency_us)
+ exit_latency_us =
+ (u64)le32_to_cpu(ctrl->psd[state].exit_lat);
+ if (exit_latency_us > ctrl->ps_max_latency_us)
continue;
+ total_latency_us =
+ exit_latency_us +
+ le32_to_cpu(ctrl->psd[state].entry_lat);
+
/*
* This state is good. Use it as the APST idle
* target for higher power states.
@@ -1513,6 +1705,31 @@ static bool quirk_matches(const struct nvme_id_ctrl *id,
string_matches(id->fr, q->fr, sizeof(id->fr));
}
+static void nvme_init_subnqn(struct nvme_ctrl *ctrl, struct nvme_id_ctrl *id)
+{
+ size_t nqnlen;
+ int off;
+
+ nqnlen = strnlen(id->subnqn, NVMF_NQN_SIZE);
+ if (nqnlen > 0 && nqnlen < NVMF_NQN_SIZE) {
+ strcpy(ctrl->subnqn, id->subnqn);
+ return;
+ }
+
+ if (ctrl->vs >= NVME_VS(1, 2, 1))
+ dev_warn(ctrl->device, "missing or invalid SUBNQN field.\n");
+
+ /* Generate a "fake" NQN per Figure 254 in NVMe 1.3 + ECN 001 */
+ off = snprintf(ctrl->subnqn, NVMF_NQN_SIZE,
+ "nqn.2014.08.org.nvmexpress:%4x%4x",
+ le16_to_cpu(id->vid), le16_to_cpu(id->ssvid));
+ memcpy(ctrl->subnqn + off, id->sn, sizeof(id->sn));
+ off += sizeof(id->sn);
+ memcpy(ctrl->subnqn + off, id->mn, sizeof(id->mn));
+ off += sizeof(id->mn);
+ memset(ctrl->subnqn + off, 0, sizeof(ctrl->subnqn) - off);
+}
+
/*
* Initialize the cached copies of the Identify data and various controller
* register in our nvme_ctrl structure. This should be called as soon as
@@ -1524,7 +1741,7 @@ int nvme_init_identify(struct nvme_ctrl *ctrl)
u64 cap;
int ret, page_shift;
u32 max_hw_sectors;
- u8 prev_apsta;
+ bool prev_apst_enabled;
ret = ctrl->ops->reg_read32(ctrl, NVME_REG_VS, &ctrl->vs);
if (ret) {
@@ -1548,6 +1765,8 @@ int nvme_init_identify(struct nvme_ctrl *ctrl)
return -EIO;
}
+ nvme_init_subnqn(ctrl, id);
+
if (!ctrl->identified) {
/*
* Check for quirks. Quirk can depend on firmware version,
@@ -1567,7 +1786,7 @@ int nvme_init_identify(struct nvme_ctrl *ctrl)
}
if (force_apst && (ctrl->quirks & NVME_QUIRK_NO_DEEPEST_PS)) {
- dev_warn(ctrl->dev, "forcibly allowing all power states due to nvme_core.force_apst -- use at your own risk\n");
+ dev_warn(ctrl->device, "forcibly allowing all power states due to nvme_core.force_apst -- use at your own risk\n");
ctrl->quirks &= ~NVME_QUIRK_NO_DEEPEST_PS;
}
@@ -1592,20 +1811,21 @@ int nvme_init_identify(struct nvme_ctrl *ctrl)
ctrl->kas = le16_to_cpu(id->kas);
ctrl->npss = id->npss;
- prev_apsta = ctrl->apsta;
+ ctrl->apsta = id->apsta;
+ prev_apst_enabled = ctrl->apst_enabled;
if (ctrl->quirks & NVME_QUIRK_NO_APST) {
if (force_apst && id->apsta) {
- dev_warn(ctrl->dev, "forcibly allowing APST due to nvme_core.force_apst -- use at your own risk\n");
- ctrl->apsta = 1;
+ dev_warn(ctrl->device, "forcibly allowing APST due to nvme_core.force_apst -- use at your own risk\n");
+ ctrl->apst_enabled = true;
} else {
- ctrl->apsta = 0;
+ ctrl->apst_enabled = false;
}
} else {
- ctrl->apsta = id->apsta;
+ ctrl->apst_enabled = id->apsta;
}
memcpy(ctrl->psd, id->psd, sizeof(ctrl->psd));
- if (ctrl->ops->is_fabrics) {
+ if (ctrl->ops->flags & NVME_F_FABRICS) {
ctrl->icdoff = le16_to_cpu(id->icdoff);
ctrl->ioccsz = le32_to_cpu(id->ioccsz);
ctrl->iorcsz = le32_to_cpu(id->iorcsz);
@@ -1619,22 +1839,25 @@ int nvme_init_identify(struct nvme_ctrl *ctrl)
ret = -EINVAL;
if (!ctrl->opts->discovery_nqn && !ctrl->kas) {
- dev_err(ctrl->dev,
+ dev_err(ctrl->device,
"keep-alive support is mandatory for fabrics\n");
ret = -EINVAL;
}
} else {
ctrl->cntlid = le16_to_cpu(id->cntlid);
+ ctrl->hmpre = le32_to_cpu(id->hmpre);
+ ctrl->hmmin = le32_to_cpu(id->hmmin);
}
kfree(id);
- if (ctrl->apsta && !prev_apsta)
+ if (ctrl->apst_enabled && !prev_apst_enabled)
dev_pm_qos_expose_latency_tolerance(ctrl->device);
- else if (!ctrl->apsta && prev_apsta)
+ else if (!ctrl->apst_enabled && prev_apst_enabled)
dev_pm_qos_hide_latency_tolerance(ctrl->device);
nvme_configure_apst(ctrl);
+ nvme_configure_directives(ctrl);
ctrl->identified = true;
@@ -1720,7 +1943,7 @@ static long nvme_dev_ioctl(struct file *file, unsigned int cmd,
return nvme_dev_user_cmd(ctrl, argp);
case NVME_IOCTL_RESET:
dev_warn(ctrl->device, "resetting controller\n");
- return ctrl->ops->reset_ctrl(ctrl);
+ return nvme_reset_ctrl_sync(ctrl);
case NVME_IOCTL_SUBSYS_RESET:
return nvme_reset_subsystem(ctrl);
case NVME_IOCTL_RESCAN:
@@ -1746,7 +1969,7 @@ static ssize_t nvme_sysfs_reset(struct device *dev,
struct nvme_ctrl *ctrl = dev_get_drvdata(dev);
int ret;
- ret = ctrl->ops->reset_ctrl(ctrl);
+ ret = nvme_reset_ctrl_sync(ctrl);
if (ret < 0)
return ret;
return count;
@@ -1772,8 +1995,8 @@ static ssize_t wwid_show(struct device *dev, struct device_attribute *attr,
int serial_len = sizeof(ctrl->serial);
int model_len = sizeof(ctrl->model);
- if (memchr_inv(ns->uuid, 0, sizeof(ns->uuid)))
- return sprintf(buf, "eui.%16phN\n", ns->uuid);
+ if (memchr_inv(ns->nguid, 0, sizeof(ns->nguid)))
+ return sprintf(buf, "eui.%16phN\n", ns->nguid);
if (memchr_inv(ns->eui, 0, sizeof(ns->eui)))
return sprintf(buf, "eui.%8phN\n", ns->eui);
@@ -1788,11 +2011,28 @@ static ssize_t wwid_show(struct device *dev, struct device_attribute *attr,
}
static DEVICE_ATTR(wwid, S_IRUGO, wwid_show, NULL);
+static ssize_t nguid_show(struct device *dev, struct device_attribute *attr,
+ char *buf)
+{
+ struct nvme_ns *ns = nvme_get_ns_from_dev(dev);
+ return sprintf(buf, "%pU\n", ns->nguid);
+}
+static DEVICE_ATTR(nguid, S_IRUGO, nguid_show, NULL);
+
static ssize_t uuid_show(struct device *dev, struct device_attribute *attr,
char *buf)
{
struct nvme_ns *ns = nvme_get_ns_from_dev(dev);
- return sprintf(buf, "%pU\n", ns->uuid);
+
+ /* For backward compatibility expose the NGUID to userspace if
+ * we have no UUID set
+ */
+ if (uuid_is_null(&ns->uuid)) {
+ printk_ratelimited(KERN_WARNING
+ "No UUID available providing old NGUID\n");
+ return sprintf(buf, "%pU\n", ns->nguid);
+ }
+ return sprintf(buf, "%pU\n", &ns->uuid);
}
static DEVICE_ATTR(uuid, S_IRUGO, uuid_show, NULL);
@@ -1815,6 +2055,7 @@ static DEVICE_ATTR(nsid, S_IRUGO, nsid_show, NULL);
static struct attribute *nvme_ns_attrs[] = {
&dev_attr_wwid.attr,
&dev_attr_uuid.attr,
+ &dev_attr_nguid.attr,
&dev_attr_eui.attr,
&dev_attr_nsid.attr,
NULL,
@@ -1827,7 +2068,12 @@ static umode_t nvme_ns_attrs_are_visible(struct kobject *kobj,
struct nvme_ns *ns = nvme_get_ns_from_dev(dev);
if (a == &dev_attr_uuid.attr) {
- if (!memchr_inv(ns->uuid, 0, sizeof(ns->uuid)))
+ if (uuid_is_null(&ns->uuid) ||
+ !memchr_inv(ns->nguid, 0, sizeof(ns->nguid)))
+ return 0;
+ }
+ if (a == &dev_attr_nguid.attr) {
+ if (!memchr_inv(ns->nguid, 0, sizeof(ns->nguid)))
return 0;
}
if (a == &dev_attr_eui.attr) {
@@ -1916,8 +2162,7 @@ static ssize_t nvme_sysfs_show_subsysnqn(struct device *dev,
{
struct nvme_ctrl *ctrl = dev_get_drvdata(dev);
- return snprintf(buf, PAGE_SIZE, "%s\n",
- ctrl->ops->get_subsysnqn(ctrl));
+ return snprintf(buf, PAGE_SIZE, "%s\n", ctrl->subnqn);
}
static DEVICE_ATTR(subsysnqn, S_IRUGO, nvme_sysfs_show_subsysnqn, NULL);
@@ -1946,24 +2191,16 @@ static struct attribute *nvme_dev_attrs[] = {
NULL
};
-#define CHECK_ATTR(ctrl, a, name) \
- if ((a) == &dev_attr_##name.attr && \
- !(ctrl)->ops->get_##name) \
- return 0
-
static umode_t nvme_dev_attrs_are_visible(struct kobject *kobj,
struct attribute *a, int n)
{
struct device *dev = container_of(kobj, struct device, kobj);
struct nvme_ctrl *ctrl = dev_get_drvdata(dev);
- if (a == &dev_attr_delete_controller.attr) {
- if (!ctrl->ops->delete_ctrl)
- return 0;
- }
-
- CHECK_ATTR(ctrl, a, subsysnqn);
- CHECK_ATTR(ctrl, a, address);
+ if (a == &dev_attr_delete_controller.attr && !ctrl->ops->delete_ctrl)
+ return 0;
+ if (a == &dev_attr_address.attr && !ctrl->ops->get_address)
+ return 0;
return a->mode;
}
@@ -2004,6 +2241,32 @@ static struct nvme_ns *nvme_find_get_ns(struct nvme_ctrl *ctrl, unsigned nsid)
return ret;
}
+static int nvme_setup_streams_ns(struct nvme_ctrl *ctrl, struct nvme_ns *ns)
+{
+ struct streams_directive_params s;
+ int ret;
+
+ if (!ctrl->nr_streams)
+ return 0;
+
+ ret = nvme_get_stream_params(ctrl, &s, ns->ns_id);
+ if (ret)
+ return ret;
+
+ ns->sws = le32_to_cpu(s.sws);
+ ns->sgs = le16_to_cpu(s.sgs);
+
+ if (ns->sws) {
+ unsigned int bs = 1 << ns->lba_shift;
+
+ blk_queue_io_min(ns->queue, bs * ns->sws);
+ if (ns->sgs)
+ blk_queue_io_opt(ns->queue, bs * ns->sws * ns->sgs);
+ }
+
+ return 0;
+}
+
static void nvme_alloc_ns(struct nvme_ctrl *ctrl, unsigned nsid)
{
struct nvme_ns *ns;
@@ -2033,6 +2296,7 @@ static void nvme_alloc_ns(struct nvme_ctrl *ctrl, unsigned nsid)
blk_queue_logical_block_size(ns->queue, 1 << ns->lba_shift);
nvme_set_queue_limits(ctrl, ns->queue);
+ nvme_setup_streams_ns(ctrl, ns);
sprintf(disk_name, "nvme%dn%d", ctrl->instance, ns->instance);
@@ -2041,7 +2305,7 @@ static void nvme_alloc_ns(struct nvme_ctrl *ctrl, unsigned nsid)
if (nvme_nvm_ns_supported(ns, id) &&
nvme_nvm_register(ns, disk_name, node)) {
- dev_warn(ctrl->dev, "%s: LightNVM init failure\n", __func__);
+ dev_warn(ctrl->device, "%s: LightNVM init failure\n", __func__);
goto out_free_id;
}
@@ -2098,7 +2362,6 @@ static void nvme_ns_remove(struct nvme_ns *ns)
if (ns->ndev)
nvme_nvm_unregister_sysfs(ns);
del_gendisk(ns->disk);
- blk_mq_abort_requeue_list(ns->queue);
blk_cleanup_queue(ns->queue);
}
@@ -2217,7 +2480,7 @@ void nvme_queue_scan(struct nvme_ctrl *ctrl)
* removal.
*/
if (ctrl->state == NVME_CTRL_LIVE)
- schedule_work(&ctrl->scan_work);
+ queue_work(nvme_wq, &ctrl->scan_work);
}
EXPORT_SYMBOL_GPL(nvme_queue_scan);
@@ -2272,7 +2535,7 @@ void nvme_complete_async_event(struct nvme_ctrl *ctrl, __le16 status,
/*FALLTHRU*/
case NVME_SC_ABORT_REQ:
++ctrl->event_limit;
- schedule_work(&ctrl->async_event_work);
+ queue_work(nvme_wq, &ctrl->async_event_work);
break;
default:
break;
@@ -2295,7 +2558,7 @@ EXPORT_SYMBOL_GPL(nvme_complete_async_event);
void nvme_queue_async_events(struct nvme_ctrl *ctrl)
{
ctrl->event_limit = NVME_NR_AERS;
- schedule_work(&ctrl->async_event_work);
+ queue_work(nvme_wq, &ctrl->async_event_work);
}
EXPORT_SYMBOL_GPL(nvme_queue_async_events);
@@ -2427,6 +2690,13 @@ void nvme_kill_queues(struct nvme_ctrl *ctrl)
struct nvme_ns *ns;
mutex_lock(&ctrl->namespaces_mutex);
+
+ /* Forcibly unquiesce queues to avoid blocking dispatch */
+ blk_mq_unquiesce_queue(ctrl->admin_q);
+
+ /* Forcibly start all queues to avoid having stuck requests */
+ blk_mq_start_hw_queues(ctrl->admin_q);
+
list_for_each_entry(ns, &ctrl->namespaces, list) {
/*
* Revalidating a dead namespace sets capacity to 0. This will
@@ -2436,8 +2706,19 @@ void nvme_kill_queues(struct nvme_ctrl *ctrl)
continue;
revalidate_disk(ns->disk);
blk_set_queue_dying(ns->queue);
- blk_mq_abort_requeue_list(ns->queue);
- blk_mq_start_stopped_hw_queues(ns->queue, true);
+
+ /* Forcibly unquiesce queues to avoid blocking dispatch */
+ blk_mq_unquiesce_queue(ns->queue);
+
+ /*
+ * Forcibly start all queues to avoid having stuck requests.
+ * Note that we must ensure the queues are not stopped
+ * when the final removal happens.
+ */
+ blk_mq_start_hw_queues(ns->queue);
+
+ /* draining requests in requeue list */
+ blk_mq_kick_requeue_list(ns->queue);
}
mutex_unlock(&ctrl->namespaces_mutex);
}
@@ -2507,7 +2788,7 @@ void nvme_start_queues(struct nvme_ctrl *ctrl)
mutex_lock(&ctrl->namespaces_mutex);
list_for_each_entry(ns, &ctrl->namespaces, list) {
- blk_mq_start_stopped_hw_queues(ns->queue, true);
+ blk_mq_unquiesce_queue(ns->queue);
blk_mq_kick_requeue_list(ns->queue);
}
mutex_unlock(&ctrl->namespaces_mutex);
@@ -2518,10 +2799,15 @@ int __init nvme_core_init(void)
{
int result;
+ nvme_wq = alloc_workqueue("nvme-wq",
+ WQ_UNBOUND | WQ_MEM_RECLAIM | WQ_SYSFS, 0);
+ if (!nvme_wq)
+ return -ENOMEM;
+
result = __register_chrdev(nvme_char_major, 0, NVME_MINORS, "nvme",
&nvme_dev_fops);
if (result < 0)
- return result;
+ goto destroy_wq;
else if (result > 0)
nvme_char_major = result;
@@ -2533,8 +2819,10 @@ int __init nvme_core_init(void)
return 0;
- unregister_chrdev:
+unregister_chrdev:
__unregister_chrdev(nvme_char_major, 0, NVME_MINORS, "nvme");
+destroy_wq:
+ destroy_workqueue(nvme_wq);
return result;
}
@@ -2542,6 +2830,7 @@ void nvme_core_exit(void)
{
class_destroy(nvme_class);
__unregister_chrdev(nvme_char_major, 0, NVME_MINORS, "nvme");
+ destroy_workqueue(nvme_wq);
}
MODULE_LICENSE("GPL");
diff --git a/drivers/nvme/host/fabrics.c b/drivers/nvme/host/fabrics.c
index 990e6fb32a63..2e582a240943 100644
--- a/drivers/nvme/host/fabrics.c
+++ b/drivers/nvme/host/fabrics.c
@@ -58,7 +58,6 @@ static struct nvmf_host *nvmf_host_add(const char *hostnqn)
kref_init(&host->ref);
memcpy(host->nqn, hostnqn, NVMF_NQN_SIZE);
- uuid_be_gen(&host->id);
list_add_tail(&host->list, &nvmf_hosts);
out_unlock:
@@ -75,7 +74,6 @@ static struct nvmf_host *nvmf_host_default(void)
return NULL;
kref_init(&host->ref);
- uuid_be_gen(&host->id);
snprintf(host->nqn, NVMF_NQN_SIZE,
"nqn.2014-08.org.nvmexpress:NVMf:uuid:%pUb", &host->id);
@@ -128,16 +126,6 @@ int nvmf_get_address(struct nvme_ctrl *ctrl, char *buf, int size)
EXPORT_SYMBOL_GPL(nvmf_get_address);
/**
- * nvmf_get_subsysnqn() - Get subsystem NQN
- * @ctrl: Host NVMe controller instance which we got the NQN
- */
-const char *nvmf_get_subsysnqn(struct nvme_ctrl *ctrl)
-{
- return ctrl->opts->subsysnqn;
-}
-EXPORT_SYMBOL_GPL(nvmf_get_subsysnqn);
-
-/**
* nvmf_reg_read32() - NVMe Fabrics "Property Get" API function.
* @ctrl: Host NVMe controller instance maintaining the admin
* queue used to submit the property read command to
@@ -337,6 +325,24 @@ static void nvmf_log_connect_error(struct nvme_ctrl *ctrl,
}
}
break;
+
+ case NVME_SC_CONNECT_INVALID_HOST:
+ dev_err(ctrl->device,
+ "Connect for subsystem %s is not allowed, hostnqn: %s\n",
+ data->subsysnqn, data->hostnqn);
+ break;
+
+ case NVME_SC_CONNECT_CTRL_BUSY:
+ dev_err(ctrl->device,
+ "Connect command failed: controller is busy or not available\n");
+ break;
+
+ case NVME_SC_CONNECT_FORMAT:
+ dev_err(ctrl->device,
+ "Connect incompatible format: %d",
+ cmd->connect.recfmt);
+ break;
+
default:
dev_err(ctrl->device,
"Connect command failed, error wo/DNR bit: %d\n",
@@ -376,13 +382,7 @@ int nvmf_connect_admin_queue(struct nvme_ctrl *ctrl)
cmd.connect.opcode = nvme_fabrics_command;
cmd.connect.fctype = nvme_fabrics_type_connect;
cmd.connect.qid = 0;
-
- /*
- * fabrics spec sets a minimum of depth 32 for admin queue,
- * so set the queue with this depth always until
- * justification otherwise.
- */
- cmd.connect.sqsize = cpu_to_le16(NVMF_AQ_DEPTH - 1);
+ cmd.connect.sqsize = cpu_to_le16(NVME_AQ_DEPTH - 1);
/*
* Set keep-alive timeout in seconds granularity (ms * 1000)
@@ -395,7 +395,7 @@ int nvmf_connect_admin_queue(struct nvme_ctrl *ctrl)
if (!data)
return -ENOMEM;
- memcpy(&data->hostid, &ctrl->opts->host->id, sizeof(uuid_be));
+ uuid_copy(&data->hostid, &ctrl->opts->host->id);
data->cntlid = cpu_to_le16(0xffff);
strncpy(data->subsysnqn, ctrl->opts->subsysnqn, NVMF_NQN_SIZE);
strncpy(data->hostnqn, ctrl->opts->host->nqn, NVMF_NQN_SIZE);
@@ -454,7 +454,7 @@ int nvmf_connect_io_queue(struct nvme_ctrl *ctrl, u16 qid)
if (!data)
return -ENOMEM;
- memcpy(&data->hostid, &ctrl->opts->host->id, sizeof(uuid_be));
+ uuid_copy(&data->hostid, &ctrl->opts->host->id);
data->cntlid = cpu_to_le16(ctrl->cntlid);
strncpy(data->subsysnqn, ctrl->opts->subsysnqn, NVMF_NQN_SIZE);
strncpy(data->hostnqn, ctrl->opts->host->nqn, NVMF_NQN_SIZE);
@@ -474,7 +474,7 @@ EXPORT_SYMBOL_GPL(nvmf_connect_io_queue);
bool nvmf_should_reconnect(struct nvme_ctrl *ctrl)
{
if (ctrl->opts->max_reconnects != -1 &&
- ctrl->opts->nr_reconnects < ctrl->opts->max_reconnects)
+ ctrl->nr_reconnects < ctrl->opts->max_reconnects)
return true;
return false;
@@ -547,6 +547,7 @@ static const match_table_t opt_tokens = {
{ NVMF_OPT_KATO, "keep_alive_tmo=%d" },
{ NVMF_OPT_HOSTNQN, "hostnqn=%s" },
{ NVMF_OPT_HOST_TRADDR, "host_traddr=%s" },
+ { NVMF_OPT_HOST_ID, "hostid=%s" },
{ NVMF_OPT_ERR, NULL }
};
@@ -558,6 +559,7 @@ static int nvmf_parse_options(struct nvmf_ctrl_options *opts,
int token, ret = 0;
size_t nqnlen = 0;
int ctrl_loss_tmo = NVMF_DEF_CTRL_LOSS_TMO;
+ uuid_t hostid;
/* Set defaults */
opts->queue_size = NVMF_DEF_QUEUE_SIZE;
@@ -568,6 +570,8 @@ static int nvmf_parse_options(struct nvmf_ctrl_options *opts,
if (!options)
return -ENOMEM;
+ uuid_gen(&hostid);
+
while ((p = strsep(&o, ",\n")) != NULL) {
if (!*p)
continue;
@@ -724,6 +728,17 @@ static int nvmf_parse_options(struct nvmf_ctrl_options *opts,
}
opts->host_traddr = p;
break;
+ case NVMF_OPT_HOST_ID:
+ p = match_strdup(args);
+ if (!p) {
+ ret = -ENOMEM;
+ goto out;
+ }
+ if (uuid_parse(p, &hostid)) {
+ ret = -EINVAL;
+ goto out;
+ }
+ break;
default:
pr_warn("unknown parameter or missing value '%s' in ctrl creation request\n",
p);
@@ -743,6 +758,8 @@ static int nvmf_parse_options(struct nvmf_ctrl_options *opts,
opts->host = nvmf_default_host;
}
+ uuid_copy(&opts->host->id, &hostid);
+
out:
if (!opts->discovery_nqn && !opts->kato)
opts->kato = NVME_DEFAULT_KATO;
@@ -803,7 +820,8 @@ EXPORT_SYMBOL_GPL(nvmf_free_options);
#define NVMF_REQUIRED_OPTS (NVMF_OPT_TRANSPORT | NVMF_OPT_NQN)
#define NVMF_ALLOWED_OPTS (NVMF_OPT_QUEUE_SIZE | NVMF_OPT_NR_IO_QUEUES | \
- NVMF_OPT_KATO | NVMF_OPT_HOSTNQN)
+ NVMF_OPT_KATO | NVMF_OPT_HOSTNQN | \
+ NVMF_OPT_HOST_ID)
static struct nvme_ctrl *
nvmf_create_ctrl(struct device *dev, const char *buf, size_t count)
@@ -854,6 +872,15 @@ nvmf_create_ctrl(struct device *dev, const char *buf, size_t count)
goto out_unlock;
}
+ if (strcmp(ctrl->subnqn, opts->subsysnqn)) {
+ dev_warn(ctrl->device,
+ "controller returned incorrect NQN: \"%s\".\n",
+ ctrl->subnqn);
+ mutex_unlock(&nvmf_transports_mutex);
+ ctrl->ops->delete_ctrl(ctrl);
+ return ERR_PTR(-EINVAL);
+ }
+
mutex_unlock(&nvmf_transports_mutex);
return ctrl;
diff --git a/drivers/nvme/host/fabrics.h b/drivers/nvme/host/fabrics.h
index f5a9c1fb186f..bf33663218cd 100644
--- a/drivers/nvme/host/fabrics.h
+++ b/drivers/nvme/host/fabrics.h
@@ -36,7 +36,7 @@ struct nvmf_host {
struct kref ref;
struct list_head list;
char nqn[NVMF_NQN_SIZE];
- uuid_be id;
+ uuid_t id;
};
/**
@@ -56,6 +56,7 @@ enum {
NVMF_OPT_RECONNECT_DELAY = 1 << 9,
NVMF_OPT_HOST_TRADDR = 1 << 10,
NVMF_OPT_CTRL_LOSS_TMO = 1 << 11,
+ NVMF_OPT_HOST_ID = 1 << 12,
};
/**
@@ -80,7 +81,6 @@ enum {
* @discovery_nqn: indicates if the subsysnqn is the well-known discovery NQN.
* @kato: Keep-alive timeout.
* @host: Virtual NVMe host, contains the NQN and Host ID.
- * @nr_reconnects: number of reconnect attempted since the last ctrl failure
* @max_reconnects: maximum number of allowed reconnect attempts before removing
* the controller, (-1) means reconnect forever, zero means remove
* immediately;
@@ -98,7 +98,6 @@ struct nvmf_ctrl_options {
bool discovery_nqn;
unsigned int kato;
struct nvmf_host *host;
- int nr_reconnects;
int max_reconnects;
};
@@ -140,7 +139,6 @@ int nvmf_connect_io_queue(struct nvme_ctrl *ctrl, u16 qid);
int nvmf_register_transport(struct nvmf_transport_ops *ops);
void nvmf_unregister_transport(struct nvmf_transport_ops *ops);
void nvmf_free_options(struct nvmf_ctrl_options *opts);
-const char *nvmf_get_subsysnqn(struct nvme_ctrl *ctrl);
int nvmf_get_address(struct nvme_ctrl *ctrl, char *buf, int size);
bool nvmf_should_reconnect(struct nvme_ctrl *ctrl);
diff --git a/drivers/nvme/host/fc.c b/drivers/nvme/host/fc.c
index dca7165fabcf..ed87214fdc0e 100644
--- a/drivers/nvme/host/fc.c
+++ b/drivers/nvme/host/fc.c
@@ -36,7 +36,7 @@
*/
#define NVME_FC_NR_AEN_COMMANDS 1
#define NVME_FC_AQ_BLKMQ_DEPTH \
- (NVMF_AQ_DEPTH - NVME_FC_NR_AEN_COMMANDS)
+ (NVME_AQ_DEPTH - NVME_FC_NR_AEN_COMMANDS)
#define AEN_CMDID_BASE (NVME_FC_AQ_BLKMQ_DEPTH + 1)
enum nvme_fc_queue_flags {
@@ -45,8 +45,6 @@ enum nvme_fc_queue_flags {
#define NVMEFC_QUEUE_DELAY 3 /* ms units */
-#define NVME_FC_MAX_CONNECT_ATTEMPTS 1
-
struct nvme_fc_queue {
struct nvme_fc_ctrl *ctrl;
struct device *dev;
@@ -163,14 +161,12 @@ struct nvme_fc_ctrl {
struct blk_mq_tag_set tag_set;
struct work_struct delete_work;
- struct work_struct reset_work;
struct delayed_work connect_work;
- int reconnect_delay;
- int connect_attempts;
struct kref ref;
u32 flags;
u32 iocnt;
+ wait_queue_head_t ioabort_wait;
struct nvme_fc_fcp_op aen_ops[NVME_FC_NR_AEN_COMMANDS];
@@ -218,7 +214,6 @@ static LIST_HEAD(nvme_fc_lport_list);
static DEFINE_IDA(nvme_fc_local_port_cnt);
static DEFINE_IDA(nvme_fc_ctrl_cnt);
-static struct workqueue_struct *nvme_fc_wq;
@@ -882,8 +877,7 @@ nvme_fc_connect_admin_queue(struct nvme_fc_ctrl *ctrl,
assoc_rqst->assoc_cmd.sqsize = cpu_to_be16(qsize);
/* Linux supports only Dynamic controllers */
assoc_rqst->assoc_cmd.cntlid = cpu_to_be16(0xffff);
- memcpy(&assoc_rqst->assoc_cmd.hostid, &ctrl->ctrl.opts->host->id,
- min_t(size_t, FCNVME_ASSOC_HOSTID_LEN, sizeof(uuid_be)));
+ uuid_copy(&assoc_rqst->assoc_cmd.hostid, &ctrl->ctrl.opts->host->id);
strncpy(assoc_rqst->assoc_cmd.hostnqn, ctrl->ctrl.opts->host->nqn,
min(FCNVME_ASSOC_HOSTNQN_LEN, NVMF_NQN_SIZE));
strncpy(assoc_rqst->assoc_cmd.subnqn, ctrl->ctrl.opts->subsysnqn,
@@ -1143,6 +1137,7 @@ nvme_fc_xmt_disconnect_assoc(struct nvme_fc_ctrl *ctrl)
/* *********************** NVME Ctrl Routines **************************** */
static void __nvme_fc_final_op_cleanup(struct request *rq);
+static void nvme_fc_error_recovery(struct nvme_fc_ctrl *ctrl, char *errmsg);
static int
nvme_fc_reinit_request(void *data, struct request *rq)
@@ -1245,8 +1240,10 @@ __nvme_fc_fcpop_chk_teardowns(struct nvme_fc_ctrl *ctrl,
spin_lock_irqsave(&ctrl->lock, flags);
if (unlikely(op->flags & FCOP_FLAGS_TERMIO)) {
- if (ctrl->flags & FCCTRL_TERMIO)
- ctrl->iocnt--;
+ if (ctrl->flags & FCCTRL_TERMIO) {
+ if (!--ctrl->iocnt)
+ wake_up(&ctrl->ioabort_wait);
+ }
}
if (op->flags & FCOP_FLAGS_RELEASED)
complete_rq = true;
@@ -1269,7 +1266,7 @@ nvme_fc_fcpio_done(struct nvmefc_fcp_req *req)
struct nvme_command *sqe = &op->cmd_iu.sqe;
__le16 status = cpu_to_le16(NVME_SC_SUCCESS << 1);
union nvme_result result;
- bool complete_rq;
+ bool complete_rq, terminate_assoc = true;
/*
* WARNING:
@@ -1298,6 +1295,14 @@ nvme_fc_fcpio_done(struct nvmefc_fcp_req *req)
* fabricate a CQE, the following fields will not be set as they
* are not referenced:
* cqe.sqid, cqe.sqhd, cqe.command_id
+ *
+ * Failure or error of an individual i/o, in a transport
+ * detected fashion unrelated to the nvme completion status,
+ * potentially cause the initiator and target sides to get out
+ * of sync on SQ head/tail (aka outstanding io count allowed).
+ * Per FC-NVME spec, failure of an individual command requires
+ * the connection to be terminated, which in turn requires the
+ * association to be terminated.
*/
fc_dma_sync_single_for_cpu(ctrl->lport->dev, op->fcp_req.rspdma,
@@ -1363,6 +1368,8 @@ nvme_fc_fcpio_done(struct nvmefc_fcp_req *req)
goto done;
}
+ terminate_assoc = false;
+
done:
if (op->flags & FCOP_FLAGS_AEN) {
nvme_complete_async_event(&queue->ctrl->ctrl, status, &result);
@@ -1370,19 +1377,23 @@ done:
atomic_set(&op->state, FCPOP_STATE_IDLE);
op->flags = FCOP_FLAGS_AEN; /* clear other flags */
nvme_fc_ctrl_put(ctrl);
- return;
+ goto check_error;
}
complete_rq = __nvme_fc_fcpop_chk_teardowns(ctrl, op);
if (!complete_rq) {
if (unlikely(op->flags & FCOP_FLAGS_TERMIO)) {
- status = cpu_to_le16(NVME_SC_ABORT_REQ);
+ status = cpu_to_le16(NVME_SC_ABORT_REQ << 1);
if (blk_queue_dying(rq->q))
- status |= cpu_to_le16(NVME_SC_DNR);
+ status |= cpu_to_le16(NVME_SC_DNR << 1);
}
nvme_end_request(rq, status, result);
} else
__nvme_fc_final_op_cleanup(rq);
+
+check_error:
+ if (terminate_assoc)
+ nvme_fc_error_recovery(ctrl, "transport detected io error");
}
static int
@@ -1439,18 +1450,8 @@ nvme_fc_init_request(struct blk_mq_tag_set *set, struct request *rq,
{
struct nvme_fc_ctrl *ctrl = set->driver_data;
struct nvme_fc_fcp_op *op = blk_mq_rq_to_pdu(rq);
- struct nvme_fc_queue *queue = &ctrl->queues[hctx_idx+1];
-
- return __nvme_fc_init_request(ctrl, queue, op, rq, queue->rqcnt++);
-}
-
-static int
-nvme_fc_init_admin_request(struct blk_mq_tag_set *set, struct request *rq,
- unsigned int hctx_idx, unsigned int numa_node)
-{
- struct nvme_fc_ctrl *ctrl = set->driver_data;
- struct nvme_fc_fcp_op *op = blk_mq_rq_to_pdu(rq);
- struct nvme_fc_queue *queue = &ctrl->queues[0];
+ int queue_idx = (set == &ctrl->tag_set) ? hctx_idx + 1 : 0;
+ struct nvme_fc_queue *queue = &ctrl->queues[queue_idx];
return __nvme_fc_init_request(ctrl, queue, op, rq, queue->rqcnt++);
}
@@ -1748,16 +1749,16 @@ nvme_fc_nvme_ctrl_freed(struct nvme_ctrl *nctrl)
static void
nvme_fc_error_recovery(struct nvme_fc_ctrl *ctrl, char *errmsg)
{
+ /* only proceed if in LIVE state - e.g. on first error */
+ if (ctrl->ctrl.state != NVME_CTRL_LIVE)
+ return;
+
dev_warn(ctrl->ctrl.device,
"NVME-FC{%d}: transport association error detected: %s\n",
ctrl->cnum, errmsg);
- dev_info(ctrl->ctrl.device,
+ dev_warn(ctrl->ctrl.device,
"NVME-FC{%d}: resetting controller\n", ctrl->cnum);
- /* stop the queues on error, cleanup is in reset thread */
- if (ctrl->queue_count > 1)
- nvme_stop_queues(&ctrl->ctrl);
-
if (!nvme_change_ctrl_state(&ctrl->ctrl, NVME_CTRL_RECONNECTING)) {
dev_err(ctrl->ctrl.device,
"NVME-FC{%d}: error_recovery: Couldn't change state "
@@ -1765,10 +1766,7 @@ nvme_fc_error_recovery(struct nvme_fc_ctrl *ctrl, char *errmsg)
return;
}
- if (!queue_work(nvme_fc_wq, &ctrl->reset_work))
- dev_err(ctrl->ctrl.device,
- "NVME-FC{%d}: error_recovery: Failed to schedule "
- "reset work\n", ctrl->cnum);
+ nvme_reset_ctrl(&ctrl->ctrl);
}
static enum blk_eh_timer_return
@@ -1877,7 +1875,7 @@ nvme_fc_unmap_data(struct nvme_fc_ctrl *ctrl, struct request *rq,
* level FC exchange resource that is also outstanding. This must be
* considered in all cleanup operations.
*/
-static int
+static blk_status_t
nvme_fc_start_fcp_op(struct nvme_fc_ctrl *ctrl, struct nvme_fc_queue *queue,
struct nvme_fc_fcp_op *op, u32 data_len,
enum nvmefc_fcp_datadir io_dir)
@@ -1892,10 +1890,10 @@ nvme_fc_start_fcp_op(struct nvme_fc_ctrl *ctrl, struct nvme_fc_queue *queue,
* the target device is present
*/
if (ctrl->rport->remoteport.port_state != FC_OBJSTATE_ONLINE)
- return BLK_MQ_RQ_QUEUE_ERROR;
+ return BLK_STS_IOERR;
if (!nvme_fc_ctrl_get(ctrl))
- return BLK_MQ_RQ_QUEUE_ERROR;
+ return BLK_STS_IOERR;
/* format the FC-NVME CMD IU and fcp_req */
cmdiu->connection_id = cpu_to_be64(queue->connection_id);
@@ -1943,8 +1941,9 @@ nvme_fc_start_fcp_op(struct nvme_fc_ctrl *ctrl, struct nvme_fc_queue *queue,
if (ret < 0) {
nvme_cleanup_cmd(op->rq);
nvme_fc_ctrl_put(ctrl);
- return (ret == -ENOMEM || ret == -EAGAIN) ?
- BLK_MQ_RQ_QUEUE_BUSY : BLK_MQ_RQ_QUEUE_ERROR;
+ if (ret == -ENOMEM || ret == -EAGAIN)
+ return BLK_STS_RESOURCE;
+ return BLK_STS_IOERR;
}
}
@@ -1961,28 +1960,26 @@ nvme_fc_start_fcp_op(struct nvme_fc_ctrl *ctrl, struct nvme_fc_queue *queue,
queue->lldd_handle, &op->fcp_req);
if (ret) {
- if (op->rq) { /* normal request */
+ if (op->rq) /* normal request */
nvme_fc_unmap_data(ctrl, op->rq, op);
- nvme_cleanup_cmd(op->rq);
- }
/* else - aen. no cleanup needed */
nvme_fc_ctrl_put(ctrl);
if (ret != -EBUSY)
- return BLK_MQ_RQ_QUEUE_ERROR;
+ return BLK_STS_IOERR;
if (op->rq) {
blk_mq_stop_hw_queues(op->rq->q);
blk_mq_delay_queue(queue->hctx, NVMEFC_QUEUE_DELAY);
}
- return BLK_MQ_RQ_QUEUE_BUSY;
+ return BLK_STS_RESOURCE;
}
- return BLK_MQ_RQ_QUEUE_OK;
+ return BLK_STS_OK;
}
-static int
+static blk_status_t
nvme_fc_queue_rq(struct blk_mq_hw_ctx *hctx,
const struct blk_mq_queue_data *bd)
{
@@ -1995,7 +1992,7 @@ nvme_fc_queue_rq(struct blk_mq_hw_ctx *hctx,
struct nvme_command *sqe = &cmdiu->sqe;
enum nvmefc_fcp_datadir io_dir;
u32 data_len;
- int ret;
+ blk_status_t ret;
ret = nvme_setup_cmd(ns, rq, sqe);
if (ret)
@@ -2050,7 +2047,7 @@ nvme_fc_submit_async_event(struct nvme_ctrl *arg, int aer_idx)
struct nvme_fc_fcp_op *aen_op;
unsigned long flags;
bool terminating = false;
- int ret;
+ blk_status_t ret;
if (aer_idx > NVME_FC_NR_AEN_COMMANDS)
return;
@@ -2082,7 +2079,6 @@ __nvme_fc_final_op_cleanup(struct request *rq)
op->flags &= ~(FCOP_FLAGS_TERMIO | FCOP_FLAGS_RELEASED |
FCOP_FLAGS_COMPLETE);
- nvme_cleanup_cmd(rq);
nvme_fc_unmap_data(ctrl, rq, op);
nvme_complete_rq(rq);
nvme_fc_ctrl_put(ctrl);
@@ -2195,9 +2191,6 @@ nvme_fc_create_io_queues(struct nvme_fc_ctrl *ctrl)
if (!opts->nr_io_queues)
return 0;
- dev_info(ctrl->ctrl.device, "creating %d I/O queues.\n",
- opts->nr_io_queues);
-
nvme_fc_init_io_queues(ctrl);
memset(&ctrl->tag_set, 0, sizeof(ctrl->tag_set));
@@ -2268,9 +2261,6 @@ nvme_fc_reinit_io_queues(struct nvme_fc_ctrl *ctrl)
if (ctrl->queue_count == 1)
return 0;
- dev_info(ctrl->ctrl.device, "Recreating %d I/O queues.\n",
- opts->nr_io_queues);
-
nvme_fc_init_io_queues(ctrl);
ret = blk_mq_reinit_tagset(&ctrl->tag_set);
@@ -2306,7 +2296,7 @@ nvme_fc_create_association(struct nvme_fc_ctrl *ctrl)
int ret;
bool changed;
- ctrl->connect_attempts++;
+ ++ctrl->ctrl.nr_reconnects;
/*
* Create the admin queue
@@ -2403,9 +2393,7 @@ nvme_fc_create_association(struct nvme_fc_ctrl *ctrl)
changed = nvme_change_ctrl_state(&ctrl->ctrl, NVME_CTRL_LIVE);
WARN_ON_ONCE(!changed);
- ctrl->connect_attempts = 0;
-
- kref_get(&ctrl->ctrl.kref);
+ ctrl->ctrl.nr_reconnects = 0;
if (ctrl->queue_count > 1) {
nvme_start_queues(&ctrl->ctrl);
@@ -2491,11 +2479,7 @@ nvme_fc_delete_association(struct nvme_fc_ctrl *ctrl)
/* wait for all io that had to be aborted */
spin_lock_irqsave(&ctrl->lock, flags);
- while (ctrl->iocnt) {
- spin_unlock_irqrestore(&ctrl->lock, flags);
- msleep(1000);
- spin_lock_irqsave(&ctrl->lock, flags);
- }
+ wait_event_lock_irq(ctrl->ioabort_wait, ctrl->iocnt == 0, ctrl->lock);
ctrl->flags &= ~FCCTRL_TERMIO;
spin_unlock_irqrestore(&ctrl->lock, flags);
@@ -2525,7 +2509,7 @@ nvme_fc_delete_ctrl_work(struct work_struct *work)
struct nvme_fc_ctrl *ctrl =
container_of(work, struct nvme_fc_ctrl, delete_work);
- cancel_work_sync(&ctrl->reset_work);
+ cancel_work_sync(&ctrl->ctrl.reset_work);
cancel_delayed_work_sync(&ctrl->connect_work);
/*
@@ -2536,26 +2520,32 @@ nvme_fc_delete_ctrl_work(struct work_struct *work)
/*
* tear down the controller
- * This will result in the last reference on the nvme ctrl to
- * expire, calling the transport nvme_fc_nvme_ctrl_freed() callback.
- * From there, the transport will tear down it's logical queues and
- * association.
+ * After the last reference on the nvme ctrl is removed,
+ * the transport nvme_fc_nvme_ctrl_freed() callback will be
+ * invoked. From there, the transport will tear down it's
+ * logical queues and association.
*/
nvme_uninit_ctrl(&ctrl->ctrl);
nvme_put_ctrl(&ctrl->ctrl);
}
-static int
-__nvme_fc_del_ctrl(struct nvme_fc_ctrl *ctrl)
+static bool
+__nvme_fc_schedule_delete_work(struct nvme_fc_ctrl *ctrl)
{
if (!nvme_change_ctrl_state(&ctrl->ctrl, NVME_CTRL_DELETING))
- return -EBUSY;
+ return true;
- if (!queue_work(nvme_fc_wq, &ctrl->delete_work))
- return -EBUSY;
+ if (!queue_work(nvme_wq, &ctrl->delete_work))
+ return true;
- return 0;
+ return false;
+}
+
+static int
+__nvme_fc_del_ctrl(struct nvme_fc_ctrl *ctrl)
+{
+ return __nvme_fc_schedule_delete_work(ctrl) ? -EBUSY : 0;
}
/*
@@ -2573,7 +2563,7 @@ nvme_fc_del_nvme_ctrl(struct nvme_ctrl *nctrl)
ret = __nvme_fc_del_ctrl(ctrl);
if (!ret)
- flush_workqueue(nvme_fc_wq);
+ flush_workqueue(nvme_wq);
nvme_put_ctrl(&ctrl->ctrl);
@@ -2581,83 +2571,62 @@ nvme_fc_del_nvme_ctrl(struct nvme_ctrl *nctrl)
}
static void
-nvme_fc_reset_ctrl_work(struct work_struct *work)
+nvme_fc_reconnect_or_delete(struct nvme_fc_ctrl *ctrl, int status)
{
- struct nvme_fc_ctrl *ctrl =
- container_of(work, struct nvme_fc_ctrl, reset_work);
- int ret;
+ /* If we are resetting/deleting then do nothing */
+ if (ctrl->ctrl.state != NVME_CTRL_RECONNECTING) {
+ WARN_ON_ONCE(ctrl->ctrl.state == NVME_CTRL_NEW ||
+ ctrl->ctrl.state == NVME_CTRL_LIVE);
+ return;
+ }
- /* will block will waiting for io to terminate */
- nvme_fc_delete_association(ctrl);
+ dev_info(ctrl->ctrl.device,
+ "NVME-FC{%d}: reset: Reconnect attempt failed (%d)\n",
+ ctrl->cnum, status);
- ret = nvme_fc_create_association(ctrl);
- if (ret) {
+ if (nvmf_should_reconnect(&ctrl->ctrl)) {
+ dev_info(ctrl->ctrl.device,
+ "NVME-FC{%d}: Reconnect attempt in %d seconds.\n",
+ ctrl->cnum, ctrl->ctrl.opts->reconnect_delay);
+ queue_delayed_work(nvme_wq, &ctrl->connect_work,
+ ctrl->ctrl.opts->reconnect_delay * HZ);
+ } else {
dev_warn(ctrl->ctrl.device,
- "NVME-FC{%d}: reset: Reconnect attempt failed (%d)\n",
- ctrl->cnum, ret);
- if (ctrl->connect_attempts >= NVME_FC_MAX_CONNECT_ATTEMPTS) {
- dev_warn(ctrl->ctrl.device,
"NVME-FC{%d}: Max reconnect attempts (%d) "
"reached. Removing controller\n",
- ctrl->cnum, ctrl->connect_attempts);
-
- if (!nvme_change_ctrl_state(&ctrl->ctrl,
- NVME_CTRL_DELETING)) {
- dev_err(ctrl->ctrl.device,
- "NVME-FC{%d}: failed to change state "
- "to DELETING\n", ctrl->cnum);
- return;
- }
-
- WARN_ON(!queue_work(nvme_fc_wq, &ctrl->delete_work));
- return;
- }
-
- dev_warn(ctrl->ctrl.device,
- "NVME-FC{%d}: Reconnect attempt in %d seconds.\n",
- ctrl->cnum, ctrl->reconnect_delay);
- queue_delayed_work(nvme_fc_wq, &ctrl->connect_work,
- ctrl->reconnect_delay * HZ);
- } else
- dev_info(ctrl->ctrl.device,
- "NVME-FC{%d}: controller reset complete\n", ctrl->cnum);
+ ctrl->cnum, ctrl->ctrl.nr_reconnects);
+ WARN_ON(__nvme_fc_schedule_delete_work(ctrl));
+ }
}
-/*
- * called by the nvme core layer, for sysfs interface that requests
- * a reset of the nvme controller
- */
-static int
-nvme_fc_reset_nvme_ctrl(struct nvme_ctrl *nctrl)
+static void
+nvme_fc_reset_ctrl_work(struct work_struct *work)
{
- struct nvme_fc_ctrl *ctrl = to_fc_ctrl(nctrl);
-
- dev_warn(ctrl->ctrl.device,
- "NVME-FC{%d}: admin requested controller reset\n", ctrl->cnum);
-
- if (!nvme_change_ctrl_state(&ctrl->ctrl, NVME_CTRL_RESETTING))
- return -EBUSY;
-
- if (!queue_work(nvme_fc_wq, &ctrl->reset_work))
- return -EBUSY;
+ struct nvme_fc_ctrl *ctrl =
+ container_of(work, struct nvme_fc_ctrl, ctrl.reset_work);
+ int ret;
- flush_work(&ctrl->reset_work);
+ /* will block will waiting for io to terminate */
+ nvme_fc_delete_association(ctrl);
- return 0;
+ ret = nvme_fc_create_association(ctrl);
+ if (ret)
+ nvme_fc_reconnect_or_delete(ctrl, ret);
+ else
+ dev_info(ctrl->ctrl.device,
+ "NVME-FC{%d}: controller reset complete\n", ctrl->cnum);
}
static const struct nvme_ctrl_ops nvme_fc_ctrl_ops = {
.name = "fc",
.module = THIS_MODULE,
- .is_fabrics = true,
+ .flags = NVME_F_FABRICS,
.reg_read32 = nvmf_reg_read32,
.reg_read64 = nvmf_reg_read64,
.reg_write32 = nvmf_reg_write32,
- .reset_ctrl = nvme_fc_reset_nvme_ctrl,
.free_ctrl = nvme_fc_nvme_ctrl_freed,
.submit_async_event = nvme_fc_submit_async_event,
.delete_ctrl = nvme_fc_del_nvme_ctrl,
- .get_subsysnqn = nvmf_get_subsysnqn,
.get_address = nvmf_get_address,
};
@@ -2671,34 +2640,9 @@ nvme_fc_connect_ctrl_work(struct work_struct *work)
struct nvme_fc_ctrl, connect_work);
ret = nvme_fc_create_association(ctrl);
- if (ret) {
- dev_warn(ctrl->ctrl.device,
- "NVME-FC{%d}: Reconnect attempt failed (%d)\n",
- ctrl->cnum, ret);
- if (ctrl->connect_attempts >= NVME_FC_MAX_CONNECT_ATTEMPTS) {
- dev_warn(ctrl->ctrl.device,
- "NVME-FC{%d}: Max reconnect attempts (%d) "
- "reached. Removing controller\n",
- ctrl->cnum, ctrl->connect_attempts);
-
- if (!nvme_change_ctrl_state(&ctrl->ctrl,
- NVME_CTRL_DELETING)) {
- dev_err(ctrl->ctrl.device,
- "NVME-FC{%d}: failed to change state "
- "to DELETING\n", ctrl->cnum);
- return;
- }
-
- WARN_ON(!queue_work(nvme_fc_wq, &ctrl->delete_work));
- return;
- }
-
- dev_warn(ctrl->ctrl.device,
- "NVME-FC{%d}: Reconnect attempt in %d seconds.\n",
- ctrl->cnum, ctrl->reconnect_delay);
- queue_delayed_work(nvme_fc_wq, &ctrl->connect_work,
- ctrl->reconnect_delay * HZ);
- } else
+ if (ret)
+ nvme_fc_reconnect_or_delete(ctrl, ret);
+ else
dev_info(ctrl->ctrl.device,
"NVME-FC{%d}: controller reconnect complete\n",
ctrl->cnum);
@@ -2708,7 +2652,7 @@ nvme_fc_connect_ctrl_work(struct work_struct *work)
static const struct blk_mq_ops nvme_fc_admin_mq_ops = {
.queue_rq = nvme_fc_queue_rq,
.complete = nvme_fc_complete_rq,
- .init_request = nvme_fc_init_admin_request,
+ .init_request = nvme_fc_init_request,
.exit_request = nvme_fc_exit_request,
.reinit_request = nvme_fc_reinit_request,
.init_hctx = nvme_fc_init_admin_hctx,
@@ -2753,9 +2697,8 @@ nvme_fc_init_ctrl(struct device *dev, struct nvmf_ctrl_options *opts,
kref_init(&ctrl->ref);
INIT_WORK(&ctrl->delete_work, nvme_fc_delete_ctrl_work);
- INIT_WORK(&ctrl->reset_work, nvme_fc_reset_ctrl_work);
+ INIT_WORK(&ctrl->ctrl.reset_work, nvme_fc_reset_ctrl_work);
INIT_DELAYED_WORK(&ctrl->connect_work, nvme_fc_connect_ctrl_work);
- ctrl->reconnect_delay = opts->reconnect_delay;
spin_lock_init(&ctrl->lock);
/* io queue count */
@@ -2821,6 +2764,9 @@ nvme_fc_init_ctrl(struct device *dev, struct nvmf_ctrl_options *opts,
nvme_uninit_ctrl(&ctrl->ctrl);
nvme_put_ctrl(&ctrl->ctrl);
+ /* Remove core ctrl ref. */
+ nvme_put_ctrl(&ctrl->ctrl);
+
/* as we're past the point where we transition to the ref
* counting teardown path, if we return a bad pointer here,
* the calling routine, thinking it's prior to the
@@ -2835,6 +2781,8 @@ nvme_fc_init_ctrl(struct device *dev, struct nvmf_ctrl_options *opts,
return ERR_PTR(ret);
}
+ kref_get(&ctrl->ctrl.kref);
+
dev_info(ctrl->ctrl.device,
"NVME-FC{%d}: new ctrl: NQN \"%s\"\n",
ctrl->cnum, ctrl->ctrl.opts->subsysnqn);
@@ -2971,26 +2919,13 @@ nvme_fc_create_ctrl(struct device *dev, struct nvmf_ctrl_options *opts)
static struct nvmf_transport_ops nvme_fc_transport = {
.name = "fc",
.required_opts = NVMF_OPT_TRADDR | NVMF_OPT_HOST_TRADDR,
- .allowed_opts = NVMF_OPT_RECONNECT_DELAY,
+ .allowed_opts = NVMF_OPT_RECONNECT_DELAY | NVMF_OPT_CTRL_LOSS_TMO,
.create_ctrl = nvme_fc_create_ctrl,
};
static int __init nvme_fc_init_module(void)
{
- int ret;
-
- nvme_fc_wq = create_workqueue("nvme_fc_wq");
- if (!nvme_fc_wq)
- return -ENOMEM;
-
- ret = nvmf_register_transport(&nvme_fc_transport);
- if (ret)
- goto err;
-
- return 0;
-err:
- destroy_workqueue(nvme_fc_wq);
- return ret;
+ return nvmf_register_transport(&nvme_fc_transport);
}
static void __exit nvme_fc_exit_module(void)
@@ -3001,8 +2936,6 @@ static void __exit nvme_fc_exit_module(void)
nvmf_unregister_transport(&nvme_fc_transport);
- destroy_workqueue(nvme_fc_wq);
-
ida_destroy(&nvme_fc_local_port_cnt);
ida_destroy(&nvme_fc_ctrl_cnt);
}
diff --git a/drivers/nvme/host/lightnvm.c b/drivers/nvme/host/lightnvm.c
index f5df78ed1e10..be8541335e31 100644
--- a/drivers/nvme/host/lightnvm.c
+++ b/drivers/nvme/host/lightnvm.c
@@ -242,7 +242,7 @@ static inline void _nvme_nvm_check_size(void)
BUILD_BUG_ON(sizeof(struct nvme_nvm_erase_blk) != 64);
BUILD_BUG_ON(sizeof(struct nvme_nvm_id_group) != 960);
BUILD_BUG_ON(sizeof(struct nvme_nvm_addr_format) != 16);
- BUILD_BUG_ON(sizeof(struct nvme_nvm_id) != 4096);
+ BUILD_BUG_ON(sizeof(struct nvme_nvm_id) != NVME_IDENTIFY_DATA_SIZE);
BUILD_BUG_ON(sizeof(struct nvme_nvm_bb_tbl) != 64);
}
@@ -480,7 +480,7 @@ static inline void nvme_nvm_rqtocmd(struct nvm_rq *rqd, struct nvme_ns *ns,
rqd->bio->bi_iter.bi_sector));
}
-static void nvme_nvm_end_io(struct request *rq, int error)
+static void nvme_nvm_end_io(struct request *rq, blk_status_t status)
{
struct nvm_rq *rqd = rq->end_io_data;
@@ -509,7 +509,7 @@ static int nvme_nvm_submit_io(struct nvm_dev *dev, struct nvm_rq *rqd)
rq = nvme_alloc_request(q, (struct nvme_command *)cmd, 0, NVME_QID_ANY);
if (IS_ERR(rq)) {
kfree(cmd);
- return -ENOMEM;
+ return PTR_ERR(rq);
}
rq->cmd_flags &= ~REQ_FAILFAST_DRIVER;
@@ -571,13 +571,6 @@ static struct nvm_dev_ops nvme_nvm_dev_ops = {
.max_phys_sect = 64,
};
-static void nvme_nvm_end_user_vio(struct request *rq, int error)
-{
- struct completion *waiting = rq->end_io_data;
-
- complete(waiting);
-}
-
static int nvme_nvm_submit_user_cmd(struct request_queue *q,
struct nvme_ns *ns,
struct nvme_nvm_command *vcmd,
@@ -608,7 +601,6 @@ static int nvme_nvm_submit_user_cmd(struct request_queue *q,
rq->timeout = timeout ? timeout : ADMIN_TIMEOUT;
rq->cmd_flags &= ~REQ_FAILFAST_DRIVER;
- rq->end_io_data = &wait;
if (ppa_buf && ppa_len) {
ppa_list = dma_pool_alloc(dev->dma_pool, GFP_KERNEL, &ppa_dma);
@@ -662,9 +654,7 @@ static int nvme_nvm_submit_user_cmd(struct request_queue *q,
}
submit:
- blk_execute_rq_nowait(q, NULL, rq, 0, nvme_nvm_end_user_vio);
-
- wait_for_completion_io(&wait);
+ blk_execute_rq(q, NULL, rq, 0);
if (nvme_req(rq)->flags & NVME_REQ_CANCELLED)
ret = -EINTR;
diff --git a/drivers/nvme/host/nvme.h b/drivers/nvme/host/nvme.h
index 29c708ca9621..d70ff0fdd36b 100644
--- a/drivers/nvme/host/nvme.h
+++ b/drivers/nvme/host/nvme.h
@@ -27,12 +27,11 @@ extern unsigned char nvme_io_timeout;
extern unsigned char admin_timeout;
#define ADMIN_TIMEOUT (admin_timeout * HZ)
-extern unsigned char shutdown_timeout;
-#define SHUTDOWN_TIMEOUT (shutdown_timeout * HZ)
-
#define NVME_DEFAULT_KATO 5
#define NVME_KATO_GRACE 10
+extern struct workqueue_struct *nvme_wq;
+
enum {
NVME_NS_LBA = 0,
NVME_NS_LIGHTNVM = 1,
@@ -131,6 +130,7 @@ struct nvme_ctrl {
struct device *device; /* char device */
struct list_head node;
struct ida ns_ida;
+ struct work_struct reset_work;
struct opal_dev *opal_dev;
@@ -138,6 +138,7 @@ struct nvme_ctrl {
char serial[20];
char model[40];
char firmware_rev[8];
+ char subnqn[NVMF_NQN_SIZE];
u16 cntlid;
u32 ctrl_config;
@@ -147,6 +148,8 @@ struct nvme_ctrl {
u16 oncs;
u16 vid;
u16 oacs;
+ u16 nssa;
+ u16 nr_streams;
atomic_t abort_limit;
u8 event_limit;
u8 vwc;
@@ -165,6 +168,10 @@ struct nvme_ctrl {
/* Power saving configuration */
u64 ps_max_latency_us;
+ bool apst_enabled;
+
+ u32 hmpre;
+ u32 hmmin;
/* Fabrics only */
u16 sqsize;
@@ -172,12 +179,10 @@ struct nvme_ctrl {
u32 iorcsz;
u16 icdoff;
u16 maxcmd;
+ int nr_reconnects;
struct nvmf_ctrl_options *opts;
};
-/*
- * An NVM Express namespace is equivalent to a SCSI LUN
- */
struct nvme_ns {
struct list_head list;
@@ -189,14 +194,18 @@ struct nvme_ns {
int instance;
u8 eui[8];
- u8 uuid[16];
+ u8 nguid[16];
+ uuid_t uuid;
unsigned ns_id;
int lba_shift;
u16 ms;
+ u16 sgs;
+ u32 sws;
bool ext;
u8 pi_type;
unsigned long flags;
+ u16 noiob;
#define NVME_NS_REMOVING 0
#define NVME_NS_DEAD 1
@@ -208,15 +217,15 @@ struct nvme_ns {
struct nvme_ctrl_ops {
const char *name;
struct module *module;
- bool is_fabrics;
+ unsigned int flags;
+#define NVME_F_FABRICS (1 << 0)
+#define NVME_F_METADATA_SUPPORTED (1 << 1)
int (*reg_read32)(struct nvme_ctrl *ctrl, u32 off, u32 *val);
int (*reg_write32)(struct nvme_ctrl *ctrl, u32 off, u32 val);
int (*reg_read64)(struct nvme_ctrl *ctrl, u32 off, u64 *val);
- int (*reset_ctrl)(struct nvme_ctrl *ctrl);
void (*free_ctrl)(struct nvme_ctrl *ctrl);
void (*submit_async_event)(struct nvme_ctrl *ctrl, int aer_idx);
int (*delete_ctrl)(struct nvme_ctrl *ctrl);
- const char *(*get_subsysnqn)(struct nvme_ctrl *ctrl);
int (*get_address)(struct nvme_ctrl *ctrl, char *buf, int size);
};
@@ -294,7 +303,7 @@ void nvme_start_freeze(struct nvme_ctrl *ctrl);
#define NVME_QID_ANY -1
struct request *nvme_alloc_request(struct request_queue *q,
struct nvme_command *cmd, unsigned int flags, int qid);
-int nvme_setup_cmd(struct nvme_ns *ns, struct request *req,
+blk_status_t nvme_setup_cmd(struct nvme_ns *ns, struct request *req,
struct nvme_command *cmd);
int nvme_submit_sync_cmd(struct request_queue *q, struct nvme_command *cmd,
void *buf, unsigned bufflen);
@@ -308,23 +317,10 @@ int __nvme_submit_user_cmd(struct request_queue *q, struct nvme_command *cmd,
void __user *ubuffer, unsigned bufflen,
void __user *meta_buffer, unsigned meta_len, u32 meta_seed,
u32 *result, unsigned timeout);
-int nvme_identify_ctrl(struct nvme_ctrl *dev, struct nvme_id_ctrl **id);
-int nvme_identify_ns(struct nvme_ctrl *dev, unsigned nsid,
- struct nvme_id_ns **id);
-int nvme_get_log_page(struct nvme_ctrl *dev, struct nvme_smart_log **log);
-int nvme_get_features(struct nvme_ctrl *dev, unsigned fid, unsigned nsid,
- void *buffer, size_t buflen, u32 *result);
-int nvme_set_features(struct nvme_ctrl *dev, unsigned fid, unsigned dword11,
- void *buffer, size_t buflen, u32 *result);
int nvme_set_queue_count(struct nvme_ctrl *ctrl, int *count);
void nvme_start_keep_alive(struct nvme_ctrl *ctrl);
void nvme_stop_keep_alive(struct nvme_ctrl *ctrl);
-
-struct sg_io_hdr;
-
-int nvme_sg_io(struct nvme_ns *ns, struct sg_io_hdr __user *u_hdr);
-int nvme_sg_io32(struct nvme_ns *ns, unsigned long arg);
-int nvme_sg_get_version_num(int __user *ip);
+int nvme_reset_ctrl(struct nvme_ctrl *ctrl);
#ifdef CONFIG_NVM
int nvme_nvm_ns_supported(struct nvme_ns *ns, struct nvme_id_ns *id);
diff --git a/drivers/nvme/host/pci.c b/drivers/nvme/host/pci.c
index 4c2ff2bb26bc..5b1ac79fb607 100644
--- a/drivers/nvme/host/pci.c
+++ b/drivers/nvme/host/pci.c
@@ -17,28 +17,15 @@
#include <linux/blkdev.h>
#include <linux/blk-mq.h>
#include <linux/blk-mq-pci.h>
-#include <linux/cpu.h>
-#include <linux/delay.h>
#include <linux/dmi.h>
-#include <linux/errno.h>
-#include <linux/fs.h>
-#include <linux/genhd.h>
-#include <linux/hdreg.h>
-#include <linux/idr.h>
#include <linux/init.h>
#include <linux/interrupt.h>
#include <linux/io.h>
-#include <linux/kdev_t.h>
-#include <linux/kernel.h>
#include <linux/mm.h>
#include <linux/module.h>
-#include <linux/moduleparam.h>
#include <linux/mutex.h>
#include <linux/pci.h>
#include <linux/poison.h>
-#include <linux/ptrace.h>
-#include <linux/sched.h>
-#include <linux/slab.h>
#include <linux/t10-pi.h>
#include <linux/timer.h>
#include <linux/types.h>
@@ -49,7 +36,6 @@
#include "nvme.h"
#define NVME_Q_DEPTH 1024
-#define NVME_AQ_DEPTH 256
#define SQ_SIZE(depth) (depth * sizeof(struct nvme_command))
#define CQ_SIZE(depth) (depth * sizeof(struct nvme_completion))
@@ -66,12 +52,14 @@ static bool use_cmb_sqes = true;
module_param(use_cmb_sqes, bool, 0644);
MODULE_PARM_DESC(use_cmb_sqes, "use controller's memory buffer for I/O SQes");
-static struct workqueue_struct *nvme_workq;
+static unsigned int max_host_mem_size_mb = 128;
+module_param(max_host_mem_size_mb, uint, 0444);
+MODULE_PARM_DESC(max_host_mem_size_mb,
+ "Maximum Host Memory Buffer (HMB) size per controller (in MiB)");
struct nvme_dev;
struct nvme_queue;
-static int nvme_reset(struct nvme_dev *dev);
static void nvme_process_cq(struct nvme_queue *nvmeq);
static void nvme_dev_disable(struct nvme_dev *dev, bool shutdown);
@@ -92,9 +80,8 @@ struct nvme_dev {
int q_depth;
u32 db_stride;
void __iomem *bar;
- struct work_struct reset_work;
+ unsigned long bar_mapped_size;
struct work_struct remove_work;
- struct timer_list watchdog_timer;
struct mutex shutdown_lock;
bool subsystem;
void __iomem *cmb;
@@ -104,10 +91,18 @@ struct nvme_dev {
u32 cmbloc;
struct nvme_ctrl ctrl;
struct completion ioq_wait;
+
+ /* shadow doorbell buffer support: */
u32 *dbbuf_dbs;
dma_addr_t dbbuf_dbs_dma_addr;
u32 *dbbuf_eis;
dma_addr_t dbbuf_eis_dma_addr;
+
+ /* host memory buffer support: */
+ u64 host_mem_size;
+ u32 nr_host_mem_descs;
+ struct nvme_host_mem_buf_desc *host_mem_descs;
+ void **host_mem_desc_bufs;
};
static inline unsigned int sq_idx(unsigned int qid, u32 stride)
@@ -185,8 +180,8 @@ static inline void _nvme_check_size(void)
BUILD_BUG_ON(sizeof(struct nvme_format_cmd) != 64);
BUILD_BUG_ON(sizeof(struct nvme_abort_cmd) != 64);
BUILD_BUG_ON(sizeof(struct nvme_command) != 64);
- BUILD_BUG_ON(sizeof(struct nvme_id_ctrl) != 4096);
- BUILD_BUG_ON(sizeof(struct nvme_id_ns) != 4096);
+ BUILD_BUG_ON(sizeof(struct nvme_id_ctrl) != NVME_IDENTIFY_DATA_SIZE);
+ BUILD_BUG_ON(sizeof(struct nvme_id_ns) != NVME_IDENTIFY_DATA_SIZE);
BUILD_BUG_ON(sizeof(struct nvme_lba_range_type) != 64);
BUILD_BUG_ON(sizeof(struct nvme_smart_log) != 512);
BUILD_BUG_ON(sizeof(struct nvme_dbbuf) != 64);
@@ -263,7 +258,7 @@ static void nvme_dbbuf_set(struct nvme_dev *dev)
c.dbbuf.prp2 = cpu_to_le64(dev->dbbuf_eis_dma_addr);
if (nvme_submit_sync_cmd(dev->ctrl.admin_q, &c, NULL, 0)) {
- dev_warn(dev->dev, "unable to set dbbuf\n");
+ dev_warn(dev->ctrl.device, "unable to set dbbuf\n");
/* Free memory and continue on */
nvme_dbbuf_dma_free(dev);
}
@@ -350,19 +345,6 @@ static void nvme_admin_exit_hctx(struct blk_mq_hw_ctx *hctx, unsigned int hctx_i
nvmeq->tags = NULL;
}
-static int nvme_admin_init_request(struct blk_mq_tag_set *set,
- struct request *req, unsigned int hctx_idx,
- unsigned int numa_node)
-{
- struct nvme_dev *dev = set->driver_data;
- struct nvme_iod *iod = blk_mq_rq_to_pdu(req);
- struct nvme_queue *nvmeq = dev->queues[0];
-
- BUG_ON(!nvmeq);
- iod->nvmeq = nvmeq;
- return 0;
-}
-
static int nvme_init_hctx(struct blk_mq_hw_ctx *hctx, void *data,
unsigned int hctx_idx)
{
@@ -382,7 +364,8 @@ static int nvme_init_request(struct blk_mq_tag_set *set, struct request *req,
{
struct nvme_dev *dev = set->driver_data;
struct nvme_iod *iod = blk_mq_rq_to_pdu(req);
- struct nvme_queue *nvmeq = dev->queues[hctx_idx + 1];
+ int queue_idx = (set == &dev->tagset) ? hctx_idx + 1 : 0;
+ struct nvme_queue *nvmeq = dev->queues[queue_idx];
BUG_ON(!nvmeq);
iod->nvmeq = nvmeq;
@@ -427,7 +410,7 @@ static __le64 **iod_list(struct request *req)
return (__le64 **)(iod->sg + blk_rq_nr_phys_segments(req));
}
-static int nvme_init_iod(struct request *rq, struct nvme_dev *dev)
+static blk_status_t nvme_init_iod(struct request *rq, struct nvme_dev *dev)
{
struct nvme_iod *iod = blk_mq_rq_to_pdu(rq);
int nseg = blk_rq_nr_phys_segments(rq);
@@ -436,7 +419,7 @@ static int nvme_init_iod(struct request *rq, struct nvme_dev *dev)
if (nseg > NVME_INT_PAGES || size > NVME_INT_BYTES(dev)) {
iod->sg = kmalloc(nvme_iod_alloc_size(dev, size, nseg), GFP_ATOMIC);
if (!iod->sg)
- return BLK_MQ_RQ_QUEUE_BUSY;
+ return BLK_STS_RESOURCE;
} else {
iod->sg = iod->inline_sg;
}
@@ -446,7 +429,7 @@ static int nvme_init_iod(struct request *rq, struct nvme_dev *dev)
iod->nents = 0;
iod->length = size;
- return BLK_MQ_RQ_QUEUE_OK;
+ return BLK_STS_OK;
}
static void nvme_free_iod(struct nvme_dev *dev, struct request *req)
@@ -616,21 +599,21 @@ static bool nvme_setup_prps(struct nvme_dev *dev, struct request *req)
return true;
}
-static int nvme_map_data(struct nvme_dev *dev, struct request *req,
+static blk_status_t nvme_map_data(struct nvme_dev *dev, struct request *req,
struct nvme_command *cmnd)
{
struct nvme_iod *iod = blk_mq_rq_to_pdu(req);
struct request_queue *q = req->q;
enum dma_data_direction dma_dir = rq_data_dir(req) ?
DMA_TO_DEVICE : DMA_FROM_DEVICE;
- int ret = BLK_MQ_RQ_QUEUE_ERROR;
+ blk_status_t ret = BLK_STS_IOERR;
sg_init_table(iod->sg, blk_rq_nr_phys_segments(req));
iod->nents = blk_rq_map_sg(q, req, iod->sg);
if (!iod->nents)
goto out;
- ret = BLK_MQ_RQ_QUEUE_BUSY;
+ ret = BLK_STS_RESOURCE;
if (!dma_map_sg_attrs(dev->dev, iod->sg, iod->nents, dma_dir,
DMA_ATTR_NO_WARN))
goto out;
@@ -638,7 +621,7 @@ static int nvme_map_data(struct nvme_dev *dev, struct request *req,
if (!nvme_setup_prps(dev, req))
goto out_unmap;
- ret = BLK_MQ_RQ_QUEUE_ERROR;
+ ret = BLK_STS_IOERR;
if (blk_integrity_rq(req)) {
if (blk_rq_count_integrity_sg(q, req->bio) != 1)
goto out_unmap;
@@ -658,7 +641,7 @@ static int nvme_map_data(struct nvme_dev *dev, struct request *req,
cmnd->rw.dptr.prp2 = cpu_to_le64(iod->first_dma);
if (blk_integrity_rq(req))
cmnd->rw.metadata = cpu_to_le64(sg_dma_address(&iod->meta_sg));
- return BLK_MQ_RQ_QUEUE_OK;
+ return BLK_STS_OK;
out_unmap:
dma_unmap_sg(dev->dev, iod->sg, iod->nents, dma_dir);
@@ -688,7 +671,7 @@ static void nvme_unmap_data(struct nvme_dev *dev, struct request *req)
/*
* NOTE: ns is NULL when called on the admin queue.
*/
-static int nvme_queue_rq(struct blk_mq_hw_ctx *hctx,
+static blk_status_t nvme_queue_rq(struct blk_mq_hw_ctx *hctx,
const struct blk_mq_queue_data *bd)
{
struct nvme_ns *ns = hctx->queue->queuedata;
@@ -696,47 +679,34 @@ static int nvme_queue_rq(struct blk_mq_hw_ctx *hctx,
struct nvme_dev *dev = nvmeq->dev;
struct request *req = bd->rq;
struct nvme_command cmnd;
- int ret = BLK_MQ_RQ_QUEUE_OK;
-
- /*
- * If formated with metadata, require the block layer provide a buffer
- * unless this namespace is formated such that the metadata can be
- * stripped/generated by the controller with PRACT=1.
- */
- if (ns && ns->ms && !blk_integrity_rq(req)) {
- if (!(ns->pi_type && ns->ms == 8) &&
- !blk_rq_is_passthrough(req)) {
- blk_mq_end_request(req, -EFAULT);
- return BLK_MQ_RQ_QUEUE_OK;
- }
- }
+ blk_status_t ret;
ret = nvme_setup_cmd(ns, req, &cmnd);
- if (ret != BLK_MQ_RQ_QUEUE_OK)
+ if (ret)
return ret;
ret = nvme_init_iod(req, dev);
- if (ret != BLK_MQ_RQ_QUEUE_OK)
+ if (ret)
goto out_free_cmd;
- if (blk_rq_nr_phys_segments(req))
+ if (blk_rq_nr_phys_segments(req)) {
ret = nvme_map_data(dev, req, &cmnd);
-
- if (ret != BLK_MQ_RQ_QUEUE_OK)
- goto out_cleanup_iod;
+ if (ret)
+ goto out_cleanup_iod;
+ }
blk_mq_start_request(req);
spin_lock_irq(&nvmeq->q_lock);
if (unlikely(nvmeq->cq_vector < 0)) {
- ret = BLK_MQ_RQ_QUEUE_ERROR;
+ ret = BLK_STS_IOERR;
spin_unlock_irq(&nvmeq->q_lock);
goto out_cleanup_iod;
}
__nvme_submit_cmd(nvmeq, &cmnd);
nvme_process_cq(nvmeq);
spin_unlock_irq(&nvmeq->q_lock);
- return BLK_MQ_RQ_QUEUE_OK;
+ return BLK_STS_OK;
out_cleanup_iod:
nvme_free_iod(dev, req);
out_free_cmd:
@@ -759,65 +729,75 @@ static inline bool nvme_cqe_valid(struct nvme_queue *nvmeq, u16 head,
return (le16_to_cpu(nvmeq->cqes[head].status) & 1) == phase;
}
-static void __nvme_process_cq(struct nvme_queue *nvmeq, unsigned int *tag)
+static inline void nvme_ring_cq_doorbell(struct nvme_queue *nvmeq)
{
- u16 head, phase;
-
- head = nvmeq->cq_head;
- phase = nvmeq->cq_phase;
-
- while (nvme_cqe_valid(nvmeq, head, phase)) {
- struct nvme_completion cqe = nvmeq->cqes[head];
- struct request *req;
-
- if (++head == nvmeq->q_depth) {
- head = 0;
- phase = !phase;
- }
-
- if (tag && *tag == cqe.command_id)
- *tag = -1;
+ u16 head = nvmeq->cq_head;
- if (unlikely(cqe.command_id >= nvmeq->q_depth)) {
- dev_warn(nvmeq->dev->ctrl.device,
- "invalid id %d completed on queue %d\n",
- cqe.command_id, le16_to_cpu(cqe.sq_id));
- continue;
- }
+ if (likely(nvmeq->cq_vector >= 0)) {
+ if (nvme_dbbuf_update_and_check_event(head, nvmeq->dbbuf_cq_db,
+ nvmeq->dbbuf_cq_ei))
+ writel(head, nvmeq->q_db + nvmeq->dev->db_stride);
+ }
+}
- /*
- * AEN requests are special as they don't time out and can
- * survive any kind of queue freeze and often don't respond to
- * aborts. We don't even bother to allocate a struct request
- * for them but rather special case them here.
- */
- if (unlikely(nvmeq->qid == 0 &&
- cqe.command_id >= NVME_AQ_BLKMQ_DEPTH)) {
- nvme_complete_async_event(&nvmeq->dev->ctrl,
- cqe.status, &cqe.result);
- continue;
- }
+static inline void nvme_handle_cqe(struct nvme_queue *nvmeq,
+ struct nvme_completion *cqe)
+{
+ struct request *req;
- req = blk_mq_tag_to_rq(*nvmeq->tags, cqe.command_id);
- nvme_end_request(req, cqe.status, cqe.result);
+ if (unlikely(cqe->command_id >= nvmeq->q_depth)) {
+ dev_warn(nvmeq->dev->ctrl.device,
+ "invalid id %d completed on queue %d\n",
+ cqe->command_id, le16_to_cpu(cqe->sq_id));
+ return;
}
- if (head == nvmeq->cq_head && phase == nvmeq->cq_phase)
+ /*
+ * AEN requests are special as they don't time out and can
+ * survive any kind of queue freeze and often don't respond to
+ * aborts. We don't even bother to allocate a struct request
+ * for them but rather special case them here.
+ */
+ if (unlikely(nvmeq->qid == 0 &&
+ cqe->command_id >= NVME_AQ_BLKMQ_DEPTH)) {
+ nvme_complete_async_event(&nvmeq->dev->ctrl,
+ cqe->status, &cqe->result);
return;
+ }
- if (likely(nvmeq->cq_vector >= 0))
- if (nvme_dbbuf_update_and_check_event(head, nvmeq->dbbuf_cq_db,
- nvmeq->dbbuf_cq_ei))
- writel(head, nvmeq->q_db + nvmeq->dev->db_stride);
- nvmeq->cq_head = head;
- nvmeq->cq_phase = phase;
+ req = blk_mq_tag_to_rq(*nvmeq->tags, cqe->command_id);
+ nvme_end_request(req, cqe->status, cqe->result);
+}
- nvmeq->cqe_seen = 1;
+static inline bool nvme_read_cqe(struct nvme_queue *nvmeq,
+ struct nvme_completion *cqe)
+{
+ if (nvme_cqe_valid(nvmeq, nvmeq->cq_head, nvmeq->cq_phase)) {
+ *cqe = nvmeq->cqes[nvmeq->cq_head];
+
+ if (++nvmeq->cq_head == nvmeq->q_depth) {
+ nvmeq->cq_head = 0;
+ nvmeq->cq_phase = !nvmeq->cq_phase;
+ }
+ return true;
+ }
+ return false;
}
static void nvme_process_cq(struct nvme_queue *nvmeq)
{
- __nvme_process_cq(nvmeq, NULL);
+ struct nvme_completion cqe;
+ int consumed = 0;
+
+ while (nvme_read_cqe(nvmeq, &cqe)) {
+ nvme_handle_cqe(nvmeq, &cqe);
+ consumed++;
+ }
+
+ if (consumed) {
+ nvme_ring_cq_doorbell(nvmeq);
+ nvmeq->cqe_seen = 1;
+ }
}
static irqreturn_t nvme_irq(int irq, void *data)
@@ -842,16 +822,28 @@ static irqreturn_t nvme_irq_check(int irq, void *data)
static int __nvme_poll(struct nvme_queue *nvmeq, unsigned int tag)
{
- if (nvme_cqe_valid(nvmeq, nvmeq->cq_head, nvmeq->cq_phase)) {
- spin_lock_irq(&nvmeq->q_lock);
- __nvme_process_cq(nvmeq, &tag);
- spin_unlock_irq(&nvmeq->q_lock);
+ struct nvme_completion cqe;
+ int found = 0, consumed = 0;
- if (tag == -1)
- return 1;
- }
+ if (!nvme_cqe_valid(nvmeq, nvmeq->cq_head, nvmeq->cq_phase))
+ return 0;
- return 0;
+ spin_lock_irq(&nvmeq->q_lock);
+ while (nvme_read_cqe(nvmeq, &cqe)) {
+ nvme_handle_cqe(nvmeq, &cqe);
+ consumed++;
+
+ if (tag == cqe.command_id) {
+ found = 1;
+ break;
+ }
+ }
+
+ if (consumed)
+ nvme_ring_cq_doorbell(nvmeq);
+ spin_unlock_irq(&nvmeq->q_lock);
+
+ return found;
}
static int nvme_poll(struct blk_mq_hw_ctx *hctx, unsigned int tag)
@@ -939,7 +931,7 @@ static int adapter_delete_sq(struct nvme_dev *dev, u16 sqid)
return adapter_delete_queue(dev, nvme_admin_delete_sq, sqid);
}
-static void abort_endio(struct request *req, int error)
+static void abort_endio(struct request *req, blk_status_t error)
{
struct nvme_iod *iod = blk_mq_rq_to_pdu(req);
struct nvme_queue *nvmeq = iod->nvmeq;
@@ -950,6 +942,51 @@ static void abort_endio(struct request *req, int error)
blk_mq_free_request(req);
}
+static bool nvme_should_reset(struct nvme_dev *dev, u32 csts)
+{
+
+ /* If true, indicates loss of adapter communication, possibly by a
+ * NVMe Subsystem reset.
+ */
+ bool nssro = dev->subsystem && (csts & NVME_CSTS_NSSRO);
+
+ /* If there is a reset ongoing, we shouldn't reset again. */
+ if (dev->ctrl.state == NVME_CTRL_RESETTING)
+ return false;
+
+ /* We shouldn't reset unless the controller is on fatal error state
+ * _or_ if we lost the communication with it.
+ */
+ if (!(csts & NVME_CSTS_CFS) && !nssro)
+ return false;
+
+ /* If PCI error recovery process is happening, we cannot reset or
+ * the recovery mechanism will surely fail.
+ */
+ if (pci_channel_offline(to_pci_dev(dev->dev)))
+ return false;
+
+ return true;
+}
+
+static void nvme_warn_reset(struct nvme_dev *dev, u32 csts)
+{
+ /* Read a config register to help see what died. */
+ u16 pci_status;
+ int result;
+
+ result = pci_read_config_word(to_pci_dev(dev->dev), PCI_STATUS,
+ &pci_status);
+ if (result == PCIBIOS_SUCCESSFUL)
+ dev_warn(dev->ctrl.device,
+ "controller is down; will reset: CSTS=0x%x, PCI_STATUS=0x%hx\n",
+ csts, pci_status);
+ else
+ dev_warn(dev->ctrl.device,
+ "controller is down; will reset: CSTS=0x%x, PCI_STATUS read failed (%d)\n",
+ csts, result);
+}
+
static enum blk_eh_timer_return nvme_timeout(struct request *req, bool reserved)
{
struct nvme_iod *iod = blk_mq_rq_to_pdu(req);
@@ -957,6 +994,17 @@ static enum blk_eh_timer_return nvme_timeout(struct request *req, bool reserved)
struct nvme_dev *dev = nvmeq->dev;
struct request *abort_req;
struct nvme_command cmd;
+ u32 csts = readl(dev->bar + NVME_REG_CSTS);
+
+ /*
+ * Reset immediately if the controller is failed
+ */
+ if (nvme_should_reset(dev, csts)) {
+ nvme_warn_reset(dev, csts);
+ nvme_dev_disable(dev, false);
+ nvme_reset_ctrl(&dev->ctrl);
+ return BLK_EH_HANDLED;
+ }
/*
* Did we miss an interrupt?
@@ -993,7 +1041,7 @@ static enum blk_eh_timer_return nvme_timeout(struct request *req, bool reserved)
"I/O %d QID %d timeout, reset controller\n",
req->tag, nvmeq->qid);
nvme_dev_disable(dev, false);
- nvme_reset(dev);
+ nvme_reset_ctrl(&dev->ctrl);
/*
* Mark the request as handled, since the inline shutdown
@@ -1247,7 +1295,7 @@ static const struct blk_mq_ops nvme_mq_admin_ops = {
.complete = nvme_pci_complete_rq,
.init_hctx = nvme_admin_init_hctx,
.exit_hctx = nvme_admin_exit_hctx,
- .init_request = nvme_admin_init_request,
+ .init_request = nvme_init_request,
.timeout = nvme_timeout,
};
@@ -1311,6 +1359,32 @@ static int nvme_alloc_admin_tags(struct nvme_dev *dev)
return 0;
}
+static unsigned long db_bar_size(struct nvme_dev *dev, unsigned nr_io_queues)
+{
+ return NVME_REG_DBS + ((nr_io_queues + 1) * 8 * dev->db_stride);
+}
+
+static int nvme_remap_bar(struct nvme_dev *dev, unsigned long size)
+{
+ struct pci_dev *pdev = to_pci_dev(dev->dev);
+
+ if (size <= dev->bar_mapped_size)
+ return 0;
+ if (size > pci_resource_len(pdev, 0))
+ return -ENOMEM;
+ if (dev->bar)
+ iounmap(dev->bar);
+ dev->bar = ioremap(pci_resource_start(pdev, 0), size);
+ if (!dev->bar) {
+ dev->bar_mapped_size = 0;
+ return -ENOMEM;
+ }
+ dev->bar_mapped_size = size;
+ dev->dbs = dev->bar + NVME_REG_DBS;
+
+ return 0;
+}
+
static int nvme_configure_admin_queue(struct nvme_dev *dev)
{
int result;
@@ -1318,6 +1392,10 @@ static int nvme_configure_admin_queue(struct nvme_dev *dev)
u64 cap = lo_hi_readq(dev->bar + NVME_REG_CAP);
struct nvme_queue *nvmeq;
+ result = nvme_remap_bar(dev, db_bar_size(dev, 0));
+ if (result < 0)
+ return result;
+
dev->subsystem = readl(dev->bar + NVME_REG_VS) >= NVME_VS(1, 1, 0) ?
NVME_CAP_NSSRC(cap) : 0;
@@ -1358,66 +1436,6 @@ static int nvme_configure_admin_queue(struct nvme_dev *dev)
return result;
}
-static bool nvme_should_reset(struct nvme_dev *dev, u32 csts)
-{
-
- /* If true, indicates loss of adapter communication, possibly by a
- * NVMe Subsystem reset.
- */
- bool nssro = dev->subsystem && (csts & NVME_CSTS_NSSRO);
-
- /* If there is a reset ongoing, we shouldn't reset again. */
- if (work_busy(&dev->reset_work))
- return false;
-
- /* We shouldn't reset unless the controller is on fatal error state
- * _or_ if we lost the communication with it.
- */
- if (!(csts & NVME_CSTS_CFS) && !nssro)
- return false;
-
- /* If PCI error recovery process is happening, we cannot reset or
- * the recovery mechanism will surely fail.
- */
- if (pci_channel_offline(to_pci_dev(dev->dev)))
- return false;
-
- return true;
-}
-
-static void nvme_warn_reset(struct nvme_dev *dev, u32 csts)
-{
- /* Read a config register to help see what died. */
- u16 pci_status;
- int result;
-
- result = pci_read_config_word(to_pci_dev(dev->dev), PCI_STATUS,
- &pci_status);
- if (result == PCIBIOS_SUCCESSFUL)
- dev_warn(dev->dev,
- "controller is down; will reset: CSTS=0x%x, PCI_STATUS=0x%hx\n",
- csts, pci_status);
- else
- dev_warn(dev->dev,
- "controller is down; will reset: CSTS=0x%x, PCI_STATUS read failed (%d)\n",
- csts, result);
-}
-
-static void nvme_watchdog_timer(unsigned long data)
-{
- struct nvme_dev *dev = (struct nvme_dev *)data;
- u32 csts = readl(dev->bar + NVME_REG_CSTS);
-
- /* Skip controllers under certain specific conditions. */
- if (nvme_should_reset(dev, csts)) {
- if (!nvme_reset(dev))
- nvme_warn_reset(dev, csts);
- return;
- }
-
- mod_timer(&dev->watchdog_timer, round_jiffies(jiffies + HZ));
-}
-
static int nvme_create_io_queues(struct nvme_dev *dev)
{
unsigned i, max;
@@ -1514,18 +1532,170 @@ static inline void nvme_release_cmb(struct nvme_dev *dev)
}
}
-static size_t db_bar_size(struct nvme_dev *dev, unsigned nr_io_queues)
+static int nvme_set_host_mem(struct nvme_dev *dev, u32 bits)
{
- return 4096 + ((nr_io_queues + 1) * 8 * dev->db_stride);
+ size_t len = dev->nr_host_mem_descs * sizeof(*dev->host_mem_descs);
+ struct nvme_command c;
+ u64 dma_addr;
+ int ret;
+
+ dma_addr = dma_map_single(dev->dev, dev->host_mem_descs, len,
+ DMA_TO_DEVICE);
+ if (dma_mapping_error(dev->dev, dma_addr))
+ return -ENOMEM;
+
+ memset(&c, 0, sizeof(c));
+ c.features.opcode = nvme_admin_set_features;
+ c.features.fid = cpu_to_le32(NVME_FEAT_HOST_MEM_BUF);
+ c.features.dword11 = cpu_to_le32(bits);
+ c.features.dword12 = cpu_to_le32(dev->host_mem_size >>
+ ilog2(dev->ctrl.page_size));
+ c.features.dword13 = cpu_to_le32(lower_32_bits(dma_addr));
+ c.features.dword14 = cpu_to_le32(upper_32_bits(dma_addr));
+ c.features.dword15 = cpu_to_le32(dev->nr_host_mem_descs);
+
+ ret = nvme_submit_sync_cmd(dev->ctrl.admin_q, &c, NULL, 0);
+ if (ret) {
+ dev_warn(dev->ctrl.device,
+ "failed to set host mem (err %d, flags %#x).\n",
+ ret, bits);
+ }
+ dma_unmap_single(dev->dev, dma_addr, len, DMA_TO_DEVICE);
+ return ret;
+}
+
+static void nvme_free_host_mem(struct nvme_dev *dev)
+{
+ int i;
+
+ for (i = 0; i < dev->nr_host_mem_descs; i++) {
+ struct nvme_host_mem_buf_desc *desc = &dev->host_mem_descs[i];
+ size_t size = le32_to_cpu(desc->size) * dev->ctrl.page_size;
+
+ dma_free_coherent(dev->dev, size, dev->host_mem_desc_bufs[i],
+ le64_to_cpu(desc->addr));
+ }
+
+ kfree(dev->host_mem_desc_bufs);
+ dev->host_mem_desc_bufs = NULL;
+ kfree(dev->host_mem_descs);
+ dev->host_mem_descs = NULL;
+}
+
+static int nvme_alloc_host_mem(struct nvme_dev *dev, u64 min, u64 preferred)
+{
+ struct nvme_host_mem_buf_desc *descs;
+ u32 chunk_size, max_entries, i = 0;
+ void **bufs;
+ u64 size, tmp;
+
+ /* start big and work our way down */
+ chunk_size = min(preferred, (u64)PAGE_SIZE << MAX_ORDER);
+retry:
+ tmp = (preferred + chunk_size - 1);
+ do_div(tmp, chunk_size);
+ max_entries = tmp;
+ descs = kcalloc(max_entries, sizeof(*descs), GFP_KERNEL);
+ if (!descs)
+ goto out;
+
+ bufs = kcalloc(max_entries, sizeof(*bufs), GFP_KERNEL);
+ if (!bufs)
+ goto out_free_descs;
+
+ for (size = 0; size < preferred; size += chunk_size) {
+ u32 len = min_t(u64, chunk_size, preferred - size);
+ dma_addr_t dma_addr;
+
+ bufs[i] = dma_alloc_attrs(dev->dev, len, &dma_addr, GFP_KERNEL,
+ DMA_ATTR_NO_KERNEL_MAPPING | DMA_ATTR_NO_WARN);
+ if (!bufs[i])
+ break;
+
+ descs[i].addr = cpu_to_le64(dma_addr);
+ descs[i].size = cpu_to_le32(len / dev->ctrl.page_size);
+ i++;
+ }
+
+ if (!size || (min && size < min)) {
+ dev_warn(dev->ctrl.device,
+ "failed to allocate host memory buffer.\n");
+ goto out_free_bufs;
+ }
+
+ dev_info(dev->ctrl.device,
+ "allocated %lld MiB host memory buffer.\n",
+ size >> ilog2(SZ_1M));
+ dev->nr_host_mem_descs = i;
+ dev->host_mem_size = size;
+ dev->host_mem_descs = descs;
+ dev->host_mem_desc_bufs = bufs;
+ return 0;
+
+out_free_bufs:
+ while (--i >= 0) {
+ size_t size = le32_to_cpu(descs[i].size) * dev->ctrl.page_size;
+
+ dma_free_coherent(dev->dev, size, bufs[i],
+ le64_to_cpu(descs[i].addr));
+ }
+
+ kfree(bufs);
+out_free_descs:
+ kfree(descs);
+out:
+ /* try a smaller chunk size if we failed early */
+ if (chunk_size >= PAGE_SIZE * 2 && (i == 0 || size < min)) {
+ chunk_size /= 2;
+ goto retry;
+ }
+ dev->host_mem_descs = NULL;
+ return -ENOMEM;
+}
+
+static void nvme_setup_host_mem(struct nvme_dev *dev)
+{
+ u64 max = (u64)max_host_mem_size_mb * SZ_1M;
+ u64 preferred = (u64)dev->ctrl.hmpre * 4096;
+ u64 min = (u64)dev->ctrl.hmmin * 4096;
+ u32 enable_bits = NVME_HOST_MEM_ENABLE;
+
+ preferred = min(preferred, max);
+ if (min > max) {
+ dev_warn(dev->ctrl.device,
+ "min host memory (%lld MiB) above limit (%d MiB).\n",
+ min >> ilog2(SZ_1M), max_host_mem_size_mb);
+ nvme_free_host_mem(dev);
+ return;
+ }
+
+ /*
+ * If we already have a buffer allocated check if we can reuse it.
+ */
+ if (dev->host_mem_descs) {
+ if (dev->host_mem_size >= min)
+ enable_bits |= NVME_HOST_MEM_RETURN;
+ else
+ nvme_free_host_mem(dev);
+ }
+
+ if (!dev->host_mem_descs) {
+ if (nvme_alloc_host_mem(dev, min, preferred))
+ return;
+ }
+
+ if (nvme_set_host_mem(dev, enable_bits))
+ nvme_free_host_mem(dev);
}
static int nvme_setup_io_queues(struct nvme_dev *dev)
{
struct nvme_queue *adminq = dev->queues[0];
struct pci_dev *pdev = to_pci_dev(dev->dev);
- int result, nr_io_queues, size;
+ int result, nr_io_queues;
+ unsigned long size;
- nr_io_queues = num_online_cpus();
+ nr_io_queues = num_present_cpus();
result = nvme_set_queue_count(&dev->ctrl, &nr_io_queues);
if (result < 0)
return result;
@@ -1542,20 +1712,15 @@ static int nvme_setup_io_queues(struct nvme_dev *dev)
nvme_release_cmb(dev);
}
- size = db_bar_size(dev, nr_io_queues);
- if (size > 8192) {
- iounmap(dev->bar);
- do {
- dev->bar = ioremap(pci_resource_start(pdev, 0), size);
- if (dev->bar)
- break;
- if (!--nr_io_queues)
- return -ENOMEM;
- size = db_bar_size(dev, nr_io_queues);
- } while (1);
- dev->dbs = dev->bar + 4096;
- adminq->q_db = dev->dbs;
- }
+ do {
+ size = db_bar_size(dev, nr_io_queues);
+ result = nvme_remap_bar(dev, size);
+ if (!result)
+ break;
+ if (!--nr_io_queues)
+ return -ENOMEM;
+ } while (1);
+ adminq->q_db = dev->dbs;
/* Deregister the admin queue's interrupt */
pci_free_irq(pdev, 0, adminq);
@@ -1586,7 +1751,7 @@ static int nvme_setup_io_queues(struct nvme_dev *dev)
return nvme_create_io_queues(dev);
}
-static void nvme_del_queue_end(struct request *req, int error)
+static void nvme_del_queue_end(struct request *req, blk_status_t error)
{
struct nvme_queue *nvmeq = req->end_io_data;
@@ -1594,7 +1759,7 @@ static void nvme_del_queue_end(struct request *req, int error)
complete(&nvmeq->dev->ioq_wait);
}
-static void nvme_del_cq_end(struct request *req, int error)
+static void nvme_del_cq_end(struct request *req, blk_status_t error)
{
struct nvme_queue *nvmeq = req->end_io_data;
@@ -1740,8 +1905,8 @@ static int nvme_pci_enable(struct nvme_dev *dev)
*/
if (pdev->vendor == PCI_VENDOR_ID_APPLE && pdev->device == 0x2001) {
dev->q_depth = 2;
- dev_warn(dev->dev, "detected Apple NVMe controller, set "
- "queue depth=%u to work around controller resets\n",
+ dev_warn(dev->ctrl.device, "detected Apple NVMe controller, "
+ "set queue depth=%u to work around controller resets\n",
dev->q_depth);
}
@@ -1759,7 +1924,7 @@ static int nvme_pci_enable(struct nvme_dev *dev)
if (dev->cmbsz) {
if (sysfs_add_file_to_group(&dev->ctrl.device->kobj,
&dev_attr_cmb.attr, NULL))
- dev_warn(dev->dev,
+ dev_warn(dev->ctrl.device,
"failed to add sysfs attribute for CMB\n");
}
}
@@ -1799,13 +1964,12 @@ static void nvme_dev_disable(struct nvme_dev *dev, bool shutdown)
bool dead = true;
struct pci_dev *pdev = to_pci_dev(dev->dev);
- del_timer_sync(&dev->watchdog_timer);
-
mutex_lock(&dev->shutdown_lock);
if (pci_is_enabled(pdev)) {
u32 csts = readl(dev->bar + NVME_REG_CSTS);
- if (dev->ctrl.state == NVME_CTRL_LIVE)
+ if (dev->ctrl.state == NVME_CTRL_LIVE ||
+ dev->ctrl.state == NVME_CTRL_RESETTING)
nvme_start_freeze(&dev->ctrl);
dead = !!((csts & NVME_CSTS_CFS) || !(csts & NVME_CSTS_RDY) ||
pdev->error_state != pci_channel_io_normal);
@@ -1815,8 +1979,20 @@ static void nvme_dev_disable(struct nvme_dev *dev, bool shutdown)
* Give the controller a chance to complete all entered requests if
* doing a safe shutdown.
*/
- if (!dead && shutdown)
- nvme_wait_freeze_timeout(&dev->ctrl, NVME_IO_TIMEOUT);
+ if (!dead) {
+ if (shutdown)
+ nvme_wait_freeze_timeout(&dev->ctrl, NVME_IO_TIMEOUT);
+
+ /*
+ * If the controller is still alive tell it to stop using the
+ * host memory buffer. In theory the shutdown / reset should
+ * make sure that it doesn't access the host memoery anymore,
+ * but I'd rather be safe than sorry..
+ */
+ if (dev->host_mem_descs)
+ nvme_set_host_mem(dev, 0);
+
+ }
nvme_stop_queues(&dev->ctrl);
queues = dev->online_queues - 1;
@@ -1899,11 +2075,12 @@ static void nvme_remove_dead_ctrl(struct nvme_dev *dev, int status)
static void nvme_reset_work(struct work_struct *work)
{
- struct nvme_dev *dev = container_of(work, struct nvme_dev, reset_work);
+ struct nvme_dev *dev =
+ container_of(work, struct nvme_dev, ctrl.reset_work);
bool was_suspend = !!(dev->ctrl.ctrl_config & NVME_CC_SHN_NORMAL);
int result = -ENODEV;
- if (WARN_ON(dev->ctrl.state == NVME_CTRL_RESETTING))
+ if (WARN_ON(dev->ctrl.state != NVME_CTRL_RESETTING))
goto out;
/*
@@ -1913,9 +2090,6 @@ static void nvme_reset_work(struct work_struct *work)
if (dev->ctrl.ctrl_config & NVME_CC_ENABLE)
nvme_dev_disable(dev, false);
- if (!nvme_change_ctrl_state(&dev->ctrl, NVME_CTRL_RESETTING))
- goto out;
-
result = nvme_pci_enable(dev);
if (result)
goto out;
@@ -1951,6 +2125,9 @@ static void nvme_reset_work(struct work_struct *work)
"unable to allocate dma for dbbuf\n");
}
+ if (dev->ctrl.hmpre)
+ nvme_setup_host_mem(dev);
+
result = nvme_setup_io_queues(dev);
if (result)
goto out;
@@ -1964,8 +2141,6 @@ static void nvme_reset_work(struct work_struct *work)
if (dev->online_queues > 1)
nvme_queue_async_events(&dev->ctrl);
- mod_timer(&dev->watchdog_timer, round_jiffies(jiffies + HZ));
-
/*
* Keep the controller around but remove all namespaces if we don't have
* any working I/O queue.
@@ -2005,17 +2180,6 @@ static void nvme_remove_dead_ctrl_work(struct work_struct *work)
nvme_put_ctrl(&dev->ctrl);
}
-static int nvme_reset(struct nvme_dev *dev)
-{
- if (!dev->ctrl.admin_q || blk_queue_dying(dev->ctrl.admin_q))
- return -ENODEV;
- if (work_busy(&dev->reset_work))
- return -ENODEV;
- if (!queue_work(nvme_workq, &dev->reset_work))
- return -EBUSY;
- return 0;
-}
-
static int nvme_pci_reg_read32(struct nvme_ctrl *ctrl, u32 off, u32 *val)
{
*val = readl(to_nvme_dev(ctrl)->bar + off);
@@ -2034,23 +2198,13 @@ static int nvme_pci_reg_read64(struct nvme_ctrl *ctrl, u32 off, u64 *val)
return 0;
}
-static int nvme_pci_reset_ctrl(struct nvme_ctrl *ctrl)
-{
- struct nvme_dev *dev = to_nvme_dev(ctrl);
- int ret = nvme_reset(dev);
-
- if (!ret)
- flush_work(&dev->reset_work);
- return ret;
-}
-
static const struct nvme_ctrl_ops nvme_pci_ctrl_ops = {
.name = "pcie",
.module = THIS_MODULE,
+ .flags = NVME_F_METADATA_SUPPORTED,
.reg_read32 = nvme_pci_reg_read32,
.reg_write32 = nvme_pci_reg_write32,
.reg_read64 = nvme_pci_reg_read64,
- .reset_ctrl = nvme_pci_reset_ctrl,
.free_ctrl = nvme_pci_free_ctrl,
.submit_async_event = nvme_pci_submit_async_event,
};
@@ -2062,8 +2216,7 @@ static int nvme_dev_map(struct nvme_dev *dev)
if (pci_request_mem_regions(pdev, "nvme"))
return -ENODEV;
- dev->bar = ioremap(pci_resource_start(pdev, 0), 8192);
- if (!dev->bar)
+ if (nvme_remap_bar(dev, NVME_REG_DBS + 4096))
goto release;
return 0;
@@ -2117,10 +2270,8 @@ static int nvme_probe(struct pci_dev *pdev, const struct pci_device_id *id)
if (result)
goto free;
- INIT_WORK(&dev->reset_work, nvme_reset_work);
+ INIT_WORK(&dev->ctrl.reset_work, nvme_reset_work);
INIT_WORK(&dev->remove_work, nvme_remove_dead_ctrl_work);
- setup_timer(&dev->watchdog_timer, nvme_watchdog_timer,
- (unsigned long)dev);
mutex_init(&dev->shutdown_lock);
init_completion(&dev->ioq_wait);
@@ -2135,9 +2286,10 @@ static int nvme_probe(struct pci_dev *pdev, const struct pci_device_id *id)
if (result)
goto release_pools;
+ nvme_change_ctrl_state(&dev->ctrl, NVME_CTRL_RESETTING);
dev_info(dev->ctrl.device, "pci function %s\n", dev_name(&pdev->dev));
- queue_work(nvme_workq, &dev->reset_work);
+ queue_work(nvme_wq, &dev->ctrl.reset_work);
return 0;
release_pools:
@@ -2158,7 +2310,7 @@ static void nvme_reset_notify(struct pci_dev *pdev, bool prepare)
if (prepare)
nvme_dev_disable(dev, false);
else
- nvme_reset(dev);
+ nvme_reset_ctrl(&dev->ctrl);
}
static void nvme_shutdown(struct pci_dev *pdev)
@@ -2178,6 +2330,7 @@ static void nvme_remove(struct pci_dev *pdev)
nvme_change_ctrl_state(&dev->ctrl, NVME_CTRL_DELETING);
+ cancel_work_sync(&dev->ctrl.reset_work);
pci_set_drvdata(pdev, NULL);
if (!pci_device_is_present(pdev)) {
@@ -2185,9 +2338,10 @@ static void nvme_remove(struct pci_dev *pdev)
nvme_dev_disable(dev, false);
}
- flush_work(&dev->reset_work);
+ flush_work(&dev->ctrl.reset_work);
nvme_uninit_ctrl(&dev->ctrl);
nvme_dev_disable(dev, true);
+ nvme_free_host_mem(dev);
nvme_dev_remove_admin(dev);
nvme_free_queues(dev, 0);
nvme_release_prp_pools(dev);
@@ -2228,7 +2382,7 @@ static int nvme_resume(struct device *dev)
struct pci_dev *pdev = to_pci_dev(dev);
struct nvme_dev *ndev = pci_get_drvdata(pdev);
- nvme_reset(ndev);
+ nvme_reset_ctrl(&ndev->ctrl);
return 0;
}
#endif
@@ -2267,7 +2421,7 @@ static pci_ers_result_t nvme_slot_reset(struct pci_dev *pdev)
dev_info(dev->ctrl.device, "restart after slot reset\n");
pci_restore_state(pdev);
- nvme_reset(dev);
+ nvme_reset_ctrl(&dev->ctrl);
return PCI_ERS_RESULT_RECOVERED;
}
@@ -2293,6 +2447,8 @@ static const struct pci_device_id nvme_id_table[] = {
{ PCI_VDEVICE(INTEL, 0x0a54),
.driver_data = NVME_QUIRK_STRIPE_SIZE |
NVME_QUIRK_DEALLOCATE_ZEROES, },
+ { PCI_VDEVICE(INTEL, 0xf1a5), /* Intel 600P/P3100 */
+ .driver_data = NVME_QUIRK_NO_DEEPEST_PS },
{ PCI_VDEVICE(INTEL, 0x5845), /* Qemu emulated controller */
.driver_data = NVME_QUIRK_IDENTIFY_CNS, },
{ PCI_DEVICE(0x1c58, 0x0003), /* HGST adapter */
@@ -2321,22 +2477,12 @@ static struct pci_driver nvme_driver = {
static int __init nvme_init(void)
{
- int result;
-
- nvme_workq = alloc_workqueue("nvme", WQ_UNBOUND | WQ_MEM_RECLAIM, 0);
- if (!nvme_workq)
- return -ENOMEM;
-
- result = pci_register_driver(&nvme_driver);
- if (result)
- destroy_workqueue(nvme_workq);
- return result;
+ return pci_register_driver(&nvme_driver);
}
static void __exit nvme_exit(void)
{
pci_unregister_driver(&nvme_driver);
- destroy_workqueue(nvme_workq);
_nvme_check_size();
}
diff --git a/drivers/nvme/host/rdma.c b/drivers/nvme/host/rdma.c
index dd1c6deef82f..6d4119dfbdaa 100644
--- a/drivers/nvme/host/rdma.c
+++ b/drivers/nvme/host/rdma.c
@@ -48,7 +48,7 @@
*/
#define NVME_RDMA_NR_AEN_COMMANDS 1
#define NVME_RDMA_AQ_BLKMQ_DEPTH \
- (NVMF_AQ_DEPTH - NVME_RDMA_NR_AEN_COMMANDS)
+ (NVME_AQ_DEPTH - NVME_RDMA_NR_AEN_COMMANDS)
struct nvme_rdma_device {
struct ib_device *dev;
@@ -80,10 +80,8 @@ struct nvme_rdma_request {
};
enum nvme_rdma_queue_flags {
- NVME_RDMA_Q_CONNECTED = (1 << 0),
- NVME_RDMA_IB_QUEUE_ALLOCATED = (1 << 1),
- NVME_RDMA_Q_DELETING = (1 << 2),
- NVME_RDMA_Q_LIVE = (1 << 3),
+ NVME_RDMA_Q_LIVE = 0,
+ NVME_RDMA_Q_DELETING = 1,
};
struct nvme_rdma_queue {
@@ -103,9 +101,6 @@ struct nvme_rdma_queue {
};
struct nvme_rdma_ctrl {
- /* read and written in the hot path */
- spinlock_t lock;
-
/* read only in the hot path */
struct nvme_rdma_queue *queues;
u32 queue_count;
@@ -113,7 +108,6 @@ struct nvme_rdma_ctrl {
/* other member variables */
struct blk_mq_tag_set tag_set;
struct work_struct delete_work;
- struct work_struct reset_work;
struct work_struct err_work;
struct nvme_rdma_qe async_event_sqe;
@@ -145,8 +139,6 @@ static DEFINE_MUTEX(device_list_mutex);
static LIST_HEAD(nvme_rdma_ctrl_list);
static DEFINE_MUTEX(nvme_rdma_ctrl_mutex);
-static struct workqueue_struct *nvme_rdma_wq;
-
/*
* Disabling this option makes small I/O goes faster, but is fundamentally
* unsafe. With it turned off we will have to register a global rkey that
@@ -301,10 +293,12 @@ out:
return ret;
}
-static void __nvme_rdma_exit_request(struct nvme_rdma_ctrl *ctrl,
- struct request *rq, unsigned int queue_idx)
+static void nvme_rdma_exit_request(struct blk_mq_tag_set *set,
+ struct request *rq, unsigned int hctx_idx)
{
+ struct nvme_rdma_ctrl *ctrl = set->driver_data;
struct nvme_rdma_request *req = blk_mq_rq_to_pdu(rq);
+ int queue_idx = (set == &ctrl->tag_set) ? hctx_idx + 1 : 0;
struct nvme_rdma_queue *queue = &ctrl->queues[queue_idx];
struct nvme_rdma_device *dev = queue->device;
@@ -315,22 +309,13 @@ static void __nvme_rdma_exit_request(struct nvme_rdma_ctrl *ctrl,
DMA_TO_DEVICE);
}
-static void nvme_rdma_exit_request(struct blk_mq_tag_set *set,
- struct request *rq, unsigned int hctx_idx)
-{
- return __nvme_rdma_exit_request(set->driver_data, rq, hctx_idx + 1);
-}
-
-static void nvme_rdma_exit_admin_request(struct blk_mq_tag_set *set,
- struct request *rq, unsigned int hctx_idx)
-{
- return __nvme_rdma_exit_request(set->driver_data, rq, 0);
-}
-
-static int __nvme_rdma_init_request(struct nvme_rdma_ctrl *ctrl,
- struct request *rq, unsigned int queue_idx)
+static int nvme_rdma_init_request(struct blk_mq_tag_set *set,
+ struct request *rq, unsigned int hctx_idx,
+ unsigned int numa_node)
{
+ struct nvme_rdma_ctrl *ctrl = set->driver_data;
struct nvme_rdma_request *req = blk_mq_rq_to_pdu(rq);
+ int queue_idx = (set == &ctrl->tag_set) ? hctx_idx + 1 : 0;
struct nvme_rdma_queue *queue = &ctrl->queues[queue_idx];
struct nvme_rdma_device *dev = queue->device;
struct ib_device *ibdev = dev->dev;
@@ -358,20 +343,6 @@ out_free_qe:
return -ENOMEM;
}
-static int nvme_rdma_init_request(struct blk_mq_tag_set *set,
- struct request *rq, unsigned int hctx_idx,
- unsigned int numa_node)
-{
- return __nvme_rdma_init_request(set->driver_data, rq, hctx_idx + 1);
-}
-
-static int nvme_rdma_init_admin_request(struct blk_mq_tag_set *set,
- struct request *rq, unsigned int hctx_idx,
- unsigned int numa_node)
-{
- return __nvme_rdma_init_request(set->driver_data, rq, 0);
-}
-
static int nvme_rdma_init_hctx(struct blk_mq_hw_ctx *hctx, void *data,
unsigned int hctx_idx)
{
@@ -469,9 +440,6 @@ static void nvme_rdma_destroy_queue_ib(struct nvme_rdma_queue *queue)
struct nvme_rdma_device *dev;
struct ib_device *ibdev;
- if (!test_and_clear_bit(NVME_RDMA_IB_QUEUE_ALLOCATED, &queue->flags))
- return;
-
dev = queue->device;
ibdev = dev->dev;
rdma_destroy_qp(queue->cm_id);
@@ -483,17 +451,21 @@ static void nvme_rdma_destroy_queue_ib(struct nvme_rdma_queue *queue)
nvme_rdma_dev_put(dev);
}
-static int nvme_rdma_create_queue_ib(struct nvme_rdma_queue *queue,
- struct nvme_rdma_device *dev)
+static int nvme_rdma_create_queue_ib(struct nvme_rdma_queue *queue)
{
- struct ib_device *ibdev = dev->dev;
+ struct ib_device *ibdev;
const int send_wr_factor = 3; /* MR, SEND, INV */
const int cq_factor = send_wr_factor + 1; /* + RECV */
int comp_vector, idx = nvme_rdma_queue_idx(queue);
-
int ret;
- queue->device = dev;
+ queue->device = nvme_rdma_find_get_device(queue->cm_id);
+ if (!queue->device) {
+ dev_err(queue->cm_id->device->dev.parent,
+ "no client data found!\n");
+ return -ECONNREFUSED;
+ }
+ ibdev = queue->device->dev;
/*
* The admin queue is barely used once the controller is live, so don't
@@ -506,12 +478,12 @@ static int nvme_rdma_create_queue_ib(struct nvme_rdma_queue *queue,
/* +1 for ib_stop_cq */
- queue->ib_cq = ib_alloc_cq(dev->dev, queue,
- cq_factor * queue->queue_size + 1, comp_vector,
- IB_POLL_SOFTIRQ);
+ queue->ib_cq = ib_alloc_cq(ibdev, queue,
+ cq_factor * queue->queue_size + 1,
+ comp_vector, IB_POLL_SOFTIRQ);
if (IS_ERR(queue->ib_cq)) {
ret = PTR_ERR(queue->ib_cq);
- goto out;
+ goto out_put_dev;
}
ret = nvme_rdma_create_qp(queue, send_wr_factor);
@@ -524,7 +496,6 @@ static int nvme_rdma_create_queue_ib(struct nvme_rdma_queue *queue,
ret = -ENOMEM;
goto out_destroy_qp;
}
- set_bit(NVME_RDMA_IB_QUEUE_ALLOCATED, &queue->flags);
return 0;
@@ -532,7 +503,8 @@ out_destroy_qp:
ib_destroy_qp(queue->qp);
out_destroy_ib_cq:
ib_free_cq(queue->ib_cq);
-out:
+out_put_dev:
+ nvme_rdma_dev_put(queue->device);
return ret;
}
@@ -583,12 +555,10 @@ static int nvme_rdma_init_queue(struct nvme_rdma_ctrl *ctrl,
}
clear_bit(NVME_RDMA_Q_DELETING, &queue->flags);
- set_bit(NVME_RDMA_Q_CONNECTED, &queue->flags);
return 0;
out_destroy_cm_id:
- nvme_rdma_destroy_queue_ib(queue);
rdma_destroy_id(queue->cm_id);
return ret;
}
@@ -718,11 +688,11 @@ static void nvme_rdma_reconnect_or_remove(struct nvme_rdma_ctrl *ctrl)
if (nvmf_should_reconnect(&ctrl->ctrl)) {
dev_info(ctrl->ctrl.device, "Reconnecting in %d seconds...\n",
ctrl->ctrl.opts->reconnect_delay);
- queue_delayed_work(nvme_rdma_wq, &ctrl->reconnect_work,
+ queue_delayed_work(nvme_wq, &ctrl->reconnect_work,
ctrl->ctrl.opts->reconnect_delay * HZ);
} else {
dev_info(ctrl->ctrl.device, "Removing controller...\n");
- queue_work(nvme_rdma_wq, &ctrl->delete_work);
+ queue_work(nvme_wq, &ctrl->delete_work);
}
}
@@ -733,7 +703,7 @@ static void nvme_rdma_reconnect_ctrl_work(struct work_struct *work)
bool changed;
int ret;
- ++ctrl->ctrl.opts->nr_reconnects;
+ ++ctrl->ctrl.nr_reconnects;
if (ctrl->queue_count > 1) {
nvme_rdma_free_io_queues(ctrl);
@@ -749,40 +719,37 @@ static void nvme_rdma_reconnect_ctrl_work(struct work_struct *work)
if (ret)
goto requeue;
- ret = nvme_rdma_init_queue(ctrl, 0, NVMF_AQ_DEPTH);
+ ret = nvme_rdma_init_queue(ctrl, 0, NVME_AQ_DEPTH);
if (ret)
goto requeue;
- blk_mq_start_stopped_hw_queues(ctrl->ctrl.admin_q, true);
-
ret = nvmf_connect_admin_queue(&ctrl->ctrl);
if (ret)
- goto stop_admin_q;
+ goto requeue;
set_bit(NVME_RDMA_Q_LIVE, &ctrl->queues[0].flags);
ret = nvme_enable_ctrl(&ctrl->ctrl, ctrl->cap);
if (ret)
- goto stop_admin_q;
+ goto requeue;
nvme_start_keep_alive(&ctrl->ctrl);
if (ctrl->queue_count > 1) {
ret = nvme_rdma_init_io_queues(ctrl);
if (ret)
- goto stop_admin_q;
+ goto requeue;
ret = nvme_rdma_connect_io_queues(ctrl);
if (ret)
- goto stop_admin_q;
+ goto requeue;
}
changed = nvme_change_ctrl_state(&ctrl->ctrl, NVME_CTRL_LIVE);
WARN_ON_ONCE(!changed);
- ctrl->ctrl.opts->nr_reconnects = 0;
+ ctrl->ctrl.nr_reconnects = 0;
if (ctrl->queue_count > 1) {
- nvme_start_queues(&ctrl->ctrl);
nvme_queue_scan(&ctrl->ctrl);
nvme_queue_async_events(&ctrl->ctrl);
}
@@ -791,11 +758,9 @@ static void nvme_rdma_reconnect_ctrl_work(struct work_struct *work)
return;
-stop_admin_q:
- blk_mq_stop_hw_queues(ctrl->ctrl.admin_q);
requeue:
dev_info(ctrl->ctrl.device, "Failed reconnect attempt %d\n",
- ctrl->ctrl.opts->nr_reconnects);
+ ctrl->ctrl.nr_reconnects);
nvme_rdma_reconnect_or_remove(ctrl);
}
@@ -807,10 +772,8 @@ static void nvme_rdma_error_recovery_work(struct work_struct *work)
nvme_stop_keep_alive(&ctrl->ctrl);
- for (i = 0; i < ctrl->queue_count; i++) {
- clear_bit(NVME_RDMA_Q_CONNECTED, &ctrl->queues[i].flags);
+ for (i = 0; i < ctrl->queue_count; i++)
clear_bit(NVME_RDMA_Q_LIVE, &ctrl->queues[i].flags);
- }
if (ctrl->queue_count > 1)
nvme_stop_queues(&ctrl->ctrl);
@@ -823,6 +786,13 @@ static void nvme_rdma_error_recovery_work(struct work_struct *work)
blk_mq_tagset_busy_iter(&ctrl->admin_tag_set,
nvme_cancel_request, &ctrl->ctrl);
+ /*
+ * queues are not a live anymore, so restart the queues to fail fast
+ * new IO
+ */
+ blk_mq_start_stopped_hw_queues(ctrl->ctrl.admin_q, true);
+ nvme_start_queues(&ctrl->ctrl);
+
nvme_rdma_reconnect_or_remove(ctrl);
}
@@ -831,7 +801,7 @@ static void nvme_rdma_error_recovery(struct nvme_rdma_ctrl *ctrl)
if (!nvme_change_ctrl_state(&ctrl->ctrl, NVME_CTRL_RECONNECTING))
return;
- queue_work(nvme_rdma_wq, &ctrl->err_work);
+ queue_work(nvme_wq, &ctrl->err_work);
}
static void nvme_rdma_wr_error(struct ib_cq *cq, struct ib_wc *wc,
@@ -1038,6 +1008,19 @@ static void nvme_rdma_send_done(struct ib_cq *cq, struct ib_wc *wc)
nvme_rdma_wr_error(cq, wc, "SEND");
}
+static inline int nvme_rdma_queue_sig_limit(struct nvme_rdma_queue *queue)
+{
+ int sig_limit;
+
+ /*
+ * We signal completion every queue depth/2 and also handle the
+ * degenerated case of a device with queue_depth=1, where we
+ * would need to signal every message.
+ */
+ sig_limit = max(queue->queue_size / 2, 1);
+ return (++queue->sig_count % sig_limit) == 0;
+}
+
static int nvme_rdma_post_send(struct nvme_rdma_queue *queue,
struct nvme_rdma_qe *qe, struct ib_sge *sge, u32 num_sge,
struct ib_send_wr *first, bool flush)
@@ -1065,9 +1048,6 @@ static int nvme_rdma_post_send(struct nvme_rdma_queue *queue,
* Would have been way to obvious to handle this in hardware or
* at least the RDMA stack..
*
- * This messy and racy code sniplet is copy and pasted from the iSER
- * initiator, and the magic '32' comes from there as well.
- *
* Always signal the flushes. The magic request used for the flush
* sequencer is not allocated in our driver's tagset and it's
* triggered to be freed by blk_cleanup_queue(). So we need to
@@ -1075,7 +1055,7 @@ static int nvme_rdma_post_send(struct nvme_rdma_queue *queue,
* embedded in request's payload, is not freed when __ib_process_cq()
* calls wr_cqe->done().
*/
- if ((++queue->sig_count % 32) == 0 || flush)
+ if (nvme_rdma_queue_sig_limit(queue) || flush)
wr.send_flags |= IB_SEND_SIGNALED;
if (first)
@@ -1266,21 +1246,11 @@ static int nvme_rdma_conn_rejected(struct nvme_rdma_queue *queue,
static int nvme_rdma_addr_resolved(struct nvme_rdma_queue *queue)
{
- struct nvme_rdma_device *dev;
int ret;
- dev = nvme_rdma_find_get_device(queue->cm_id);
- if (!dev) {
- dev_err(queue->cm_id->device->dev.parent,
- "no client data found!\n");
- return -ECONNREFUSED;
- }
-
- ret = nvme_rdma_create_queue_ib(queue, dev);
- if (ret) {
- nvme_rdma_dev_put(dev);
- goto out;
- }
+ ret = nvme_rdma_create_queue_ib(queue);
+ if (ret)
+ return ret;
ret = rdma_resolve_route(queue->cm_id, NVME_RDMA_CONNECT_TIMEOUT_MS);
if (ret) {
@@ -1294,7 +1264,6 @@ static int nvme_rdma_addr_resolved(struct nvme_rdma_queue *queue)
out_destroy_queue:
nvme_rdma_destroy_queue_ib(queue);
-out:
return ret;
}
@@ -1322,8 +1291,8 @@ static int nvme_rdma_route_resolved(struct nvme_rdma_queue *queue)
* specified by the Fabrics standard.
*/
if (priv.qid == 0) {
- priv.hrqsize = cpu_to_le16(NVMF_AQ_DEPTH);
- priv.hsqsize = cpu_to_le16(NVMF_AQ_DEPTH - 1);
+ priv.hrqsize = cpu_to_le16(NVME_AQ_DEPTH);
+ priv.hsqsize = cpu_to_le16(NVME_AQ_DEPTH - 1);
} else {
/*
* current interpretation of the fabrics spec
@@ -1371,12 +1340,14 @@ static int nvme_rdma_cm_handler(struct rdma_cm_id *cm_id,
complete(&queue->cm_done);
return 0;
case RDMA_CM_EVENT_REJECTED:
+ nvme_rdma_destroy_queue_ib(queue);
cm_error = nvme_rdma_conn_rejected(queue, ev);
break;
- case RDMA_CM_EVENT_ADDR_ERROR:
case RDMA_CM_EVENT_ROUTE_ERROR:
case RDMA_CM_EVENT_CONNECT_ERROR:
case RDMA_CM_EVENT_UNREACHABLE:
+ nvme_rdma_destroy_queue_ib(queue);
+ case RDMA_CM_EVENT_ADDR_ERROR:
dev_dbg(queue->ctrl->ctrl.device,
"CM error event %d\n", ev->event);
cm_error = -ECONNRESET;
@@ -1423,22 +1394,32 @@ nvme_rdma_timeout(struct request *rq, bool reserved)
/*
* We cannot accept any other command until the Connect command has completed.
*/
-static inline bool nvme_rdma_queue_is_ready(struct nvme_rdma_queue *queue,
- struct request *rq)
+static inline blk_status_t
+nvme_rdma_queue_is_ready(struct nvme_rdma_queue *queue, struct request *rq)
{
if (unlikely(!test_bit(NVME_RDMA_Q_LIVE, &queue->flags))) {
struct nvme_command *cmd = nvme_req(rq)->cmd;
if (!blk_rq_is_passthrough(rq) ||
cmd->common.opcode != nvme_fabrics_command ||
- cmd->fabrics.fctype != nvme_fabrics_type_connect)
- return false;
+ cmd->fabrics.fctype != nvme_fabrics_type_connect) {
+ /*
+ * reconnecting state means transport disruption, which
+ * can take a long time and even might fail permanently,
+ * so we can't let incoming I/O be requeued forever.
+ * fail it fast to allow upper layers a chance to
+ * failover.
+ */
+ if (queue->ctrl->ctrl.state == NVME_CTRL_RECONNECTING)
+ return BLK_STS_IOERR;
+ return BLK_STS_RESOURCE; /* try again later */
+ }
}
- return true;
+ return 0;
}
-static int nvme_rdma_queue_rq(struct blk_mq_hw_ctx *hctx,
+static blk_status_t nvme_rdma_queue_rq(struct blk_mq_hw_ctx *hctx,
const struct blk_mq_queue_data *bd)
{
struct nvme_ns *ns = hctx->queue->queuedata;
@@ -1449,27 +1430,29 @@ static int nvme_rdma_queue_rq(struct blk_mq_hw_ctx *hctx,
struct nvme_command *c = sqe->data;
bool flush = false;
struct ib_device *dev;
- int ret;
+ blk_status_t ret;
+ int err;
WARN_ON_ONCE(rq->tag < 0);
- if (!nvme_rdma_queue_is_ready(queue, rq))
- return BLK_MQ_RQ_QUEUE_BUSY;
+ ret = nvme_rdma_queue_is_ready(queue, rq);
+ if (unlikely(ret))
+ return ret;
dev = queue->device->dev;
ib_dma_sync_single_for_cpu(dev, sqe->dma,
sizeof(struct nvme_command), DMA_TO_DEVICE);
ret = nvme_setup_cmd(ns, rq, c);
- if (ret != BLK_MQ_RQ_QUEUE_OK)
+ if (ret)
return ret;
blk_mq_start_request(rq);
- ret = nvme_rdma_map_data(queue, rq, c);
- if (ret < 0) {
+ err = nvme_rdma_map_data(queue, rq, c);
+ if (err < 0) {
dev_err(queue->ctrl->ctrl.device,
- "Failed to map data (%d)\n", ret);
+ "Failed to map data (%d)\n", err);
nvme_cleanup_cmd(rq);
goto err;
}
@@ -1479,17 +1462,18 @@ static int nvme_rdma_queue_rq(struct blk_mq_hw_ctx *hctx,
if (req_op(rq) == REQ_OP_FLUSH)
flush = true;
- ret = nvme_rdma_post_send(queue, sqe, req->sge, req->num_sge,
+ err = nvme_rdma_post_send(queue, sqe, req->sge, req->num_sge,
req->mr->need_inval ? &req->reg_wr.wr : NULL, flush);
- if (ret) {
+ if (err) {
nvme_rdma_unmap_data(queue, rq);
goto err;
}
- return BLK_MQ_RQ_QUEUE_OK;
+ return BLK_STS_OK;
err:
- return (ret == -ENOMEM || ret == -EAGAIN) ?
- BLK_MQ_RQ_QUEUE_BUSY : BLK_MQ_RQ_QUEUE_ERROR;
+ if (err == -ENOMEM || err == -EAGAIN)
+ return BLK_STS_RESOURCE;
+ return BLK_STS_IOERR;
}
static int nvme_rdma_poll(struct blk_mq_hw_ctx *hctx, unsigned int tag)
@@ -1499,7 +1483,6 @@ static int nvme_rdma_poll(struct blk_mq_hw_ctx *hctx, unsigned int tag)
struct ib_wc wc;
int found = 0;
- ib_req_notify_cq(cq, IB_CQ_NEXT_COMP);
while (ib_poll_cq(cq, 1, &wc) > 0) {
struct ib_cqe *cqe = wc.wr_cqe;
@@ -1536,8 +1519,8 @@ static const struct blk_mq_ops nvme_rdma_mq_ops = {
static const struct blk_mq_ops nvme_rdma_admin_mq_ops = {
.queue_rq = nvme_rdma_queue_rq,
.complete = nvme_rdma_complete_rq,
- .init_request = nvme_rdma_init_admin_request,
- .exit_request = nvme_rdma_exit_admin_request,
+ .init_request = nvme_rdma_init_request,
+ .exit_request = nvme_rdma_exit_request,
.reinit_request = nvme_rdma_reinit_request,
.init_hctx = nvme_rdma_init_admin_hctx,
.timeout = nvme_rdma_timeout,
@@ -1547,7 +1530,7 @@ static int nvme_rdma_configure_admin_queue(struct nvme_rdma_ctrl *ctrl)
{
int error;
- error = nvme_rdma_init_queue(ctrl, 0, NVMF_AQ_DEPTH);
+ error = nvme_rdma_init_queue(ctrl, 0, NVME_AQ_DEPTH);
if (error)
return error;
@@ -1648,7 +1631,7 @@ static void nvme_rdma_shutdown_ctrl(struct nvme_rdma_ctrl *ctrl)
nvme_rdma_free_io_queues(ctrl);
}
- if (test_bit(NVME_RDMA_Q_CONNECTED, &ctrl->queues[0].flags))
+ if (test_bit(NVME_RDMA_Q_LIVE, &ctrl->queues[0].flags))
nvme_shutdown_ctrl(&ctrl->ctrl);
blk_mq_stop_hw_queues(ctrl->ctrl.admin_q);
@@ -1685,7 +1668,7 @@ static int __nvme_rdma_del_ctrl(struct nvme_rdma_ctrl *ctrl)
if (!nvme_change_ctrl_state(&ctrl->ctrl, NVME_CTRL_DELETING))
return -EBUSY;
- if (!queue_work(nvme_rdma_wq, &ctrl->delete_work))
+ if (!queue_work(nvme_wq, &ctrl->delete_work))
return -EBUSY;
return 0;
@@ -1719,8 +1702,8 @@ static void nvme_rdma_remove_ctrl_work(struct work_struct *work)
static void nvme_rdma_reset_ctrl_work(struct work_struct *work)
{
- struct nvme_rdma_ctrl *ctrl = container_of(work,
- struct nvme_rdma_ctrl, reset_work);
+ struct nvme_rdma_ctrl *ctrl =
+ container_of(work, struct nvme_rdma_ctrl, ctrl.reset_work);
int ret;
bool changed;
@@ -1761,36 +1744,19 @@ static void nvme_rdma_reset_ctrl_work(struct work_struct *work)
del_dead_ctrl:
/* Deleting this dead controller... */
dev_warn(ctrl->ctrl.device, "Removing after reset failure\n");
- WARN_ON(!queue_work(nvme_rdma_wq, &ctrl->delete_work));
-}
-
-static int nvme_rdma_reset_ctrl(struct nvme_ctrl *nctrl)
-{
- struct nvme_rdma_ctrl *ctrl = to_rdma_ctrl(nctrl);
-
- if (!nvme_change_ctrl_state(&ctrl->ctrl, NVME_CTRL_RESETTING))
- return -EBUSY;
-
- if (!queue_work(nvme_rdma_wq, &ctrl->reset_work))
- return -EBUSY;
-
- flush_work(&ctrl->reset_work);
-
- return 0;
+ WARN_ON(!queue_work(nvme_wq, &ctrl->delete_work));
}
static const struct nvme_ctrl_ops nvme_rdma_ctrl_ops = {
.name = "rdma",
.module = THIS_MODULE,
- .is_fabrics = true,
+ .flags = NVME_F_FABRICS,
.reg_read32 = nvmf_reg_read32,
.reg_read64 = nvmf_reg_read64,
.reg_write32 = nvmf_reg_write32,
- .reset_ctrl = nvme_rdma_reset_ctrl,
.free_ctrl = nvme_rdma_free_ctrl,
.submit_async_event = nvme_rdma_submit_async_event,
.delete_ctrl = nvme_rdma_del_ctrl,
- .get_subsysnqn = nvmf_get_subsysnqn,
.get_address = nvmf_get_address,
};
@@ -1895,8 +1861,7 @@ static struct nvme_ctrl *nvme_rdma_create_ctrl(struct device *dev,
nvme_rdma_reconnect_ctrl_work);
INIT_WORK(&ctrl->err_work, nvme_rdma_error_recovery_work);
INIT_WORK(&ctrl->delete_work, nvme_rdma_del_ctrl_work);
- INIT_WORK(&ctrl->reset_work, nvme_rdma_reset_ctrl_work);
- spin_lock_init(&ctrl->lock);
+ INIT_WORK(&ctrl->ctrl.reset_work, nvme_rdma_reset_ctrl_work);
ctrl->queue_count = opts->nr_io_queues + 1; /* +1 for admin queue */
ctrl->ctrl.sqsize = opts->queue_size - 1;
@@ -1915,12 +1880,14 @@ static struct nvme_ctrl *nvme_rdma_create_ctrl(struct device *dev,
/* sanity check icdoff */
if (ctrl->ctrl.icdoff) {
dev_err(ctrl->ctrl.device, "icdoff is not supported!\n");
+ ret = -EINVAL;
goto out_remove_admin_queue;
}
/* sanity check keyed sgls */
if (!(ctrl->ctrl.sgls & (1 << 20))) {
dev_err(ctrl->ctrl.device, "Mandatory keyed sgls are not support\n");
+ ret = -EINVAL;
goto out_remove_admin_queue;
}
@@ -2009,7 +1976,7 @@ static void nvme_rdma_remove_one(struct ib_device *ib_device, void *client_data)
}
mutex_unlock(&nvme_rdma_ctrl_mutex);
- flush_workqueue(nvme_rdma_wq);
+ flush_workqueue(nvme_wq);
}
static struct ib_client nvme_rdma_ib_client = {
@@ -2022,13 +1989,9 @@ static int __init nvme_rdma_init_module(void)
{
int ret;
- nvme_rdma_wq = create_workqueue("nvme_rdma_wq");
- if (!nvme_rdma_wq)
- return -ENOMEM;
-
ret = ib_register_client(&nvme_rdma_ib_client);
if (ret)
- goto err_destroy_wq;
+ return ret;
ret = nvmf_register_transport(&nvme_rdma_transport);
if (ret)
@@ -2038,8 +2001,6 @@ static int __init nvme_rdma_init_module(void)
err_unreg_client:
ib_unregister_client(&nvme_rdma_ib_client);
-err_destroy_wq:
- destroy_workqueue(nvme_rdma_wq);
return ret;
}
@@ -2047,7 +2008,6 @@ static void __exit nvme_rdma_cleanup_module(void)
{
nvmf_unregister_transport(&nvme_rdma_transport);
ib_unregister_client(&nvme_rdma_ib_client);
- destroy_workqueue(nvme_rdma_wq);
}
module_init(nvme_rdma_init_module);
diff --git a/drivers/nvme/host/scsi.c b/drivers/nvme/host/scsi.c
deleted file mode 100644
index 1f7671e631dd..000000000000
--- a/drivers/nvme/host/scsi.c
+++ /dev/null
@@ -1,2460 +0,0 @@
-/*
- * NVM Express device driver
- * Copyright (c) 2011-2014, Intel Corporation.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- * more details.
- */
-
-/*
- * Refer to the SCSI-NVMe Translation spec for details on how
- * each command is translated.
- */
-
-#include <linux/bio.h>
-#include <linux/bitops.h>
-#include <linux/blkdev.h>
-#include <linux/compat.h>
-#include <linux/delay.h>
-#include <linux/errno.h>
-#include <linux/fs.h>
-#include <linux/genhd.h>
-#include <linux/idr.h>
-#include <linux/init.h>
-#include <linux/interrupt.h>
-#include <linux/io.h>
-#include <linux/kdev_t.h>
-#include <linux/kthread.h>
-#include <linux/kernel.h>
-#include <linux/mm.h>
-#include <linux/module.h>
-#include <linux/moduleparam.h>
-#include <linux/pci.h>
-#include <linux/poison.h>
-#include <linux/sched.h>
-#include <linux/slab.h>
-#include <linux/types.h>
-#include <asm/unaligned.h>
-#include <scsi/sg.h>
-#include <scsi/scsi.h>
-#include <scsi/scsi_request.h>
-
-#include "nvme.h"
-
-static int sg_version_num = 30534; /* 2 digits for each component */
-
-/* VPD Page Codes */
-#define VPD_SUPPORTED_PAGES 0x00
-#define VPD_SERIAL_NUMBER 0x80
-#define VPD_DEVICE_IDENTIFIERS 0x83
-#define VPD_EXTENDED_INQUIRY 0x86
-#define VPD_BLOCK_LIMITS 0xB0
-#define VPD_BLOCK_DEV_CHARACTERISTICS 0xB1
-
-/* format unit paramter list offsets */
-#define FORMAT_UNIT_SHORT_PARM_LIST_LEN 4
-#define FORMAT_UNIT_LONG_PARM_LIST_LEN 8
-#define FORMAT_UNIT_PROT_INT_OFFSET 3
-#define FORMAT_UNIT_PROT_FIELD_USAGE_OFFSET 0
-#define FORMAT_UNIT_PROT_FIELD_USAGE_MASK 0x07
-
-/* Misc. defines */
-#define FIXED_SENSE_DATA 0x70
-#define DESC_FORMAT_SENSE_DATA 0x72
-#define FIXED_SENSE_DATA_ADD_LENGTH 10
-#define LUN_ENTRY_SIZE 8
-#define LUN_DATA_HEADER_SIZE 8
-#define ALL_LUNS_RETURNED 0x02
-#define ALL_WELL_KNOWN_LUNS_RETURNED 0x01
-#define RESTRICTED_LUNS_RETURNED 0x00
-#define DOWNLOAD_SAVE_ACTIVATE 0x05
-#define DOWNLOAD_SAVE_DEFER_ACTIVATE 0x0E
-#define ACTIVATE_DEFERRED_MICROCODE 0x0F
-#define FORMAT_UNIT_IMMED_MASK 0x2
-#define FORMAT_UNIT_IMMED_OFFSET 1
-#define KELVIN_TEMP_FACTOR 273
-#define FIXED_FMT_SENSE_DATA_SIZE 18
-#define DESC_FMT_SENSE_DATA_SIZE 8
-
-/* SCSI/NVMe defines and bit masks */
-#define INQ_STANDARD_INQUIRY_PAGE 0x00
-#define INQ_SUPPORTED_VPD_PAGES_PAGE 0x00
-#define INQ_UNIT_SERIAL_NUMBER_PAGE 0x80
-#define INQ_DEVICE_IDENTIFICATION_PAGE 0x83
-#define INQ_EXTENDED_INQUIRY_DATA_PAGE 0x86
-#define INQ_BDEV_LIMITS_PAGE 0xB0
-#define INQ_BDEV_CHARACTERISTICS_PAGE 0xB1
-#define INQ_SERIAL_NUMBER_LENGTH 0x14
-#define INQ_NUM_SUPPORTED_VPD_PAGES 6
-#define VERSION_SPC_4 0x06
-#define ACA_UNSUPPORTED 0
-#define STANDARD_INQUIRY_LENGTH 36
-#define ADDITIONAL_STD_INQ_LENGTH 31
-#define EXTENDED_INQUIRY_DATA_PAGE_LENGTH 0x3C
-#define RESERVED_FIELD 0
-
-/* Mode Sense/Select defines */
-#define MODE_PAGE_INFO_EXCEP 0x1C
-#define MODE_PAGE_CACHING 0x08
-#define MODE_PAGE_CONTROL 0x0A
-#define MODE_PAGE_POWER_CONDITION 0x1A
-#define MODE_PAGE_RETURN_ALL 0x3F
-#define MODE_PAGE_BLK_DES_LEN 0x08
-#define MODE_PAGE_LLBAA_BLK_DES_LEN 0x10
-#define MODE_PAGE_CACHING_LEN 0x14
-#define MODE_PAGE_CONTROL_LEN 0x0C
-#define MODE_PAGE_POW_CND_LEN 0x28
-#define MODE_PAGE_INF_EXC_LEN 0x0C
-#define MODE_PAGE_ALL_LEN 0x54
-#define MODE_SENSE6_MPH_SIZE 4
-#define MODE_SENSE_PAGE_CONTROL_MASK 0xC0
-#define MODE_SENSE_PAGE_CODE_OFFSET 2
-#define MODE_SENSE_PAGE_CODE_MASK 0x3F
-#define MODE_SENSE_LLBAA_MASK 0x10
-#define MODE_SENSE_LLBAA_SHIFT 4
-#define MODE_SENSE_DBD_MASK 8
-#define MODE_SENSE_DBD_SHIFT 3
-#define MODE_SENSE10_MPH_SIZE 8
-#define MODE_SELECT_CDB_PAGE_FORMAT_MASK 0x10
-#define MODE_SELECT_CDB_SAVE_PAGES_MASK 0x1
-#define MODE_SELECT_6_BD_OFFSET 3
-#define MODE_SELECT_10_BD_OFFSET 6
-#define MODE_SELECT_10_LLBAA_OFFSET 4
-#define MODE_SELECT_10_LLBAA_MASK 1
-#define MODE_SELECT_6_MPH_SIZE 4
-#define MODE_SELECT_10_MPH_SIZE 8
-#define CACHING_MODE_PAGE_WCE_MASK 0x04
-#define MODE_SENSE_BLK_DESC_ENABLED 0
-#define MODE_SENSE_BLK_DESC_COUNT 1
-#define MODE_SELECT_PAGE_CODE_MASK 0x3F
-#define SHORT_DESC_BLOCK 8
-#define LONG_DESC_BLOCK 16
-#define MODE_PAGE_POW_CND_LEN_FIELD 0x26
-#define MODE_PAGE_INF_EXC_LEN_FIELD 0x0A
-#define MODE_PAGE_CACHING_LEN_FIELD 0x12
-#define MODE_PAGE_CONTROL_LEN_FIELD 0x0A
-#define MODE_SENSE_PC_CURRENT_VALUES 0
-
-/* Log Sense defines */
-#define LOG_PAGE_SUPPORTED_LOG_PAGES_PAGE 0x00
-#define LOG_PAGE_SUPPORTED_LOG_PAGES_LENGTH 0x07
-#define LOG_PAGE_INFORMATIONAL_EXCEPTIONS_PAGE 0x2F
-#define LOG_PAGE_TEMPERATURE_PAGE 0x0D
-#define LOG_SENSE_CDB_SP_NOT_ENABLED 0
-#define LOG_SENSE_CDB_PC_MASK 0xC0
-#define LOG_SENSE_CDB_PC_SHIFT 6
-#define LOG_SENSE_CDB_PC_CUMULATIVE_VALUES 1
-#define LOG_SENSE_CDB_PAGE_CODE_MASK 0x3F
-#define REMAINING_INFO_EXCP_PAGE_LENGTH 0x8
-#define LOG_INFO_EXCP_PAGE_LENGTH 0xC
-#define REMAINING_TEMP_PAGE_LENGTH 0xC
-#define LOG_TEMP_PAGE_LENGTH 0x10
-#define LOG_TEMP_UNKNOWN 0xFF
-#define SUPPORTED_LOG_PAGES_PAGE_LENGTH 0x3
-
-/* Read Capacity defines */
-#define READ_CAP_10_RESP_SIZE 8
-#define READ_CAP_16_RESP_SIZE 32
-
-/* NVMe Namespace and Command Defines */
-#define BYTES_TO_DWORDS 4
-#define NVME_MAX_FIRMWARE_SLOT 7
-
-/* Report LUNs defines */
-#define REPORT_LUNS_FIRST_LUN_OFFSET 8
-
-/* SCSI ADDITIONAL SENSE Codes */
-
-#define SCSI_ASC_NO_SENSE 0x00
-#define SCSI_ASC_PERIPHERAL_DEV_WRITE_FAULT 0x03
-#define SCSI_ASC_LUN_NOT_READY 0x04
-#define SCSI_ASC_WARNING 0x0B
-#define SCSI_ASC_LOG_BLOCK_GUARD_CHECK_FAILED 0x10
-#define SCSI_ASC_LOG_BLOCK_APPTAG_CHECK_FAILED 0x10
-#define SCSI_ASC_LOG_BLOCK_REFTAG_CHECK_FAILED 0x10
-#define SCSI_ASC_UNRECOVERED_READ_ERROR 0x11
-#define SCSI_ASC_MISCOMPARE_DURING_VERIFY 0x1D
-#define SCSI_ASC_ACCESS_DENIED_INVALID_LUN_ID 0x20
-#define SCSI_ASC_ILLEGAL_COMMAND 0x20
-#define SCSI_ASC_ILLEGAL_BLOCK 0x21
-#define SCSI_ASC_INVALID_CDB 0x24
-#define SCSI_ASC_INVALID_LUN 0x25
-#define SCSI_ASC_INVALID_PARAMETER 0x26
-#define SCSI_ASC_FORMAT_COMMAND_FAILED 0x31
-#define SCSI_ASC_INTERNAL_TARGET_FAILURE 0x44
-
-/* SCSI ADDITIONAL SENSE Code Qualifiers */
-
-#define SCSI_ASCQ_CAUSE_NOT_REPORTABLE 0x00
-#define SCSI_ASCQ_FORMAT_COMMAND_FAILED 0x01
-#define SCSI_ASCQ_LOG_BLOCK_GUARD_CHECK_FAILED 0x01
-#define SCSI_ASCQ_LOG_BLOCK_APPTAG_CHECK_FAILED 0x02
-#define SCSI_ASCQ_LOG_BLOCK_REFTAG_CHECK_FAILED 0x03
-#define SCSI_ASCQ_FORMAT_IN_PROGRESS 0x04
-#define SCSI_ASCQ_POWER_LOSS_EXPECTED 0x08
-#define SCSI_ASCQ_INVALID_LUN_ID 0x09
-
-/* copied from drivers/usb/gadget/function/storage_common.h */
-static inline u32 get_unaligned_be24(u8 *buf)
-{
- return 0xffffff & (u32) get_unaligned_be32(buf - 1);
-}
-
-/* Struct to gather data that needs to be extracted from a SCSI CDB.
- Not conforming to any particular CDB variant, but compatible with all. */
-
-struct nvme_trans_io_cdb {
- u8 fua;
- u8 prot_info;
- u64 lba;
- u32 xfer_len;
-};
-
-
-/* Internal Helper Functions */
-
-
-/* Copy data to userspace memory */
-
-static int nvme_trans_copy_to_user(struct sg_io_hdr *hdr, void *from,
- unsigned long n)
-{
- int i;
- void *index = from;
- size_t remaining = n;
- size_t xfer_len;
-
- if (hdr->iovec_count > 0) {
- struct sg_iovec sgl;
-
- for (i = 0; i < hdr->iovec_count; i++) {
- if (copy_from_user(&sgl, hdr->dxferp +
- i * sizeof(struct sg_iovec),
- sizeof(struct sg_iovec)))
- return -EFAULT;
- xfer_len = min(remaining, sgl.iov_len);
- if (copy_to_user(sgl.iov_base, index, xfer_len))
- return -EFAULT;
-
- index += xfer_len;
- remaining -= xfer_len;
- if (remaining == 0)
- break;
- }
- return 0;
- }
-
- if (copy_to_user(hdr->dxferp, from, n))
- return -EFAULT;
- return 0;
-}
-
-/* Copy data from userspace memory */
-
-static int nvme_trans_copy_from_user(struct sg_io_hdr *hdr, void *to,
- unsigned long n)
-{
- int i;
- void *index = to;
- size_t remaining = n;
- size_t xfer_len;
-
- if (hdr->iovec_count > 0) {
- struct sg_iovec sgl;
-
- for (i = 0; i < hdr->iovec_count; i++) {
- if (copy_from_user(&sgl, hdr->dxferp +
- i * sizeof(struct sg_iovec),
- sizeof(struct sg_iovec)))
- return -EFAULT;
- xfer_len = min(remaining, sgl.iov_len);
- if (copy_from_user(index, sgl.iov_base, xfer_len))
- return -EFAULT;
- index += xfer_len;
- remaining -= xfer_len;
- if (remaining == 0)
- break;
- }
- return 0;
- }
-
- if (copy_from_user(to, hdr->dxferp, n))
- return -EFAULT;
- return 0;
-}
-
-/* Status/Sense Buffer Writeback */
-
-static int nvme_trans_completion(struct sg_io_hdr *hdr, u8 status, u8 sense_key,
- u8 asc, u8 ascq)
-{
- u8 xfer_len;
- u8 resp[DESC_FMT_SENSE_DATA_SIZE];
-
- if (scsi_status_is_good(status)) {
- hdr->status = SAM_STAT_GOOD;
- hdr->masked_status = GOOD;
- hdr->host_status = DID_OK;
- hdr->driver_status = DRIVER_OK;
- hdr->sb_len_wr = 0;
- } else {
- hdr->status = status;
- hdr->masked_status = status >> 1;
- hdr->host_status = DID_OK;
- hdr->driver_status = DRIVER_OK;
-
- memset(resp, 0, DESC_FMT_SENSE_DATA_SIZE);
- resp[0] = DESC_FORMAT_SENSE_DATA;
- resp[1] = sense_key;
- resp[2] = asc;
- resp[3] = ascq;
-
- xfer_len = min_t(u8, hdr->mx_sb_len, DESC_FMT_SENSE_DATA_SIZE);
- hdr->sb_len_wr = xfer_len;
- if (copy_to_user(hdr->sbp, resp, xfer_len) > 0)
- return -EFAULT;
- }
-
- return 0;
-}
-
-/*
- * Take a status code from a lowlevel routine, and if it was a positive NVMe
- * error code update the sense data based on it. In either case the passed
- * in value is returned again, unless an -EFAULT from copy_to_user overrides
- * it.
- */
-static int nvme_trans_status_code(struct sg_io_hdr *hdr, int nvme_sc)
-{
- u8 status, sense_key, asc, ascq;
- int res;
-
- /* For non-nvme (Linux) errors, simply return the error code */
- if (nvme_sc < 0)
- return nvme_sc;
-
- /* Mask DNR, More, and reserved fields */
- switch (nvme_sc & 0x7FF) {
- /* Generic Command Status */
- case NVME_SC_SUCCESS:
- status = SAM_STAT_GOOD;
- sense_key = NO_SENSE;
- asc = SCSI_ASC_NO_SENSE;
- ascq = SCSI_ASCQ_CAUSE_NOT_REPORTABLE;
- break;
- case NVME_SC_INVALID_OPCODE:
- status = SAM_STAT_CHECK_CONDITION;
- sense_key = ILLEGAL_REQUEST;
- asc = SCSI_ASC_ILLEGAL_COMMAND;
- ascq = SCSI_ASCQ_CAUSE_NOT_REPORTABLE;
- break;
- case NVME_SC_INVALID_FIELD:
- status = SAM_STAT_CHECK_CONDITION;
- sense_key = ILLEGAL_REQUEST;
- asc = SCSI_ASC_INVALID_CDB;
- ascq = SCSI_ASCQ_CAUSE_NOT_REPORTABLE;
- break;
- case NVME_SC_DATA_XFER_ERROR:
- status = SAM_STAT_CHECK_CONDITION;
- sense_key = MEDIUM_ERROR;
- asc = SCSI_ASC_NO_SENSE;
- ascq = SCSI_ASCQ_CAUSE_NOT_REPORTABLE;
- break;
- case NVME_SC_POWER_LOSS:
- status = SAM_STAT_TASK_ABORTED;
- sense_key = ABORTED_COMMAND;
- asc = SCSI_ASC_WARNING;
- ascq = SCSI_ASCQ_POWER_LOSS_EXPECTED;
- break;
- case NVME_SC_INTERNAL:
- status = SAM_STAT_CHECK_CONDITION;
- sense_key = HARDWARE_ERROR;
- asc = SCSI_ASC_INTERNAL_TARGET_FAILURE;
- ascq = SCSI_ASCQ_CAUSE_NOT_REPORTABLE;
- break;
- case NVME_SC_ABORT_REQ:
- status = SAM_STAT_TASK_ABORTED;
- sense_key = ABORTED_COMMAND;
- asc = SCSI_ASC_NO_SENSE;
- ascq = SCSI_ASCQ_CAUSE_NOT_REPORTABLE;
- break;
- case NVME_SC_ABORT_QUEUE:
- status = SAM_STAT_TASK_ABORTED;
- sense_key = ABORTED_COMMAND;
- asc = SCSI_ASC_NO_SENSE;
- ascq = SCSI_ASCQ_CAUSE_NOT_REPORTABLE;
- break;
- case NVME_SC_FUSED_FAIL:
- status = SAM_STAT_TASK_ABORTED;
- sense_key = ABORTED_COMMAND;
- asc = SCSI_ASC_NO_SENSE;
- ascq = SCSI_ASCQ_CAUSE_NOT_REPORTABLE;
- break;
- case NVME_SC_FUSED_MISSING:
- status = SAM_STAT_TASK_ABORTED;
- sense_key = ABORTED_COMMAND;
- asc = SCSI_ASC_NO_SENSE;
- ascq = SCSI_ASCQ_CAUSE_NOT_REPORTABLE;
- break;
- case NVME_SC_INVALID_NS:
- status = SAM_STAT_CHECK_CONDITION;
- sense_key = ILLEGAL_REQUEST;
- asc = SCSI_ASC_ACCESS_DENIED_INVALID_LUN_ID;
- ascq = SCSI_ASCQ_INVALID_LUN_ID;
- break;
- case NVME_SC_LBA_RANGE:
- status = SAM_STAT_CHECK_CONDITION;
- sense_key = ILLEGAL_REQUEST;
- asc = SCSI_ASC_ILLEGAL_BLOCK;
- ascq = SCSI_ASCQ_CAUSE_NOT_REPORTABLE;
- break;
- case NVME_SC_CAP_EXCEEDED:
- status = SAM_STAT_CHECK_CONDITION;
- sense_key = MEDIUM_ERROR;
- asc = SCSI_ASC_NO_SENSE;
- ascq = SCSI_ASCQ_CAUSE_NOT_REPORTABLE;
- break;
- case NVME_SC_NS_NOT_READY:
- status = SAM_STAT_CHECK_CONDITION;
- sense_key = NOT_READY;
- asc = SCSI_ASC_LUN_NOT_READY;
- ascq = SCSI_ASCQ_CAUSE_NOT_REPORTABLE;
- break;
-
- /* Command Specific Status */
- case NVME_SC_INVALID_FORMAT:
- status = SAM_STAT_CHECK_CONDITION;
- sense_key = ILLEGAL_REQUEST;
- asc = SCSI_ASC_FORMAT_COMMAND_FAILED;
- ascq = SCSI_ASCQ_FORMAT_COMMAND_FAILED;
- break;
- case NVME_SC_BAD_ATTRIBUTES:
- status = SAM_STAT_CHECK_CONDITION;
- sense_key = ILLEGAL_REQUEST;
- asc = SCSI_ASC_INVALID_CDB;
- ascq = SCSI_ASCQ_CAUSE_NOT_REPORTABLE;
- break;
-
- /* Media Errors */
- case NVME_SC_WRITE_FAULT:
- status = SAM_STAT_CHECK_CONDITION;
- sense_key = MEDIUM_ERROR;
- asc = SCSI_ASC_PERIPHERAL_DEV_WRITE_FAULT;
- ascq = SCSI_ASCQ_CAUSE_NOT_REPORTABLE;
- break;
- case NVME_SC_READ_ERROR:
- status = SAM_STAT_CHECK_CONDITION;
- sense_key = MEDIUM_ERROR;
- asc = SCSI_ASC_UNRECOVERED_READ_ERROR;
- ascq = SCSI_ASCQ_CAUSE_NOT_REPORTABLE;
- break;
- case NVME_SC_GUARD_CHECK:
- status = SAM_STAT_CHECK_CONDITION;
- sense_key = MEDIUM_ERROR;
- asc = SCSI_ASC_LOG_BLOCK_GUARD_CHECK_FAILED;
- ascq = SCSI_ASCQ_LOG_BLOCK_GUARD_CHECK_FAILED;
- break;
- case NVME_SC_APPTAG_CHECK:
- status = SAM_STAT_CHECK_CONDITION;
- sense_key = MEDIUM_ERROR;
- asc = SCSI_ASC_LOG_BLOCK_APPTAG_CHECK_FAILED;
- ascq = SCSI_ASCQ_LOG_BLOCK_APPTAG_CHECK_FAILED;
- break;
- case NVME_SC_REFTAG_CHECK:
- status = SAM_STAT_CHECK_CONDITION;
- sense_key = MEDIUM_ERROR;
- asc = SCSI_ASC_LOG_BLOCK_REFTAG_CHECK_FAILED;
- ascq = SCSI_ASCQ_LOG_BLOCK_REFTAG_CHECK_FAILED;
- break;
- case NVME_SC_COMPARE_FAILED:
- status = SAM_STAT_CHECK_CONDITION;
- sense_key = MISCOMPARE;
- asc = SCSI_ASC_MISCOMPARE_DURING_VERIFY;
- ascq = SCSI_ASCQ_CAUSE_NOT_REPORTABLE;
- break;
- case NVME_SC_ACCESS_DENIED:
- status = SAM_STAT_CHECK_CONDITION;
- sense_key = ILLEGAL_REQUEST;
- asc = SCSI_ASC_ACCESS_DENIED_INVALID_LUN_ID;
- ascq = SCSI_ASCQ_INVALID_LUN_ID;
- break;
-
- /* Unspecified/Default */
- case NVME_SC_CMDID_CONFLICT:
- case NVME_SC_CMD_SEQ_ERROR:
- case NVME_SC_CQ_INVALID:
- case NVME_SC_QID_INVALID:
- case NVME_SC_QUEUE_SIZE:
- case NVME_SC_ABORT_LIMIT:
- case NVME_SC_ABORT_MISSING:
- case NVME_SC_ASYNC_LIMIT:
- case NVME_SC_FIRMWARE_SLOT:
- case NVME_SC_FIRMWARE_IMAGE:
- case NVME_SC_INVALID_VECTOR:
- case NVME_SC_INVALID_LOG_PAGE:
- default:
- status = SAM_STAT_CHECK_CONDITION;
- sense_key = ILLEGAL_REQUEST;
- asc = SCSI_ASC_NO_SENSE;
- ascq = SCSI_ASCQ_CAUSE_NOT_REPORTABLE;
- break;
- }
-
- res = nvme_trans_completion(hdr, status, sense_key, asc, ascq);
- return res ? res : nvme_sc;
-}
-
-/* INQUIRY Helper Functions */
-
-static int nvme_trans_standard_inquiry_page(struct nvme_ns *ns,
- struct sg_io_hdr *hdr, u8 *inq_response,
- int alloc_len)
-{
- struct nvme_ctrl *ctrl = ns->ctrl;
- struct nvme_id_ns *id_ns;
- int res;
- int nvme_sc;
- int xfer_len;
- u8 resp_data_format = 0x02;
- u8 protect;
- u8 cmdque = 0x01 << 1;
- u8 fw_offset = sizeof(ctrl->firmware_rev);
-
- /* nvme ns identify - use DPS value for PROTECT field */
- nvme_sc = nvme_identify_ns(ctrl, ns->ns_id, &id_ns);
- res = nvme_trans_status_code(hdr, nvme_sc);
- if (res)
- return res;
-
- if (id_ns->dps)
- protect = 0x01;
- else
- protect = 0;
- kfree(id_ns);
-
- memset(inq_response, 0, STANDARD_INQUIRY_LENGTH);
- inq_response[2] = VERSION_SPC_4;
- inq_response[3] = resp_data_format; /*normaca=0 | hisup=0 */
- inq_response[4] = ADDITIONAL_STD_INQ_LENGTH;
- inq_response[5] = protect; /* sccs=0 | acc=0 | tpgs=0 | pc3=0 */
- inq_response[7] = cmdque; /* wbus16=0 | sync=0 | vs=0 */
- strncpy(&inq_response[8], "NVMe ", 8);
- strncpy(&inq_response[16], ctrl->model, 16);
-
- while (ctrl->firmware_rev[fw_offset - 1] == ' ' && fw_offset > 4)
- fw_offset--;
- fw_offset -= 4;
- strncpy(&inq_response[32], ctrl->firmware_rev + fw_offset, 4);
-
- xfer_len = min(alloc_len, STANDARD_INQUIRY_LENGTH);
- return nvme_trans_copy_to_user(hdr, inq_response, xfer_len);
-}
-
-static int nvme_trans_supported_vpd_pages(struct nvme_ns *ns,
- struct sg_io_hdr *hdr, u8 *inq_response,
- int alloc_len)
-{
- int xfer_len;
-
- memset(inq_response, 0, STANDARD_INQUIRY_LENGTH);
- inq_response[1] = INQ_SUPPORTED_VPD_PAGES_PAGE; /* Page Code */
- inq_response[3] = INQ_NUM_SUPPORTED_VPD_PAGES; /* Page Length */
- inq_response[4] = INQ_SUPPORTED_VPD_PAGES_PAGE;
- inq_response[5] = INQ_UNIT_SERIAL_NUMBER_PAGE;
- inq_response[6] = INQ_DEVICE_IDENTIFICATION_PAGE;
- inq_response[7] = INQ_EXTENDED_INQUIRY_DATA_PAGE;
- inq_response[8] = INQ_BDEV_CHARACTERISTICS_PAGE;
- inq_response[9] = INQ_BDEV_LIMITS_PAGE;
-
- xfer_len = min(alloc_len, STANDARD_INQUIRY_LENGTH);
- return nvme_trans_copy_to_user(hdr, inq_response, xfer_len);
-}
-
-static int nvme_trans_unit_serial_page(struct nvme_ns *ns,
- struct sg_io_hdr *hdr, u8 *inq_response,
- int alloc_len)
-{
- int xfer_len;
-
- memset(inq_response, 0, STANDARD_INQUIRY_LENGTH);
- inq_response[1] = INQ_UNIT_SERIAL_NUMBER_PAGE; /* Page Code */
- inq_response[3] = INQ_SERIAL_NUMBER_LENGTH; /* Page Length */
- strncpy(&inq_response[4], ns->ctrl->serial, INQ_SERIAL_NUMBER_LENGTH);
-
- xfer_len = min(alloc_len, STANDARD_INQUIRY_LENGTH);
- return nvme_trans_copy_to_user(hdr, inq_response, xfer_len);
-}
-
-static int nvme_fill_device_id_eui64(struct nvme_ns *ns, struct sg_io_hdr *hdr,
- u8 *inq_response, int alloc_len)
-{
- struct nvme_id_ns *id_ns;
- int nvme_sc, res;
- size_t len;
- void *eui;
-
- nvme_sc = nvme_identify_ns(ns->ctrl, ns->ns_id, &id_ns);
- res = nvme_trans_status_code(hdr, nvme_sc);
- if (res)
- return res;
-
- eui = id_ns->eui64;
- len = sizeof(id_ns->eui64);
-
- if (ns->ctrl->vs >= NVME_VS(1, 2, 0)) {
- if (bitmap_empty(eui, len * 8)) {
- eui = id_ns->nguid;
- len = sizeof(id_ns->nguid);
- }
- }
-
- if (bitmap_empty(eui, len * 8)) {
- res = -EOPNOTSUPP;
- goto out_free_id;
- }
-
- memset(inq_response, 0, alloc_len);
- inq_response[1] = INQ_DEVICE_IDENTIFICATION_PAGE;
- inq_response[3] = 4 + len; /* Page Length */
-
- /* Designation Descriptor start */
- inq_response[4] = 0x01; /* Proto ID=0h | Code set=1h */
- inq_response[5] = 0x02; /* PIV=0b | Asso=00b | Designator Type=2h */
- inq_response[6] = 0x00; /* Rsvd */
- inq_response[7] = len; /* Designator Length */
- memcpy(&inq_response[8], eui, len);
-
- res = nvme_trans_copy_to_user(hdr, inq_response, alloc_len);
-out_free_id:
- kfree(id_ns);
- return res;
-}
-
-static int nvme_fill_device_id_scsi_string(struct nvme_ns *ns,
- struct sg_io_hdr *hdr, u8 *inq_response, int alloc_len)
-{
- struct nvme_ctrl *ctrl = ns->ctrl;
- struct nvme_id_ctrl *id_ctrl;
- int nvme_sc, res;
-
- if (alloc_len < 72) {
- return nvme_trans_completion(hdr,
- SAM_STAT_CHECK_CONDITION,
- ILLEGAL_REQUEST, SCSI_ASC_INVALID_CDB,
- SCSI_ASCQ_CAUSE_NOT_REPORTABLE);
- }
-
- nvme_sc = nvme_identify_ctrl(ctrl, &id_ctrl);
- res = nvme_trans_status_code(hdr, nvme_sc);
- if (res)
- return res;
-
- memset(inq_response, 0, alloc_len);
- inq_response[1] = INQ_DEVICE_IDENTIFICATION_PAGE;
- inq_response[3] = 0x48; /* Page Length */
-
- /* Designation Descriptor start */
- inq_response[4] = 0x03; /* Proto ID=0h | Code set=3h */
- inq_response[5] = 0x08; /* PIV=0b | Asso=00b | Designator Type=8h */
- inq_response[6] = 0x00; /* Rsvd */
- inq_response[7] = 0x44; /* Designator Length */
-
- sprintf(&inq_response[8], "%04x", le16_to_cpu(id_ctrl->vid));
- memcpy(&inq_response[12], ctrl->model, sizeof(ctrl->model));
- sprintf(&inq_response[52], "%04x", cpu_to_be32(ns->ns_id));
- memcpy(&inq_response[56], ctrl->serial, sizeof(ctrl->serial));
-
- res = nvme_trans_copy_to_user(hdr, inq_response, alloc_len);
- kfree(id_ctrl);
- return res;
-}
-
-static int nvme_trans_device_id_page(struct nvme_ns *ns, struct sg_io_hdr *hdr,
- u8 *resp, int alloc_len)
-{
- int res;
-
- if (ns->ctrl->vs >= NVME_VS(1, 1, 0)) {
- res = nvme_fill_device_id_eui64(ns, hdr, resp, alloc_len);
- if (res != -EOPNOTSUPP)
- return res;
- }
-
- return nvme_fill_device_id_scsi_string(ns, hdr, resp, alloc_len);
-}
-
-static int nvme_trans_ext_inq_page(struct nvme_ns *ns, struct sg_io_hdr *hdr,
- int alloc_len)
-{
- u8 *inq_response;
- int res;
- int nvme_sc;
- struct nvme_ctrl *ctrl = ns->ctrl;
- struct nvme_id_ctrl *id_ctrl;
- struct nvme_id_ns *id_ns;
- int xfer_len;
- u8 microcode = 0x80;
- u8 spt;
- u8 spt_lut[8] = {0, 0, 2, 1, 4, 6, 5, 7};
- u8 grd_chk, app_chk, ref_chk, protect;
- u8 uask_sup = 0x20;
- u8 v_sup;
- u8 luiclr = 0x01;
-
- inq_response = kmalloc(EXTENDED_INQUIRY_DATA_PAGE_LENGTH, GFP_KERNEL);
- if (inq_response == NULL)
- return -ENOMEM;
-
- nvme_sc = nvme_identify_ns(ctrl, ns->ns_id, &id_ns);
- res = nvme_trans_status_code(hdr, nvme_sc);
- if (res)
- goto out_free_inq;
-
- spt = spt_lut[id_ns->dpc & 0x07] << 3;
- if (id_ns->dps)
- protect = 0x01;
- else
- protect = 0;
- kfree(id_ns);
-
- grd_chk = protect << 2;
- app_chk = protect << 1;
- ref_chk = protect;
-
- nvme_sc = nvme_identify_ctrl(ctrl, &id_ctrl);
- res = nvme_trans_status_code(hdr, nvme_sc);
- if (res)
- goto out_free_inq;
-
- v_sup = id_ctrl->vwc;
- kfree(id_ctrl);
-
- memset(inq_response, 0, EXTENDED_INQUIRY_DATA_PAGE_LENGTH);
- inq_response[1] = INQ_EXTENDED_INQUIRY_DATA_PAGE; /* Page Code */
- inq_response[2] = 0x00; /* Page Length MSB */
- inq_response[3] = 0x3C; /* Page Length LSB */
- inq_response[4] = microcode | spt | grd_chk | app_chk | ref_chk;
- inq_response[5] = uask_sup;
- inq_response[6] = v_sup;
- inq_response[7] = luiclr;
- inq_response[8] = 0;
- inq_response[9] = 0;
-
- xfer_len = min(alloc_len, EXTENDED_INQUIRY_DATA_PAGE_LENGTH);
- res = nvme_trans_copy_to_user(hdr, inq_response, xfer_len);
-
- out_free_inq:
- kfree(inq_response);
- return res;
-}
-
-static int nvme_trans_bdev_limits_page(struct nvme_ns *ns, struct sg_io_hdr *hdr,
- u8 *inq_response, int alloc_len)
-{
- __be32 max_sectors = cpu_to_be32(
- nvme_block_nr(ns, queue_max_hw_sectors(ns->queue)));
- __be32 max_discard = cpu_to_be32(ns->queue->limits.max_discard_sectors);
- __be32 discard_desc_count = cpu_to_be32(0x100);
-
- memset(inq_response, 0, STANDARD_INQUIRY_LENGTH);
- inq_response[1] = VPD_BLOCK_LIMITS;
- inq_response[3] = 0x3c; /* Page Length */
- memcpy(&inq_response[8], &max_sectors, sizeof(u32));
- memcpy(&inq_response[20], &max_discard, sizeof(u32));
-
- if (max_discard)
- memcpy(&inq_response[24], &discard_desc_count, sizeof(u32));
-
- return nvme_trans_copy_to_user(hdr, inq_response, 0x3c);
-}
-
-static int nvme_trans_bdev_char_page(struct nvme_ns *ns, struct sg_io_hdr *hdr,
- int alloc_len)
-{
- u8 *inq_response;
- int res;
- int xfer_len;
-
- inq_response = kzalloc(EXTENDED_INQUIRY_DATA_PAGE_LENGTH, GFP_KERNEL);
- if (inq_response == NULL) {
- res = -ENOMEM;
- goto out_mem;
- }
-
- inq_response[1] = INQ_BDEV_CHARACTERISTICS_PAGE; /* Page Code */
- inq_response[2] = 0x00; /* Page Length MSB */
- inq_response[3] = 0x3C; /* Page Length LSB */
- inq_response[4] = 0x00; /* Medium Rotation Rate MSB */
- inq_response[5] = 0x01; /* Medium Rotation Rate LSB */
- inq_response[6] = 0x00; /* Form Factor */
-
- xfer_len = min(alloc_len, EXTENDED_INQUIRY_DATA_PAGE_LENGTH);
- res = nvme_trans_copy_to_user(hdr, inq_response, xfer_len);
-
- kfree(inq_response);
- out_mem:
- return res;
-}
-
-/* LOG SENSE Helper Functions */
-
-static int nvme_trans_log_supp_pages(struct nvme_ns *ns, struct sg_io_hdr *hdr,
- int alloc_len)
-{
- int res;
- int xfer_len;
- u8 *log_response;
-
- log_response = kzalloc(LOG_PAGE_SUPPORTED_LOG_PAGES_LENGTH, GFP_KERNEL);
- if (log_response == NULL) {
- res = -ENOMEM;
- goto out_mem;
- }
-
- log_response[0] = LOG_PAGE_SUPPORTED_LOG_PAGES_PAGE;
- /* Subpage=0x00, Page Length MSB=0 */
- log_response[3] = SUPPORTED_LOG_PAGES_PAGE_LENGTH;
- log_response[4] = LOG_PAGE_SUPPORTED_LOG_PAGES_PAGE;
- log_response[5] = LOG_PAGE_INFORMATIONAL_EXCEPTIONS_PAGE;
- log_response[6] = LOG_PAGE_TEMPERATURE_PAGE;
-
- xfer_len = min(alloc_len, LOG_PAGE_SUPPORTED_LOG_PAGES_LENGTH);
- res = nvme_trans_copy_to_user(hdr, log_response, xfer_len);
-
- kfree(log_response);
- out_mem:
- return res;
-}
-
-static int nvme_trans_log_info_exceptions(struct nvme_ns *ns,
- struct sg_io_hdr *hdr, int alloc_len)
-{
- int res;
- int xfer_len;
- u8 *log_response;
- struct nvme_smart_log *smart_log;
- u8 temp_c;
- u16 temp_k;
-
- log_response = kzalloc(LOG_INFO_EXCP_PAGE_LENGTH, GFP_KERNEL);
- if (log_response == NULL)
- return -ENOMEM;
-
- res = nvme_get_log_page(ns->ctrl, &smart_log);
- if (res < 0)
- goto out_free_response;
-
- if (res != NVME_SC_SUCCESS) {
- temp_c = LOG_TEMP_UNKNOWN;
- } else {
- temp_k = (smart_log->temperature[1] << 8) +
- (smart_log->temperature[0]);
- temp_c = temp_k - KELVIN_TEMP_FACTOR;
- }
- kfree(smart_log);
-
- log_response[0] = LOG_PAGE_INFORMATIONAL_EXCEPTIONS_PAGE;
- /* Subpage=0x00, Page Length MSB=0 */
- log_response[3] = REMAINING_INFO_EXCP_PAGE_LENGTH;
- /* Informational Exceptions Log Parameter 1 Start */
- /* Parameter Code=0x0000 bytes 4,5 */
- log_response[6] = 0x23; /* DU=0, TSD=1, ETC=0, TMC=0, FMT_AND_LNK=11b */
- log_response[7] = 0x04; /* PARAMETER LENGTH */
- /* Add sense Code and qualifier = 0x00 each */
- /* Use Temperature from NVMe Get Log Page, convert to C from K */
- log_response[10] = temp_c;
-
- xfer_len = min(alloc_len, LOG_INFO_EXCP_PAGE_LENGTH);
- res = nvme_trans_copy_to_user(hdr, log_response, xfer_len);
-
- out_free_response:
- kfree(log_response);
- return res;
-}
-
-static int nvme_trans_log_temperature(struct nvme_ns *ns, struct sg_io_hdr *hdr,
- int alloc_len)
-{
- int res;
- int xfer_len;
- u8 *log_response;
- struct nvme_smart_log *smart_log;
- u32 feature_resp;
- u8 temp_c_cur, temp_c_thresh;
- u16 temp_k;
-
- log_response = kzalloc(LOG_TEMP_PAGE_LENGTH, GFP_KERNEL);
- if (log_response == NULL)
- return -ENOMEM;
-
- res = nvme_get_log_page(ns->ctrl, &smart_log);
- if (res < 0)
- goto out_free_response;
-
- if (res != NVME_SC_SUCCESS) {
- temp_c_cur = LOG_TEMP_UNKNOWN;
- } else {
- temp_k = (smart_log->temperature[1] << 8) +
- (smart_log->temperature[0]);
- temp_c_cur = temp_k - KELVIN_TEMP_FACTOR;
- }
- kfree(smart_log);
-
- /* Get Features for Temp Threshold */
- res = nvme_get_features(ns->ctrl, NVME_FEAT_TEMP_THRESH, 0, NULL, 0,
- &feature_resp);
- if (res != NVME_SC_SUCCESS)
- temp_c_thresh = LOG_TEMP_UNKNOWN;
- else
- temp_c_thresh = (feature_resp & 0xFFFF) - KELVIN_TEMP_FACTOR;
-
- log_response[0] = LOG_PAGE_TEMPERATURE_PAGE;
- /* Subpage=0x00, Page Length MSB=0 */
- log_response[3] = REMAINING_TEMP_PAGE_LENGTH;
- /* Temperature Log Parameter 1 (Temperature) Start */
- /* Parameter Code = 0x0000 */
- log_response[6] = 0x01; /* Format and Linking = 01b */
- log_response[7] = 0x02; /* Parameter Length */
- /* Use Temperature from NVMe Get Log Page, convert to C from K */
- log_response[9] = temp_c_cur;
- /* Temperature Log Parameter 2 (Reference Temperature) Start */
- log_response[11] = 0x01; /* Parameter Code = 0x0001 */
- log_response[12] = 0x01; /* Format and Linking = 01b */
- log_response[13] = 0x02; /* Parameter Length */
- /* Use Temperature Thresh from NVMe Get Log Page, convert to C from K */
- log_response[15] = temp_c_thresh;
-
- xfer_len = min(alloc_len, LOG_TEMP_PAGE_LENGTH);
- res = nvme_trans_copy_to_user(hdr, log_response, xfer_len);
-
- out_free_response:
- kfree(log_response);
- return res;
-}
-
-/* MODE SENSE Helper Functions */
-
-static int nvme_trans_fill_mode_parm_hdr(u8 *resp, int len, u8 cdb10, u8 llbaa,
- u16 mode_data_length, u16 blk_desc_len)
-{
- /* Quick check to make sure I don't stomp on my own memory... */
- if ((cdb10 && len < 8) || (!cdb10 && len < 4))
- return -EINVAL;
-
- if (cdb10) {
- resp[0] = (mode_data_length & 0xFF00) >> 8;
- resp[1] = (mode_data_length & 0x00FF);
- resp[3] = 0x10 /* DPOFUA */;
- resp[4] = llbaa;
- resp[5] = RESERVED_FIELD;
- resp[6] = (blk_desc_len & 0xFF00) >> 8;
- resp[7] = (blk_desc_len & 0x00FF);
- } else {
- resp[0] = (mode_data_length & 0x00FF);
- resp[2] = 0x10 /* DPOFUA */;
- resp[3] = (blk_desc_len & 0x00FF);
- }
-
- return 0;
-}
-
-static int nvme_trans_fill_blk_desc(struct nvme_ns *ns, struct sg_io_hdr *hdr,
- u8 *resp, int len, u8 llbaa)
-{
- int res;
- int nvme_sc;
- struct nvme_id_ns *id_ns;
- u8 flbas;
- u32 lba_length;
-
- if (llbaa == 0 && len < MODE_PAGE_BLK_DES_LEN)
- return -EINVAL;
- else if (llbaa > 0 && len < MODE_PAGE_LLBAA_BLK_DES_LEN)
- return -EINVAL;
-
- nvme_sc = nvme_identify_ns(ns->ctrl, ns->ns_id, &id_ns);
- res = nvme_trans_status_code(hdr, nvme_sc);
- if (res)
- return res;
-
- flbas = (id_ns->flbas) & 0x0F;
- lba_length = (1 << (id_ns->lbaf[flbas].ds));
-
- if (llbaa == 0) {
- __be32 tmp_cap = cpu_to_be32(le64_to_cpu(id_ns->ncap));
- /* Byte 4 is reserved */
- __be32 tmp_len = cpu_to_be32(lba_length & 0x00FFFFFF);
-
- memcpy(resp, &tmp_cap, sizeof(u32));
- memcpy(&resp[4], &tmp_len, sizeof(u32));
- } else {
- __be64 tmp_cap = cpu_to_be64(le64_to_cpu(id_ns->ncap));
- __be32 tmp_len = cpu_to_be32(lba_length);
-
- memcpy(resp, &tmp_cap, sizeof(u64));
- /* Bytes 8, 9, 10, 11 are reserved */
- memcpy(&resp[12], &tmp_len, sizeof(u32));
- }
-
- kfree(id_ns);
- return res;
-}
-
-static int nvme_trans_fill_control_page(struct nvme_ns *ns,
- struct sg_io_hdr *hdr, u8 *resp,
- int len)
-{
- if (len < MODE_PAGE_CONTROL_LEN)
- return -EINVAL;
-
- resp[0] = MODE_PAGE_CONTROL;
- resp[1] = MODE_PAGE_CONTROL_LEN_FIELD;
- resp[2] = 0x0E; /* TST=000b, TMF_ONLY=0, DPICZ=1,
- * D_SENSE=1, GLTSD=1, RLEC=0 */
- resp[3] = 0x12; /* Q_ALGO_MODIFIER=1h, NUAR=0, QERR=01b */
- /* Byte 4: VS=0, RAC=0, UA_INT=0, SWP=0 */
- resp[5] = 0x40; /* ATO=0, TAS=1, ATMPE=0, RWWP=0, AUTOLOAD=0 */
- /* resp[6] and [7] are obsolete, thus zero */
- resp[8] = 0xFF; /* Busy timeout period = 0xffff */
- resp[9] = 0xFF;
- /* Bytes 10,11: Extended selftest completion time = 0x0000 */
-
- return 0;
-}
-
-static int nvme_trans_fill_caching_page(struct nvme_ns *ns,
- struct sg_io_hdr *hdr,
- u8 *resp, int len)
-{
- int res = 0;
- int nvme_sc;
- u32 feature_resp;
- u8 vwc;
-
- if (len < MODE_PAGE_CACHING_LEN)
- return -EINVAL;
-
- nvme_sc = nvme_get_features(ns->ctrl, NVME_FEAT_VOLATILE_WC, 0, NULL, 0,
- &feature_resp);
- res = nvme_trans_status_code(hdr, nvme_sc);
- if (res)
- return res;
-
- vwc = feature_resp & 0x00000001;
-
- resp[0] = MODE_PAGE_CACHING;
- resp[1] = MODE_PAGE_CACHING_LEN_FIELD;
- resp[2] = vwc << 2;
- return 0;
-}
-
-static int nvme_trans_fill_pow_cnd_page(struct nvme_ns *ns,
- struct sg_io_hdr *hdr, u8 *resp,
- int len)
-{
- if (len < MODE_PAGE_POW_CND_LEN)
- return -EINVAL;
-
- resp[0] = MODE_PAGE_POWER_CONDITION;
- resp[1] = MODE_PAGE_POW_CND_LEN_FIELD;
- /* All other bytes are zero */
-
- return 0;
-}
-
-static int nvme_trans_fill_inf_exc_page(struct nvme_ns *ns,
- struct sg_io_hdr *hdr, u8 *resp,
- int len)
-{
- if (len < MODE_PAGE_INF_EXC_LEN)
- return -EINVAL;
-
- resp[0] = MODE_PAGE_INFO_EXCEP;
- resp[1] = MODE_PAGE_INF_EXC_LEN_FIELD;
- resp[2] = 0x88;
- /* All other bytes are zero */
-
- return 0;
-}
-
-static int nvme_trans_fill_all_pages(struct nvme_ns *ns, struct sg_io_hdr *hdr,
- u8 *resp, int len)
-{
- int res;
- u16 mode_pages_offset_1 = 0;
- u16 mode_pages_offset_2, mode_pages_offset_3, mode_pages_offset_4;
-
- mode_pages_offset_2 = mode_pages_offset_1 + MODE_PAGE_CACHING_LEN;
- mode_pages_offset_3 = mode_pages_offset_2 + MODE_PAGE_CONTROL_LEN;
- mode_pages_offset_4 = mode_pages_offset_3 + MODE_PAGE_POW_CND_LEN;
-
- res = nvme_trans_fill_caching_page(ns, hdr, &resp[mode_pages_offset_1],
- MODE_PAGE_CACHING_LEN);
- if (res)
- return res;
- res = nvme_trans_fill_control_page(ns, hdr, &resp[mode_pages_offset_2],
- MODE_PAGE_CONTROL_LEN);
- if (res)
- return res;
- res = nvme_trans_fill_pow_cnd_page(ns, hdr, &resp[mode_pages_offset_3],
- MODE_PAGE_POW_CND_LEN);
- if (res)
- return res;
- return nvme_trans_fill_inf_exc_page(ns, hdr, &resp[mode_pages_offset_4],
- MODE_PAGE_INF_EXC_LEN);
-}
-
-static inline int nvme_trans_get_blk_desc_len(u8 dbd, u8 llbaa)
-{
- if (dbd == MODE_SENSE_BLK_DESC_ENABLED) {
- /* SPC-4: len = 8 x Num_of_descriptors if llbaa = 0, 16x if 1 */
- return 8 * (llbaa + 1) * MODE_SENSE_BLK_DESC_COUNT;
- } else {
- return 0;
- }
-}
-
-static int nvme_trans_mode_page_create(struct nvme_ns *ns,
- struct sg_io_hdr *hdr, u8 *cmd,
- u16 alloc_len, u8 cdb10,
- int (*mode_page_fill_func)
- (struct nvme_ns *,
- struct sg_io_hdr *hdr, u8 *, int),
- u16 mode_pages_tot_len)
-{
- int res;
- int xfer_len;
- u8 *response;
- u8 dbd, llbaa;
- u16 resp_size;
- int mph_size;
- u16 mode_pages_offset_1;
- u16 blk_desc_len, blk_desc_offset, mode_data_length;
-
- dbd = (cmd[1] & MODE_SENSE_DBD_MASK) >> MODE_SENSE_DBD_SHIFT;
- llbaa = (cmd[1] & MODE_SENSE_LLBAA_MASK) >> MODE_SENSE_LLBAA_SHIFT;
- mph_size = cdb10 ? MODE_SENSE10_MPH_SIZE : MODE_SENSE6_MPH_SIZE;
-
- blk_desc_len = nvme_trans_get_blk_desc_len(dbd, llbaa);
-
- resp_size = mph_size + blk_desc_len + mode_pages_tot_len;
- /* Refer spc4r34 Table 440 for calculation of Mode data Length field */
- mode_data_length = 3 + (3 * cdb10) + blk_desc_len + mode_pages_tot_len;
-
- blk_desc_offset = mph_size;
- mode_pages_offset_1 = blk_desc_offset + blk_desc_len;
-
- response = kzalloc(resp_size, GFP_KERNEL);
- if (response == NULL) {
- res = -ENOMEM;
- goto out_mem;
- }
-
- res = nvme_trans_fill_mode_parm_hdr(&response[0], mph_size, cdb10,
- llbaa, mode_data_length, blk_desc_len);
- if (res)
- goto out_free;
- if (blk_desc_len > 0) {
- res = nvme_trans_fill_blk_desc(ns, hdr,
- &response[blk_desc_offset],
- blk_desc_len, llbaa);
- if (res)
- goto out_free;
- }
- res = mode_page_fill_func(ns, hdr, &response[mode_pages_offset_1],
- mode_pages_tot_len);
- if (res)
- goto out_free;
-
- xfer_len = min(alloc_len, resp_size);
- res = nvme_trans_copy_to_user(hdr, response, xfer_len);
-
- out_free:
- kfree(response);
- out_mem:
- return res;
-}
-
-/* Read Capacity Helper Functions */
-
-static void nvme_trans_fill_read_cap(u8 *response, struct nvme_id_ns *id_ns,
- u8 cdb16)
-{
- u8 flbas;
- u32 lba_length;
- u64 rlba;
- u8 prot_en;
- u8 p_type_lut[4] = {0, 0, 1, 2};
- __be64 tmp_rlba;
- __be32 tmp_rlba_32;
- __be32 tmp_len;
-
- flbas = (id_ns->flbas) & 0x0F;
- lba_length = (1 << (id_ns->lbaf[flbas].ds));
- rlba = le64_to_cpup(&id_ns->nsze) - 1;
- (id_ns->dps) ? (prot_en = 0x01) : (prot_en = 0);
-
- if (!cdb16) {
- if (rlba > 0xFFFFFFFF)
- rlba = 0xFFFFFFFF;
- tmp_rlba_32 = cpu_to_be32(rlba);
- tmp_len = cpu_to_be32(lba_length);
- memcpy(response, &tmp_rlba_32, sizeof(u32));
- memcpy(&response[4], &tmp_len, sizeof(u32));
- } else {
- tmp_rlba = cpu_to_be64(rlba);
- tmp_len = cpu_to_be32(lba_length);
- memcpy(response, &tmp_rlba, sizeof(u64));
- memcpy(&response[8], &tmp_len, sizeof(u32));
- response[12] = (p_type_lut[id_ns->dps & 0x3] << 1) | prot_en;
- /* P_I_Exponent = 0x0 | LBPPBE = 0x0 */
- /* LBPME = 0 | LBPRZ = 0 | LALBA = 0x00 */
- /* Bytes 16-31 - Reserved */
- }
-}
-
-/* Start Stop Unit Helper Functions */
-
-static int nvme_trans_send_activate_fw_cmd(struct nvme_ns *ns, struct sg_io_hdr *hdr,
- u8 buffer_id)
-{
- struct nvme_command c;
- int nvme_sc;
-
- memset(&c, 0, sizeof(c));
- c.common.opcode = nvme_admin_activate_fw;
- c.common.cdw10[0] = cpu_to_le32(buffer_id | NVME_FWACT_REPL_ACTV);
-
- nvme_sc = nvme_submit_sync_cmd(ns->queue, &c, NULL, 0);
- return nvme_trans_status_code(hdr, nvme_sc);
-}
-
-static int nvme_trans_send_download_fw_cmd(struct nvme_ns *ns, struct sg_io_hdr *hdr,
- u8 opcode, u32 tot_len, u32 offset,
- u8 buffer_id)
-{
- int nvme_sc;
- struct nvme_command c;
-
- if (hdr->iovec_count > 0) {
- /* Assuming SGL is not allowed for this command */
- return nvme_trans_completion(hdr,
- SAM_STAT_CHECK_CONDITION,
- ILLEGAL_REQUEST,
- SCSI_ASC_INVALID_CDB,
- SCSI_ASCQ_CAUSE_NOT_REPORTABLE);
- }
-
- memset(&c, 0, sizeof(c));
- c.common.opcode = nvme_admin_download_fw;
- c.dlfw.numd = cpu_to_le32((tot_len/BYTES_TO_DWORDS) - 1);
- c.dlfw.offset = cpu_to_le32(offset/BYTES_TO_DWORDS);
-
- nvme_sc = nvme_submit_user_cmd(ns->ctrl->admin_q, &c,
- hdr->dxferp, tot_len, NULL, 0);
- return nvme_trans_status_code(hdr, nvme_sc);
-}
-
-/* Mode Select Helper Functions */
-
-static inline void nvme_trans_modesel_get_bd_len(u8 *parm_list, u8 cdb10,
- u16 *bd_len, u8 *llbaa)
-{
- if (cdb10) {
- /* 10 Byte CDB */
- *bd_len = (parm_list[MODE_SELECT_10_BD_OFFSET] << 8) +
- parm_list[MODE_SELECT_10_BD_OFFSET + 1];
- *llbaa = parm_list[MODE_SELECT_10_LLBAA_OFFSET] &
- MODE_SELECT_10_LLBAA_MASK;
- } else {
- /* 6 Byte CDB */
- *bd_len = parm_list[MODE_SELECT_6_BD_OFFSET];
- }
-}
-
-static void nvme_trans_modesel_save_bd(struct nvme_ns *ns, u8 *parm_list,
- u16 idx, u16 bd_len, u8 llbaa)
-{
- /* Store block descriptor info if a FORMAT UNIT comes later */
- /* TODO Saving 1st BD info; what to do if multiple BD received? */
- if (llbaa == 0) {
- /* Standard Block Descriptor - spc4r34 7.5.5.1 */
- ns->mode_select_num_blocks =
- (parm_list[idx + 1] << 16) +
- (parm_list[idx + 2] << 8) +
- (parm_list[idx + 3]);
-
- ns->mode_select_block_len =
- (parm_list[idx + 5] << 16) +
- (parm_list[idx + 6] << 8) +
- (parm_list[idx + 7]);
- } else {
- /* Long LBA Block Descriptor - sbc3r27 6.4.2.3 */
- ns->mode_select_num_blocks =
- (((u64)parm_list[idx + 0]) << 56) +
- (((u64)parm_list[idx + 1]) << 48) +
- (((u64)parm_list[idx + 2]) << 40) +
- (((u64)parm_list[idx + 3]) << 32) +
- (((u64)parm_list[idx + 4]) << 24) +
- (((u64)parm_list[idx + 5]) << 16) +
- (((u64)parm_list[idx + 6]) << 8) +
- ((u64)parm_list[idx + 7]);
-
- ns->mode_select_block_len =
- (parm_list[idx + 12] << 24) +
- (parm_list[idx + 13] << 16) +
- (parm_list[idx + 14] << 8) +
- (parm_list[idx + 15]);
- }
-}
-
-static int nvme_trans_modesel_get_mp(struct nvme_ns *ns, struct sg_io_hdr *hdr,
- u8 *mode_page, u8 page_code)
-{
- int res = 0;
- int nvme_sc;
- unsigned dword11;
-
- switch (page_code) {
- case MODE_PAGE_CACHING:
- dword11 = ((mode_page[2] & CACHING_MODE_PAGE_WCE_MASK) ? 1 : 0);
- nvme_sc = nvme_set_features(ns->ctrl, NVME_FEAT_VOLATILE_WC,
- dword11, NULL, 0, NULL);
- res = nvme_trans_status_code(hdr, nvme_sc);
- break;
- case MODE_PAGE_CONTROL:
- break;
- case MODE_PAGE_POWER_CONDITION:
- /* Verify the OS is not trying to set timers */
- if ((mode_page[2] & 0x01) != 0 || (mode_page[3] & 0x0F) != 0) {
- res = nvme_trans_completion(hdr,
- SAM_STAT_CHECK_CONDITION,
- ILLEGAL_REQUEST,
- SCSI_ASC_INVALID_PARAMETER,
- SCSI_ASCQ_CAUSE_NOT_REPORTABLE);
- break;
- }
- break;
- default:
- res = nvme_trans_completion(hdr, SAM_STAT_CHECK_CONDITION,
- ILLEGAL_REQUEST, SCSI_ASC_INVALID_CDB,
- SCSI_ASCQ_CAUSE_NOT_REPORTABLE);
- break;
- }
-
- return res;
-}
-
-static int nvme_trans_modesel_data(struct nvme_ns *ns, struct sg_io_hdr *hdr,
- u8 *cmd, u16 parm_list_len, u8 pf,
- u8 sp, u8 cdb10)
-{
- int res;
- u8 *parm_list;
- u16 bd_len;
- u8 llbaa = 0;
- u16 index, saved_index;
- u8 page_code;
- u16 mp_size;
-
- /* Get parm list from data-in/out buffer */
- parm_list = kmalloc(parm_list_len, GFP_KERNEL);
- if (parm_list == NULL) {
- res = -ENOMEM;
- goto out;
- }
-
- res = nvme_trans_copy_from_user(hdr, parm_list, parm_list_len);
- if (res)
- goto out_mem;
-
- nvme_trans_modesel_get_bd_len(parm_list, cdb10, &bd_len, &llbaa);
- index = (cdb10) ? (MODE_SELECT_10_MPH_SIZE) : (MODE_SELECT_6_MPH_SIZE);
-
- if (bd_len != 0) {
- /* Block Descriptors present, parse */
- nvme_trans_modesel_save_bd(ns, parm_list, index, bd_len, llbaa);
- index += bd_len;
- }
- saved_index = index;
-
- /* Multiple mode pages may be present; iterate through all */
- /* In 1st Iteration, don't do NVME Command, only check for CDB errors */
- do {
- page_code = parm_list[index] & MODE_SELECT_PAGE_CODE_MASK;
- mp_size = parm_list[index + 1] + 2;
- if ((page_code != MODE_PAGE_CACHING) &&
- (page_code != MODE_PAGE_CONTROL) &&
- (page_code != MODE_PAGE_POWER_CONDITION)) {
- res = nvme_trans_completion(hdr,
- SAM_STAT_CHECK_CONDITION,
- ILLEGAL_REQUEST,
- SCSI_ASC_INVALID_CDB,
- SCSI_ASCQ_CAUSE_NOT_REPORTABLE);
- goto out_mem;
- }
- index += mp_size;
- } while (index < parm_list_len);
-
- /* In 2nd Iteration, do the NVME Commands */
- index = saved_index;
- do {
- page_code = parm_list[index] & MODE_SELECT_PAGE_CODE_MASK;
- mp_size = parm_list[index + 1] + 2;
- res = nvme_trans_modesel_get_mp(ns, hdr, &parm_list[index],
- page_code);
- if (res)
- break;
- index += mp_size;
- } while (index < parm_list_len);
-
- out_mem:
- kfree(parm_list);
- out:
- return res;
-}
-
-/* Format Unit Helper Functions */
-
-static int nvme_trans_fmt_set_blk_size_count(struct nvme_ns *ns,
- struct sg_io_hdr *hdr)
-{
- int res = 0;
- int nvme_sc;
- u8 flbas;
-
- /*
- * SCSI Expects a MODE SELECT would have been issued prior to
- * a FORMAT UNIT, and the block size and number would be used
- * from the block descriptor in it. If a MODE SELECT had not
- * been issued, FORMAT shall use the current values for both.
- */
-
- if (ns->mode_select_num_blocks == 0 || ns->mode_select_block_len == 0) {
- struct nvme_id_ns *id_ns;
-
- nvme_sc = nvme_identify_ns(ns->ctrl, ns->ns_id, &id_ns);
- res = nvme_trans_status_code(hdr, nvme_sc);
- if (res)
- return res;
-
- if (ns->mode_select_num_blocks == 0)
- ns->mode_select_num_blocks = le64_to_cpu(id_ns->ncap);
- if (ns->mode_select_block_len == 0) {
- flbas = (id_ns->flbas) & 0x0F;
- ns->mode_select_block_len =
- (1 << (id_ns->lbaf[flbas].ds));
- }
-
- kfree(id_ns);
- }
-
- return 0;
-}
-
-static int nvme_trans_fmt_get_parm_header(struct sg_io_hdr *hdr, u8 len,
- u8 format_prot_info, u8 *nvme_pf_code)
-{
- int res;
- u8 *parm_list;
- u8 pf_usage, pf_code;
-
- parm_list = kmalloc(len, GFP_KERNEL);
- if (parm_list == NULL) {
- res = -ENOMEM;
- goto out;
- }
- res = nvme_trans_copy_from_user(hdr, parm_list, len);
- if (res)
- goto out_mem;
-
- if ((parm_list[FORMAT_UNIT_IMMED_OFFSET] &
- FORMAT_UNIT_IMMED_MASK) != 0) {
- res = nvme_trans_completion(hdr, SAM_STAT_CHECK_CONDITION,
- ILLEGAL_REQUEST, SCSI_ASC_INVALID_CDB,
- SCSI_ASCQ_CAUSE_NOT_REPORTABLE);
- goto out_mem;
- }
-
- if (len == FORMAT_UNIT_LONG_PARM_LIST_LEN &&
- (parm_list[FORMAT_UNIT_PROT_INT_OFFSET] & 0x0F) != 0) {
- res = nvme_trans_completion(hdr, SAM_STAT_CHECK_CONDITION,
- ILLEGAL_REQUEST, SCSI_ASC_INVALID_CDB,
- SCSI_ASCQ_CAUSE_NOT_REPORTABLE);
- goto out_mem;
- }
- pf_usage = parm_list[FORMAT_UNIT_PROT_FIELD_USAGE_OFFSET] &
- FORMAT_UNIT_PROT_FIELD_USAGE_MASK;
- pf_code = (pf_usage << 2) | format_prot_info;
- switch (pf_code) {
- case 0:
- *nvme_pf_code = 0;
- break;
- case 2:
- *nvme_pf_code = 1;
- break;
- case 3:
- *nvme_pf_code = 2;
- break;
- case 7:
- *nvme_pf_code = 3;
- break;
- default:
- res = nvme_trans_completion(hdr, SAM_STAT_CHECK_CONDITION,
- ILLEGAL_REQUEST, SCSI_ASC_INVALID_CDB,
- SCSI_ASCQ_CAUSE_NOT_REPORTABLE);
- break;
- }
-
- out_mem:
- kfree(parm_list);
- out:
- return res;
-}
-
-static int nvme_trans_fmt_send_cmd(struct nvme_ns *ns, struct sg_io_hdr *hdr,
- u8 prot_info)
-{
- int res;
- int nvme_sc;
- struct nvme_id_ns *id_ns;
- u8 i;
- u8 nlbaf;
- u8 selected_lbaf = 0xFF;
- u32 cdw10 = 0;
- struct nvme_command c;
-
- /* Loop thru LBAF's in id_ns to match reqd lbaf, put in cdw10 */
- nvme_sc = nvme_identify_ns(ns->ctrl, ns->ns_id, &id_ns);
- res = nvme_trans_status_code(hdr, nvme_sc);
- if (res)
- return res;
-
- nlbaf = id_ns->nlbaf;
-
- for (i = 0; i < nlbaf; i++) {
- if (ns->mode_select_block_len == (1 << (id_ns->lbaf[i].ds))) {
- selected_lbaf = i;
- break;
- }
- }
- if (selected_lbaf > 0x0F) {
- res = nvme_trans_completion(hdr, SAM_STAT_CHECK_CONDITION,
- ILLEGAL_REQUEST, SCSI_ASC_INVALID_PARAMETER,
- SCSI_ASCQ_CAUSE_NOT_REPORTABLE);
- }
- if (ns->mode_select_num_blocks != le64_to_cpu(id_ns->ncap)) {
- res = nvme_trans_completion(hdr, SAM_STAT_CHECK_CONDITION,
- ILLEGAL_REQUEST, SCSI_ASC_INVALID_PARAMETER,
- SCSI_ASCQ_CAUSE_NOT_REPORTABLE);
- }
-
- cdw10 |= prot_info << 5;
- cdw10 |= selected_lbaf & 0x0F;
- memset(&c, 0, sizeof(c));
- c.format.opcode = nvme_admin_format_nvm;
- c.format.nsid = cpu_to_le32(ns->ns_id);
- c.format.cdw10 = cpu_to_le32(cdw10);
-
- nvme_sc = nvme_submit_sync_cmd(ns->ctrl->admin_q, &c, NULL, 0);
- res = nvme_trans_status_code(hdr, nvme_sc);
-
- kfree(id_ns);
- return res;
-}
-
-static inline u32 nvme_trans_io_get_num_cmds(struct sg_io_hdr *hdr,
- struct nvme_trans_io_cdb *cdb_info,
- u32 max_blocks)
-{
- /* If using iovecs, send one nvme command per vector */
- if (hdr->iovec_count > 0)
- return hdr->iovec_count;
- else if (cdb_info->xfer_len > max_blocks)
- return ((cdb_info->xfer_len - 1) / max_blocks) + 1;
- else
- return 1;
-}
-
-static u16 nvme_trans_io_get_control(struct nvme_ns *ns,
- struct nvme_trans_io_cdb *cdb_info)
-{
- u16 control = 0;
-
- /* When Protection information support is added, implement here */
-
- if (cdb_info->fua > 0)
- control |= NVME_RW_FUA;
-
- return control;
-}
-
-static int nvme_trans_do_nvme_io(struct nvme_ns *ns, struct sg_io_hdr *hdr,
- struct nvme_trans_io_cdb *cdb_info, u8 is_write)
-{
- int nvme_sc = NVME_SC_SUCCESS;
- u32 num_cmds;
- u64 unit_len;
- u64 unit_num_blocks; /* Number of blocks to xfer in each nvme cmd */
- u32 retcode;
- u32 i = 0;
- u64 nvme_offset = 0;
- void __user *next_mapping_addr;
- struct nvme_command c;
- u8 opcode = (is_write ? nvme_cmd_write : nvme_cmd_read);
- u16 control;
- u32 max_blocks = queue_max_hw_sectors(ns->queue) >> (ns->lba_shift - 9);
-
- num_cmds = nvme_trans_io_get_num_cmds(hdr, cdb_info, max_blocks);
-
- /*
- * This loop handles two cases.
- * First, when an SGL is used in the form of an iovec list:
- * - Use iov_base as the next mapping address for the nvme command_id
- * - Use iov_len as the data transfer length for the command.
- * Second, when we have a single buffer
- * - If larger than max_blocks, split into chunks, offset
- * each nvme command accordingly.
- */
- for (i = 0; i < num_cmds; i++) {
- memset(&c, 0, sizeof(c));
- if (hdr->iovec_count > 0) {
- struct sg_iovec sgl;
-
- retcode = copy_from_user(&sgl, hdr->dxferp +
- i * sizeof(struct sg_iovec),
- sizeof(struct sg_iovec));
- if (retcode)
- return -EFAULT;
- unit_len = sgl.iov_len;
- unit_num_blocks = unit_len >> ns->lba_shift;
- next_mapping_addr = sgl.iov_base;
- } else {
- unit_num_blocks = min((u64)max_blocks,
- (cdb_info->xfer_len - nvme_offset));
- unit_len = unit_num_blocks << ns->lba_shift;
- next_mapping_addr = hdr->dxferp +
- ((1 << ns->lba_shift) * nvme_offset);
- }
-
- c.rw.opcode = opcode;
- c.rw.nsid = cpu_to_le32(ns->ns_id);
- c.rw.slba = cpu_to_le64(cdb_info->lba + nvme_offset);
- c.rw.length = cpu_to_le16(unit_num_blocks - 1);
- control = nvme_trans_io_get_control(ns, cdb_info);
- c.rw.control = cpu_to_le16(control);
-
- if (get_capacity(ns->disk) - unit_num_blocks <
- cdb_info->lba + nvme_offset) {
- nvme_sc = NVME_SC_LBA_RANGE;
- break;
- }
- nvme_sc = nvme_submit_user_cmd(ns->queue, &c,
- next_mapping_addr, unit_len, NULL, 0);
- if (nvme_sc)
- break;
-
- nvme_offset += unit_num_blocks;
- }
-
- return nvme_trans_status_code(hdr, nvme_sc);
-}
-
-
-/* SCSI Command Translation Functions */
-
-static int nvme_trans_io(struct nvme_ns *ns, struct sg_io_hdr *hdr, u8 is_write,
- u8 *cmd)
-{
- int res = 0;
- struct nvme_trans_io_cdb cdb_info = { 0, };
- u8 opcode = cmd[0];
- u64 xfer_bytes;
- u64 sum_iov_len = 0;
- struct sg_iovec sgl;
- int i;
- size_t not_copied;
-
- /*
- * The FUA and WPROTECT fields are not supported in 6-byte CDBs,
- * but always in the same place for all others.
- */
- switch (opcode) {
- case WRITE_6:
- case READ_6:
- break;
- default:
- cdb_info.fua = cmd[1] & 0x8;
- cdb_info.prot_info = (cmd[1] & 0xe0) >> 5;
- if (cdb_info.prot_info && !ns->pi_type) {
- return nvme_trans_completion(hdr,
- SAM_STAT_CHECK_CONDITION,
- ILLEGAL_REQUEST,
- SCSI_ASC_INVALID_CDB,
- SCSI_ASCQ_CAUSE_NOT_REPORTABLE);
- }
- }
-
- switch (opcode) {
- case WRITE_6:
- case READ_6:
- cdb_info.lba = get_unaligned_be24(&cmd[1]);
- cdb_info.xfer_len = cmd[4];
- if (cdb_info.xfer_len == 0)
- cdb_info.xfer_len = 256;
- break;
- case WRITE_10:
- case READ_10:
- cdb_info.lba = get_unaligned_be32(&cmd[2]);
- cdb_info.xfer_len = get_unaligned_be16(&cmd[7]);
- break;
- case WRITE_12:
- case READ_12:
- cdb_info.lba = get_unaligned_be32(&cmd[2]);
- cdb_info.xfer_len = get_unaligned_be32(&cmd[6]);
- break;
- case WRITE_16:
- case READ_16:
- cdb_info.lba = get_unaligned_be64(&cmd[2]);
- cdb_info.xfer_len = get_unaligned_be32(&cmd[10]);
- break;
- default:
- /* Will never really reach here */
- res = -EIO;
- goto out;
- }
-
- /* Calculate total length of transfer (in bytes) */
- if (hdr->iovec_count > 0) {
- for (i = 0; i < hdr->iovec_count; i++) {
- not_copied = copy_from_user(&sgl, hdr->dxferp +
- i * sizeof(struct sg_iovec),
- sizeof(struct sg_iovec));
- if (not_copied)
- return -EFAULT;
- sum_iov_len += sgl.iov_len;
- /* IO vector sizes should be multiples of block size */
- if (sgl.iov_len % (1 << ns->lba_shift) != 0) {
- res = nvme_trans_completion(hdr,
- SAM_STAT_CHECK_CONDITION,
- ILLEGAL_REQUEST,
- SCSI_ASC_INVALID_PARAMETER,
- SCSI_ASCQ_CAUSE_NOT_REPORTABLE);
- goto out;
- }
- }
- } else {
- sum_iov_len = hdr->dxfer_len;
- }
-
- /* As Per sg ioctl howto, if the lengths differ, use the lower one */
- xfer_bytes = min(((u64)hdr->dxfer_len), sum_iov_len);
-
- /* If block count and actual data buffer size dont match, error out */
- if (xfer_bytes != (cdb_info.xfer_len << ns->lba_shift)) {
- res = -EINVAL;
- goto out;
- }
-
- /* Check for 0 length transfer - it is not illegal */
- if (cdb_info.xfer_len == 0)
- goto out;
-
- /* Send NVMe IO Command(s) */
- res = nvme_trans_do_nvme_io(ns, hdr, &cdb_info, is_write);
- if (res)
- goto out;
-
- out:
- return res;
-}
-
-static int nvme_trans_inquiry(struct nvme_ns *ns, struct sg_io_hdr *hdr,
- u8 *cmd)
-{
- int res = 0;
- u8 evpd;
- u8 page_code;
- int alloc_len;
- u8 *inq_response;
-
- evpd = cmd[1] & 0x01;
- page_code = cmd[2];
- alloc_len = get_unaligned_be16(&cmd[3]);
-
- inq_response = kmalloc(max(alloc_len, STANDARD_INQUIRY_LENGTH),
- GFP_KERNEL);
- if (inq_response == NULL) {
- res = -ENOMEM;
- goto out_mem;
- }
-
- if (evpd == 0) {
- if (page_code == INQ_STANDARD_INQUIRY_PAGE) {
- res = nvme_trans_standard_inquiry_page(ns, hdr,
- inq_response, alloc_len);
- } else {
- res = nvme_trans_completion(hdr,
- SAM_STAT_CHECK_CONDITION,
- ILLEGAL_REQUEST,
- SCSI_ASC_INVALID_CDB,
- SCSI_ASCQ_CAUSE_NOT_REPORTABLE);
- }
- } else {
- switch (page_code) {
- case VPD_SUPPORTED_PAGES:
- res = nvme_trans_supported_vpd_pages(ns, hdr,
- inq_response, alloc_len);
- break;
- case VPD_SERIAL_NUMBER:
- res = nvme_trans_unit_serial_page(ns, hdr, inq_response,
- alloc_len);
- break;
- case VPD_DEVICE_IDENTIFIERS:
- res = nvme_trans_device_id_page(ns, hdr, inq_response,
- alloc_len);
- break;
- case VPD_EXTENDED_INQUIRY:
- res = nvme_trans_ext_inq_page(ns, hdr, alloc_len);
- break;
- case VPD_BLOCK_LIMITS:
- res = nvme_trans_bdev_limits_page(ns, hdr, inq_response,
- alloc_len);
- break;
- case VPD_BLOCK_DEV_CHARACTERISTICS:
- res = nvme_trans_bdev_char_page(ns, hdr, alloc_len);
- break;
- default:
- res = nvme_trans_completion(hdr,
- SAM_STAT_CHECK_CONDITION,
- ILLEGAL_REQUEST,
- SCSI_ASC_INVALID_CDB,
- SCSI_ASCQ_CAUSE_NOT_REPORTABLE);
- break;
- }
- }
- kfree(inq_response);
- out_mem:
- return res;
-}
-
-static int nvme_trans_log_sense(struct nvme_ns *ns, struct sg_io_hdr *hdr,
- u8 *cmd)
-{
- int res;
- u16 alloc_len;
- u8 pc;
- u8 page_code;
-
- if (cmd[1] != LOG_SENSE_CDB_SP_NOT_ENABLED) {
- res = nvme_trans_completion(hdr, SAM_STAT_CHECK_CONDITION,
- ILLEGAL_REQUEST, SCSI_ASC_INVALID_CDB,
- SCSI_ASCQ_CAUSE_NOT_REPORTABLE);
- goto out;
- }
-
- page_code = cmd[2] & LOG_SENSE_CDB_PAGE_CODE_MASK;
- pc = (cmd[2] & LOG_SENSE_CDB_PC_MASK) >> LOG_SENSE_CDB_PC_SHIFT;
- if (pc != LOG_SENSE_CDB_PC_CUMULATIVE_VALUES) {
- res = nvme_trans_completion(hdr, SAM_STAT_CHECK_CONDITION,
- ILLEGAL_REQUEST, SCSI_ASC_INVALID_CDB,
- SCSI_ASCQ_CAUSE_NOT_REPORTABLE);
- goto out;
- }
- alloc_len = get_unaligned_be16(&cmd[7]);
- switch (page_code) {
- case LOG_PAGE_SUPPORTED_LOG_PAGES_PAGE:
- res = nvme_trans_log_supp_pages(ns, hdr, alloc_len);
- break;
- case LOG_PAGE_INFORMATIONAL_EXCEPTIONS_PAGE:
- res = nvme_trans_log_info_exceptions(ns, hdr, alloc_len);
- break;
- case LOG_PAGE_TEMPERATURE_PAGE:
- res = nvme_trans_log_temperature(ns, hdr, alloc_len);
- break;
- default:
- res = nvme_trans_completion(hdr, SAM_STAT_CHECK_CONDITION,
- ILLEGAL_REQUEST, SCSI_ASC_INVALID_CDB,
- SCSI_ASCQ_CAUSE_NOT_REPORTABLE);
- break;
- }
-
- out:
- return res;
-}
-
-static int nvme_trans_mode_select(struct nvme_ns *ns, struct sg_io_hdr *hdr,
- u8 *cmd)
-{
- u8 cdb10 = 0;
- u16 parm_list_len;
- u8 page_format;
- u8 save_pages;
-
- page_format = cmd[1] & MODE_SELECT_CDB_PAGE_FORMAT_MASK;
- save_pages = cmd[1] & MODE_SELECT_CDB_SAVE_PAGES_MASK;
-
- if (cmd[0] == MODE_SELECT) {
- parm_list_len = cmd[4];
- } else {
- parm_list_len = cmd[7];
- cdb10 = 1;
- }
-
- if (parm_list_len != 0) {
- /*
- * According to SPC-4 r24, a paramter list length field of 0
- * shall not be considered an error
- */
- return nvme_trans_modesel_data(ns, hdr, cmd, parm_list_len,
- page_format, save_pages, cdb10);
- }
-
- return 0;
-}
-
-static int nvme_trans_mode_sense(struct nvme_ns *ns, struct sg_io_hdr *hdr,
- u8 *cmd)
-{
- int res = 0;
- u16 alloc_len;
- u8 cdb10 = 0;
-
- if (cmd[0] == MODE_SENSE) {
- alloc_len = cmd[4];
- } else {
- alloc_len = get_unaligned_be16(&cmd[7]);
- cdb10 = 1;
- }
-
- if ((cmd[2] & MODE_SENSE_PAGE_CONTROL_MASK) !=
- MODE_SENSE_PC_CURRENT_VALUES) {
- res = nvme_trans_completion(hdr, SAM_STAT_CHECK_CONDITION,
- ILLEGAL_REQUEST, SCSI_ASC_INVALID_CDB,
- SCSI_ASCQ_CAUSE_NOT_REPORTABLE);
- goto out;
- }
-
- switch (cmd[2] & MODE_SENSE_PAGE_CODE_MASK) {
- case MODE_PAGE_CACHING:
- res = nvme_trans_mode_page_create(ns, hdr, cmd, alloc_len,
- cdb10,
- &nvme_trans_fill_caching_page,
- MODE_PAGE_CACHING_LEN);
- break;
- case MODE_PAGE_CONTROL:
- res = nvme_trans_mode_page_create(ns, hdr, cmd, alloc_len,
- cdb10,
- &nvme_trans_fill_control_page,
- MODE_PAGE_CONTROL_LEN);
- break;
- case MODE_PAGE_POWER_CONDITION:
- res = nvme_trans_mode_page_create(ns, hdr, cmd, alloc_len,
- cdb10,
- &nvme_trans_fill_pow_cnd_page,
- MODE_PAGE_POW_CND_LEN);
- break;
- case MODE_PAGE_INFO_EXCEP:
- res = nvme_trans_mode_page_create(ns, hdr, cmd, alloc_len,
- cdb10,
- &nvme_trans_fill_inf_exc_page,
- MODE_PAGE_INF_EXC_LEN);
- break;
- case MODE_PAGE_RETURN_ALL:
- res = nvme_trans_mode_page_create(ns, hdr, cmd, alloc_len,
- cdb10,
- &nvme_trans_fill_all_pages,
- MODE_PAGE_ALL_LEN);
- break;
- default:
- res = nvme_trans_completion(hdr, SAM_STAT_CHECK_CONDITION,
- ILLEGAL_REQUEST, SCSI_ASC_INVALID_CDB,
- SCSI_ASCQ_CAUSE_NOT_REPORTABLE);
- break;
- }
-
- out:
- return res;
-}
-
-static int nvme_trans_read_capacity(struct nvme_ns *ns, struct sg_io_hdr *hdr,
- u8 *cmd, u8 cdb16)
-{
- int res;
- int nvme_sc;
- u32 alloc_len;
- u32 resp_size;
- u32 xfer_len;
- struct nvme_id_ns *id_ns;
- u8 *response;
-
- if (cdb16) {
- alloc_len = get_unaligned_be32(&cmd[10]);
- resp_size = READ_CAP_16_RESP_SIZE;
- } else {
- alloc_len = READ_CAP_10_RESP_SIZE;
- resp_size = READ_CAP_10_RESP_SIZE;
- }
-
- nvme_sc = nvme_identify_ns(ns->ctrl, ns->ns_id, &id_ns);
- res = nvme_trans_status_code(hdr, nvme_sc);
- if (res)
- return res;
-
- response = kzalloc(resp_size, GFP_KERNEL);
- if (response == NULL) {
- res = -ENOMEM;
- goto out_free_id;
- }
- nvme_trans_fill_read_cap(response, id_ns, cdb16);
-
- xfer_len = min(alloc_len, resp_size);
- res = nvme_trans_copy_to_user(hdr, response, xfer_len);
-
- kfree(response);
- out_free_id:
- kfree(id_ns);
- return res;
-}
-
-static int nvme_trans_report_luns(struct nvme_ns *ns, struct sg_io_hdr *hdr,
- u8 *cmd)
-{
- int res;
- int nvme_sc;
- u32 alloc_len, xfer_len, resp_size;
- u8 *response;
- struct nvme_id_ctrl *id_ctrl;
- u32 ll_length, lun_id;
- u8 lun_id_offset = REPORT_LUNS_FIRST_LUN_OFFSET;
- __be32 tmp_len;
-
- switch (cmd[2]) {
- default:
- return nvme_trans_completion(hdr, SAM_STAT_CHECK_CONDITION,
- ILLEGAL_REQUEST, SCSI_ASC_INVALID_CDB,
- SCSI_ASCQ_CAUSE_NOT_REPORTABLE);
- case ALL_LUNS_RETURNED:
- case ALL_WELL_KNOWN_LUNS_RETURNED:
- case RESTRICTED_LUNS_RETURNED:
- nvme_sc = nvme_identify_ctrl(ns->ctrl, &id_ctrl);
- res = nvme_trans_status_code(hdr, nvme_sc);
- if (res)
- return res;
-
- ll_length = le32_to_cpu(id_ctrl->nn) * LUN_ENTRY_SIZE;
- resp_size = ll_length + LUN_DATA_HEADER_SIZE;
-
- alloc_len = get_unaligned_be32(&cmd[6]);
- if (alloc_len < resp_size) {
- res = nvme_trans_completion(hdr,
- SAM_STAT_CHECK_CONDITION,
- ILLEGAL_REQUEST, SCSI_ASC_INVALID_CDB,
- SCSI_ASCQ_CAUSE_NOT_REPORTABLE);
- goto out_free_id;
- }
-
- response = kzalloc(resp_size, GFP_KERNEL);
- if (response == NULL) {
- res = -ENOMEM;
- goto out_free_id;
- }
-
- /* The first LUN ID will always be 0 per the SAM spec */
- for (lun_id = 0; lun_id < le32_to_cpu(id_ctrl->nn); lun_id++) {
- /*
- * Set the LUN Id and then increment to the next LUN
- * location in the parameter data.
- */
- __be64 tmp_id = cpu_to_be64(lun_id);
- memcpy(&response[lun_id_offset], &tmp_id, sizeof(u64));
- lun_id_offset += LUN_ENTRY_SIZE;
- }
- tmp_len = cpu_to_be32(ll_length);
- memcpy(response, &tmp_len, sizeof(u32));
- }
-
- xfer_len = min(alloc_len, resp_size);
- res = nvme_trans_copy_to_user(hdr, response, xfer_len);
-
- kfree(response);
- out_free_id:
- kfree(id_ctrl);
- return res;
-}
-
-static int nvme_trans_request_sense(struct nvme_ns *ns, struct sg_io_hdr *hdr,
- u8 *cmd)
-{
- int res;
- u8 alloc_len, xfer_len, resp_size;
- u8 desc_format;
- u8 *response;
-
- desc_format = cmd[1] & 0x01;
- alloc_len = cmd[4];
-
- resp_size = ((desc_format) ? (DESC_FMT_SENSE_DATA_SIZE) :
- (FIXED_FMT_SENSE_DATA_SIZE));
- response = kzalloc(resp_size, GFP_KERNEL);
- if (response == NULL) {
- res = -ENOMEM;
- goto out;
- }
-
- if (desc_format) {
- /* Descriptor Format Sense Data */
- response[0] = DESC_FORMAT_SENSE_DATA;
- response[1] = NO_SENSE;
- /* TODO How is LOW POWER CONDITION ON handled? (byte 2) */
- response[2] = SCSI_ASC_NO_SENSE;
- response[3] = SCSI_ASCQ_CAUSE_NOT_REPORTABLE;
- /* SDAT_OVFL = 0 | Additional Sense Length = 0 */
- } else {
- /* Fixed Format Sense Data */
- response[0] = FIXED_SENSE_DATA;
- /* Byte 1 = Obsolete */
- response[2] = NO_SENSE; /* FM, EOM, ILI, SDAT_OVFL = 0 */
- /* Bytes 3-6 - Information - set to zero */
- response[7] = FIXED_SENSE_DATA_ADD_LENGTH;
- /* Bytes 8-11 - Cmd Specific Information - set to zero */
- response[12] = SCSI_ASC_NO_SENSE;
- response[13] = SCSI_ASCQ_CAUSE_NOT_REPORTABLE;
- /* Byte 14 = Field Replaceable Unit Code = 0 */
- /* Bytes 15-17 - SKSV=0; Sense Key Specific = 0 */
- }
-
- xfer_len = min(alloc_len, resp_size);
- res = nvme_trans_copy_to_user(hdr, response, xfer_len);
-
- kfree(response);
- out:
- return res;
-}
-
-static int nvme_trans_synchronize_cache(struct nvme_ns *ns,
- struct sg_io_hdr *hdr)
-{
- int nvme_sc;
- struct nvme_command c;
-
- memset(&c, 0, sizeof(c));
- c.common.opcode = nvme_cmd_flush;
- c.common.nsid = cpu_to_le32(ns->ns_id);
-
- nvme_sc = nvme_submit_sync_cmd(ns->queue, &c, NULL, 0);
- return nvme_trans_status_code(hdr, nvme_sc);
-}
-
-static int nvme_trans_format_unit(struct nvme_ns *ns, struct sg_io_hdr *hdr,
- u8 *cmd)
-{
- int res;
- u8 parm_hdr_len = 0;
- u8 nvme_pf_code = 0;
- u8 format_prot_info, long_list, format_data;
-
- format_prot_info = (cmd[1] & 0xc0) >> 6;
- long_list = cmd[1] & 0x20;
- format_data = cmd[1] & 0x10;
-
- if (format_data != 0) {
- if (format_prot_info != 0) {
- if (long_list == 0)
- parm_hdr_len = FORMAT_UNIT_SHORT_PARM_LIST_LEN;
- else
- parm_hdr_len = FORMAT_UNIT_LONG_PARM_LIST_LEN;
- }
- } else if (format_data == 0 && format_prot_info != 0) {
- res = nvme_trans_completion(hdr, SAM_STAT_CHECK_CONDITION,
- ILLEGAL_REQUEST, SCSI_ASC_INVALID_CDB,
- SCSI_ASCQ_CAUSE_NOT_REPORTABLE);
- goto out;
- }
-
- /* Get parm header from data-in/out buffer */
- /*
- * According to the translation spec, the only fields in the parameter
- * list we are concerned with are in the header. So allocate only that.
- */
- if (parm_hdr_len > 0) {
- res = nvme_trans_fmt_get_parm_header(hdr, parm_hdr_len,
- format_prot_info, &nvme_pf_code);
- if (res)
- goto out;
- }
-
- /* Attempt to activate any previously downloaded firmware image */
- res = nvme_trans_send_activate_fw_cmd(ns, hdr, 0);
-
- /* Determine Block size and count and send format command */
- res = nvme_trans_fmt_set_blk_size_count(ns, hdr);
- if (res)
- goto out;
-
- res = nvme_trans_fmt_send_cmd(ns, hdr, nvme_pf_code);
-
- out:
- return res;
-}
-
-static int nvme_trans_test_unit_ready(struct nvme_ns *ns,
- struct sg_io_hdr *hdr,
- u8 *cmd)
-{
- if (nvme_ctrl_ready(ns->ctrl))
- return nvme_trans_completion(hdr, SAM_STAT_CHECK_CONDITION,
- NOT_READY, SCSI_ASC_LUN_NOT_READY,
- SCSI_ASCQ_CAUSE_NOT_REPORTABLE);
- else
- return nvme_trans_completion(hdr, SAM_STAT_GOOD, NO_SENSE, 0, 0);
-}
-
-static int nvme_trans_write_buffer(struct nvme_ns *ns, struct sg_io_hdr *hdr,
- u8 *cmd)
-{
- int res = 0;
- u32 buffer_offset, parm_list_length;
- u8 buffer_id, mode;
-
- parm_list_length = get_unaligned_be24(&cmd[6]);
- if (parm_list_length % BYTES_TO_DWORDS != 0) {
- /* NVMe expects Firmware file to be a whole number of DWORDS */
- res = nvme_trans_completion(hdr, SAM_STAT_CHECK_CONDITION,
- ILLEGAL_REQUEST, SCSI_ASC_INVALID_CDB,
- SCSI_ASCQ_CAUSE_NOT_REPORTABLE);
- goto out;
- }
- buffer_id = cmd[2];
- if (buffer_id > NVME_MAX_FIRMWARE_SLOT) {
- res = nvme_trans_completion(hdr, SAM_STAT_CHECK_CONDITION,
- ILLEGAL_REQUEST, SCSI_ASC_INVALID_CDB,
- SCSI_ASCQ_CAUSE_NOT_REPORTABLE);
- goto out;
- }
- mode = cmd[1] & 0x1f;
- buffer_offset = get_unaligned_be24(&cmd[3]);
-
- switch (mode) {
- case DOWNLOAD_SAVE_ACTIVATE:
- res = nvme_trans_send_download_fw_cmd(ns, hdr, nvme_admin_download_fw,
- parm_list_length, buffer_offset,
- buffer_id);
- if (res)
- goto out;
- res = nvme_trans_send_activate_fw_cmd(ns, hdr, buffer_id);
- break;
- case DOWNLOAD_SAVE_DEFER_ACTIVATE:
- res = nvme_trans_send_download_fw_cmd(ns, hdr, nvme_admin_download_fw,
- parm_list_length, buffer_offset,
- buffer_id);
- break;
- case ACTIVATE_DEFERRED_MICROCODE:
- res = nvme_trans_send_activate_fw_cmd(ns, hdr, buffer_id);
- break;
- default:
- res = nvme_trans_completion(hdr, SAM_STAT_CHECK_CONDITION,
- ILLEGAL_REQUEST, SCSI_ASC_INVALID_CDB,
- SCSI_ASCQ_CAUSE_NOT_REPORTABLE);
- break;
- }
-
- out:
- return res;
-}
-
-struct scsi_unmap_blk_desc {
- __be64 slba;
- __be32 nlb;
- u32 resv;
-};
-
-struct scsi_unmap_parm_list {
- __be16 unmap_data_len;
- __be16 unmap_blk_desc_data_len;
- u32 resv;
- struct scsi_unmap_blk_desc desc[0];
-};
-
-static int nvme_trans_unmap(struct nvme_ns *ns, struct sg_io_hdr *hdr,
- u8 *cmd)
-{
- struct scsi_unmap_parm_list *plist;
- struct nvme_dsm_range *range;
- struct nvme_command c;
- int i, nvme_sc, res;
- u16 ndesc, list_len;
-
- list_len = get_unaligned_be16(&cmd[7]);
- if (!list_len)
- return -EINVAL;
-
- plist = kmalloc(list_len, GFP_KERNEL);
- if (!plist)
- return -ENOMEM;
-
- res = nvme_trans_copy_from_user(hdr, plist, list_len);
- if (res)
- goto out;
-
- ndesc = be16_to_cpu(plist->unmap_blk_desc_data_len) >> 4;
- if (!ndesc || ndesc > 256) {
- res = -EINVAL;
- goto out;
- }
-
- range = kcalloc(ndesc, sizeof(*range), GFP_KERNEL);
- if (!range) {
- res = -ENOMEM;
- goto out;
- }
-
- for (i = 0; i < ndesc; i++) {
- range[i].nlb = cpu_to_le32(be32_to_cpu(plist->desc[i].nlb));
- range[i].slba = cpu_to_le64(be64_to_cpu(plist->desc[i].slba));
- range[i].cattr = 0;
- }
-
- memset(&c, 0, sizeof(c));
- c.dsm.opcode = nvme_cmd_dsm;
- c.dsm.nsid = cpu_to_le32(ns->ns_id);
- c.dsm.nr = cpu_to_le32(ndesc - 1);
- c.dsm.attributes = cpu_to_le32(NVME_DSMGMT_AD);
-
- nvme_sc = nvme_submit_sync_cmd(ns->queue, &c, range,
- ndesc * sizeof(*range));
- res = nvme_trans_status_code(hdr, nvme_sc);
-
- kfree(range);
- out:
- kfree(plist);
- return res;
-}
-
-static int nvme_scsi_translate(struct nvme_ns *ns, struct sg_io_hdr *hdr)
-{
- u8 cmd[16];
- int retcode;
- unsigned int opcode;
-
- if (hdr->cmdp == NULL)
- return -EMSGSIZE;
- if (hdr->cmd_len > sizeof(cmd))
- return -EINVAL;
- if (copy_from_user(cmd, hdr->cmdp, hdr->cmd_len))
- return -EFAULT;
-
- /*
- * Prime the hdr with good status for scsi commands that don't require
- * an nvme command for translation.
- */
- retcode = nvme_trans_status_code(hdr, NVME_SC_SUCCESS);
- if (retcode)
- return retcode;
-
- opcode = cmd[0];
-
- switch (opcode) {
- case READ_6:
- case READ_10:
- case READ_12:
- case READ_16:
- retcode = nvme_trans_io(ns, hdr, 0, cmd);
- break;
- case WRITE_6:
- case WRITE_10:
- case WRITE_12:
- case WRITE_16:
- retcode = nvme_trans_io(ns, hdr, 1, cmd);
- break;
- case INQUIRY:
- retcode = nvme_trans_inquiry(ns, hdr, cmd);
- break;
- case LOG_SENSE:
- retcode = nvme_trans_log_sense(ns, hdr, cmd);
- break;
- case MODE_SELECT:
- case MODE_SELECT_10:
- retcode = nvme_trans_mode_select(ns, hdr, cmd);
- break;
- case MODE_SENSE:
- case MODE_SENSE_10:
- retcode = nvme_trans_mode_sense(ns, hdr, cmd);
- break;
- case READ_CAPACITY:
- retcode = nvme_trans_read_capacity(ns, hdr, cmd, 0);
- break;
- case SERVICE_ACTION_IN_16:
- switch (cmd[1]) {
- case SAI_READ_CAPACITY_16:
- retcode = nvme_trans_read_capacity(ns, hdr, cmd, 1);
- break;
- default:
- goto out;
- }
- break;
- case REPORT_LUNS:
- retcode = nvme_trans_report_luns(ns, hdr, cmd);
- break;
- case REQUEST_SENSE:
- retcode = nvme_trans_request_sense(ns, hdr, cmd);
- break;
- case SYNCHRONIZE_CACHE:
- retcode = nvme_trans_synchronize_cache(ns, hdr);
- break;
- case FORMAT_UNIT:
- retcode = nvme_trans_format_unit(ns, hdr, cmd);
- break;
- case TEST_UNIT_READY:
- retcode = nvme_trans_test_unit_ready(ns, hdr, cmd);
- break;
- case WRITE_BUFFER:
- retcode = nvme_trans_write_buffer(ns, hdr, cmd);
- break;
- case UNMAP:
- retcode = nvme_trans_unmap(ns, hdr, cmd);
- break;
- default:
- out:
- retcode = nvme_trans_completion(hdr, SAM_STAT_CHECK_CONDITION,
- ILLEGAL_REQUEST, SCSI_ASC_ILLEGAL_COMMAND,
- SCSI_ASCQ_CAUSE_NOT_REPORTABLE);
- break;
- }
- return retcode;
-}
-
-int nvme_sg_io(struct nvme_ns *ns, struct sg_io_hdr __user *u_hdr)
-{
- struct sg_io_hdr hdr;
- int retcode;
-
- if (!capable(CAP_SYS_ADMIN))
- return -EACCES;
- if (copy_from_user(&hdr, u_hdr, sizeof(hdr)))
- return -EFAULT;
- if (hdr.interface_id != 'S')
- return -EINVAL;
-
- /*
- * A positive return code means a NVMe status, which has been
- * translated to sense data.
- */
- retcode = nvme_scsi_translate(ns, &hdr);
- if (retcode < 0)
- return retcode;
- if (copy_to_user(u_hdr, &hdr, sizeof(sg_io_hdr_t)) > 0)
- return -EFAULT;
- return 0;
-}
-
-int nvme_sg_get_version_num(int __user *ip)
-{
- return put_user(sg_version_num, ip);
-}
diff --git a/drivers/nvme/target/admin-cmd.c b/drivers/nvme/target/admin-cmd.c
index ff1f97006322..35f930db3c02 100644
--- a/drivers/nvme/target/admin-cmd.c
+++ b/drivers/nvme/target/admin-cmd.c
@@ -336,7 +336,7 @@ out:
static void nvmet_execute_identify_nslist(struct nvmet_req *req)
{
- static const int buf_size = 4096;
+ static const int buf_size = NVME_IDENTIFY_DATA_SIZE;
struct nvmet_ctrl *ctrl = req->sq->ctrl;
struct nvmet_ns *ns;
u32 min_nsid = le32_to_cpu(req->cmd->identify.nsid);
@@ -367,6 +367,64 @@ out:
nvmet_req_complete(req, status);
}
+static u16 nvmet_copy_ns_identifier(struct nvmet_req *req, u8 type, u8 len,
+ void *id, off_t *off)
+{
+ struct nvme_ns_id_desc desc = {
+ .nidt = type,
+ .nidl = len,
+ };
+ u16 status;
+
+ status = nvmet_copy_to_sgl(req, *off, &desc, sizeof(desc));
+ if (status)
+ return status;
+ *off += sizeof(desc);
+
+ status = nvmet_copy_to_sgl(req, *off, id, len);
+ if (status)
+ return status;
+ *off += len;
+
+ return 0;
+}
+
+static void nvmet_execute_identify_desclist(struct nvmet_req *req)
+{
+ struct nvmet_ns *ns;
+ u16 status = 0;
+ off_t off = 0;
+
+ ns = nvmet_find_namespace(req->sq->ctrl, req->cmd->identify.nsid);
+ if (!ns) {
+ status = NVME_SC_INVALID_NS | NVME_SC_DNR;
+ goto out;
+ }
+
+ if (memchr_inv(&ns->uuid, 0, sizeof(ns->uuid))) {
+ status = nvmet_copy_ns_identifier(req, NVME_NIDT_UUID,
+ NVME_NIDT_UUID_LEN,
+ &ns->uuid, &off);
+ if (status)
+ goto out_put_ns;
+ }
+ if (memchr_inv(ns->nguid, 0, sizeof(ns->nguid))) {
+ status = nvmet_copy_ns_identifier(req, NVME_NIDT_NGUID,
+ NVME_NIDT_NGUID_LEN,
+ &ns->nguid, &off);
+ if (status)
+ goto out_put_ns;
+ }
+
+ if (sg_zero_buffer(req->sg, req->sg_cnt, NVME_IDENTIFY_DATA_SIZE - off,
+ off) != NVME_IDENTIFY_DATA_SIZE - off)
+ status = NVME_SC_INTERNAL | NVME_SC_DNR;
+out_put_ns:
+ nvmet_put_namespace(ns);
+out:
+ nvmet_req_complete(req, status);
+}
+
/*
* A "mimimum viable" abort implementation: the command is mandatory in the
* spec, but we are not required to do any useful work. We couldn't really
@@ -504,7 +562,7 @@ u16 nvmet_parse_admin_cmd(struct nvmet_req *req)
}
break;
case nvme_admin_identify:
- req->data_len = 4096;
+ req->data_len = NVME_IDENTIFY_DATA_SIZE;
switch (cmd->identify.cns) {
case NVME_ID_CNS_NS:
req->execute = nvmet_execute_identify_ns;
@@ -515,6 +573,9 @@ u16 nvmet_parse_admin_cmd(struct nvmet_req *req)
case NVME_ID_CNS_NS_ACTIVE_LIST:
req->execute = nvmet_execute_identify_nslist;
return 0;
+ case NVME_ID_CNS_NS_DESC_LIST:
+ req->execute = nvmet_execute_identify_desclist;
+ return 0;
}
break;
case nvme_admin_abort_cmd:
diff --git a/drivers/nvme/target/configfs.c b/drivers/nvme/target/configfs.c
index be8c800078e2..a358ecd93e11 100644
--- a/drivers/nvme/target/configfs.c
+++ b/drivers/nvme/target/configfs.c
@@ -305,11 +305,41 @@ out_unlock:
CONFIGFS_ATTR(nvmet_ns_, device_path);
+static ssize_t nvmet_ns_device_uuid_show(struct config_item *item, char *page)
+{
+ return sprintf(page, "%pUb\n", &to_nvmet_ns(item)->uuid);
+}
+
+static ssize_t nvmet_ns_device_uuid_store(struct config_item *item,
+ const char *page, size_t count)
+{
+ struct nvmet_ns *ns = to_nvmet_ns(item);
+ struct nvmet_subsys *subsys = ns->subsys;
+ int ret = 0;
+
+
+ mutex_lock(&subsys->lock);
+ if (ns->enabled) {
+ ret = -EBUSY;
+ goto out_unlock;
+ }
+
+
+ if (uuid_parse(page, &ns->uuid))
+ ret = -EINVAL;
+
+out_unlock:
+ mutex_unlock(&subsys->lock);
+ return ret ? ret : count;
+}
+
static ssize_t nvmet_ns_device_nguid_show(struct config_item *item, char *page)
{
return sprintf(page, "%pUb\n", &to_nvmet_ns(item)->nguid);
}
+CONFIGFS_ATTR(nvmet_ns_, device_uuid);
+
static ssize_t nvmet_ns_device_nguid_store(struct config_item *item,
const char *page, size_t count)
{
@@ -379,6 +409,7 @@ CONFIGFS_ATTR(nvmet_ns_, enable);
static struct configfs_attribute *nvmet_ns_attrs[] = {
&nvmet_ns_attr_device_path,
&nvmet_ns_attr_device_nguid,
+ &nvmet_ns_attr_device_uuid,
&nvmet_ns_attr_enable,
NULL,
};
@@ -619,8 +650,45 @@ out_unlock:
CONFIGFS_ATTR(nvmet_subsys_, attr_allow_any_host);
+static ssize_t nvmet_subsys_version_show(struct config_item *item,
+ char *page)
+{
+ struct nvmet_subsys *subsys = to_subsys(item);
+
+ if (NVME_TERTIARY(subsys->ver))
+ return snprintf(page, PAGE_SIZE, "%d.%d.%d\n",
+ (int)NVME_MAJOR(subsys->ver),
+ (int)NVME_MINOR(subsys->ver),
+ (int)NVME_TERTIARY(subsys->ver));
+ else
+ return snprintf(page, PAGE_SIZE, "%d.%d\n",
+ (int)NVME_MAJOR(subsys->ver),
+ (int)NVME_MINOR(subsys->ver));
+}
+
+static ssize_t nvmet_subsys_version_store(struct config_item *item,
+ const char *page, size_t count)
+{
+ struct nvmet_subsys *subsys = to_subsys(item);
+ int major, minor, tertiary = 0;
+ int ret;
+
+
+ ret = sscanf(page, "%d.%d.%d\n", &major, &minor, &tertiary);
+ if (ret != 2 && ret != 3)
+ return -EINVAL;
+
+ down_write(&nvmet_config_sem);
+ subsys->ver = NVME_VS(major, minor, tertiary);
+ up_write(&nvmet_config_sem);
+
+ return count;
+}
+CONFIGFS_ATTR(nvmet_subsys_, version);
+
static struct configfs_attribute *nvmet_subsys_attrs[] = {
&nvmet_subsys_attr_attr_allow_any_host,
+ &nvmet_subsys_attr_version,
NULL,
};
diff --git a/drivers/nvme/target/core.c b/drivers/nvme/target/core.c
index eb9399ac97cf..b5b4ac103748 100644
--- a/drivers/nvme/target/core.c
+++ b/drivers/nvme/target/core.c
@@ -380,6 +380,7 @@ struct nvmet_ns *nvmet_ns_alloc(struct nvmet_subsys *subsys, u32 nsid)
ns->nsid = nsid;
ns->subsys = subsys;
+ uuid_gen(&ns->uuid);
return ns;
}
@@ -926,7 +927,7 @@ struct nvmet_subsys *nvmet_subsys_alloc(const char *subsysnqn,
if (!subsys)
return NULL;
- subsys->ver = NVME_VS(1, 2, 1); /* NVMe 1.2.1 */
+ subsys->ver = NVME_VS(1, 3, 0); /* NVMe 1.3.0 */
switch (type) {
case NVME_NQN_NVME:
diff --git a/drivers/nvme/target/discovery.c b/drivers/nvme/target/discovery.c
index 1aaf597e81fc..8f3b57b4c97b 100644
--- a/drivers/nvme/target/discovery.c
+++ b/drivers/nvme/target/discovery.c
@@ -53,7 +53,7 @@ static void nvmet_format_discovery_entry(struct nvmf_disc_rsp_page_hdr *hdr,
e->portid = port->disc_addr.portid;
/* we support only dynamic controllers */
e->cntlid = cpu_to_le16(NVME_CNTLID_DYNAMIC);
- e->asqsz = cpu_to_le16(NVMF_AQ_DEPTH);
+ e->asqsz = cpu_to_le16(NVME_AQ_DEPTH);
e->subtype = type;
memcpy(e->trsvcid, port->disc_addr.trsvcid, NVMF_TRSVCID_SIZE);
memcpy(e->traddr, port->disc_addr.traddr, NVMF_TRADDR_SIZE);
@@ -185,7 +185,7 @@ u16 nvmet_parse_discovery_cmd(struct nvmet_req *req)
return NVME_SC_INVALID_OPCODE | NVME_SC_DNR;
}
case nvme_admin_identify:
- req->data_len = 4096;
+ req->data_len = NVME_IDENTIFY_DATA_SIZE;
switch (cmd->identify.cns) {
case NVME_ID_CNS_CTRL:
req->execute =
diff --git a/drivers/nvme/target/fc.c b/drivers/nvme/target/fc.c
index 2006fae61980..7692a96c9065 100644
--- a/drivers/nvme/target/fc.c
+++ b/drivers/nvme/target/fc.c
@@ -2096,20 +2096,22 @@ nvmet_fc_handle_fcp_rqst(struct nvmet_fc_tgtport *tgtport,
/* clear any response payload */
memset(&fod->rspiubuf, 0, sizeof(fod->rspiubuf));
+ fod->data_sg = NULL;
+ fod->data_sg_cnt = 0;
+
ret = nvmet_req_init(&fod->req,
&fod->queue->nvme_cq,
&fod->queue->nvme_sq,
&nvmet_fc_tgt_fcp_ops);
- if (!ret) { /* bad SQE content or invalid ctrl state */
- nvmet_fc_abort_op(tgtport, fod);
+ if (!ret) {
+ /* bad SQE content or invalid ctrl state */
+ /* nvmet layer has already called op done to send rsp. */
return;
}
/* keep a running counter of tail position */
atomic_inc(&fod->queue->sqtail);
- fod->data_sg = NULL;
- fod->data_sg_cnt = 0;
if (fod->total_length) {
ret = nvmet_fc_alloc_tgt_pgs(fod);
if (ret) {
diff --git a/drivers/nvme/target/fcloop.c b/drivers/nvme/target/fcloop.c
index 294a6611fb24..1bb9d5b311b1 100644
--- a/drivers/nvme/target/fcloop.c
+++ b/drivers/nvme/target/fcloop.c
@@ -569,7 +569,6 @@ fcloop_tgt_fcp_abort(struct nvmet_fc_target_port *tgtport,
struct nvmefc_tgt_fcp_req *tgt_fcpreq)
{
struct fcloop_fcpreq *tfcp_req = tgt_fcp_req_to_fcpreq(tgt_fcpreq);
- int active;
/*
* mark aborted only in case there were 2 threads in transport
@@ -577,7 +576,6 @@ fcloop_tgt_fcp_abort(struct nvmet_fc_target_port *tgtport,
* after the abort request
*/
spin_lock(&tfcp_req->reqlock);
- active = tfcp_req->active;
tfcp_req->aborted = true;
spin_unlock(&tfcp_req->reqlock);
diff --git a/drivers/nvme/target/io-cmd.c b/drivers/nvme/target/io-cmd.c
index c77940d80fc8..40128793e613 100644
--- a/drivers/nvme/target/io-cmd.c
+++ b/drivers/nvme/target/io-cmd.c
@@ -21,7 +21,7 @@ static void nvmet_bio_done(struct bio *bio)
struct nvmet_req *req = bio->bi_private;
nvmet_req_complete(req,
- bio->bi_error ? NVME_SC_INTERNAL | NVME_SC_DNR : 0);
+ bio->bi_status ? NVME_SC_INTERNAL | NVME_SC_DNR : 0);
if (bio != &req->inline_bio)
bio_put(bio);
@@ -145,7 +145,7 @@ static void nvmet_execute_discard(struct nvmet_req *req)
bio->bi_private = req;
bio->bi_end_io = nvmet_bio_done;
if (status) {
- bio->bi_error = -EIO;
+ bio->bi_status = BLK_STS_IOERR;
bio_endio(bio);
} else {
submit_bio(bio);
diff --git a/drivers/nvme/target/loop.c b/drivers/nvme/target/loop.c
index feb497134aee..5f55c683b338 100644
--- a/drivers/nvme/target/loop.c
+++ b/drivers/nvme/target/loop.c
@@ -21,8 +21,6 @@
#include "../host/nvme.h"
#include "../host/fabrics.h"
-#define NVME_LOOP_AQ_DEPTH 256
-
#define NVME_LOOP_MAX_SEGMENTS 256
/*
@@ -31,7 +29,7 @@
*/
#define NVME_LOOP_NR_AEN_COMMANDS 1
#define NVME_LOOP_AQ_BLKMQ_DEPTH \
- (NVME_LOOP_AQ_DEPTH - NVME_LOOP_NR_AEN_COMMANDS)
+ (NVME_AQ_DEPTH - NVME_LOOP_NR_AEN_COMMANDS)
struct nvme_loop_iod {
struct nvme_request nvme_req;
@@ -45,7 +43,6 @@ struct nvme_loop_iod {
};
struct nvme_loop_ctrl {
- spinlock_t lock;
struct nvme_loop_queue *queues;
u32 queue_count;
@@ -59,7 +56,6 @@ struct nvme_loop_ctrl {
struct nvmet_ctrl *target_ctrl;
struct work_struct delete_work;
- struct work_struct reset_work;
};
static inline struct nvme_loop_ctrl *to_loop_ctrl(struct nvme_ctrl *ctrl)
@@ -151,7 +147,7 @@ nvme_loop_timeout(struct request *rq, bool reserved)
struct nvme_loop_iod *iod = blk_mq_rq_to_pdu(rq);
/* queue error recovery */
- schedule_work(&iod->queue->ctrl->reset_work);
+ nvme_reset_ctrl(&iod->queue->ctrl->ctrl);
/* fail with DNR on admin cmd timeout */
nvme_req(rq)->status = NVME_SC_ABORT_REQ | NVME_SC_DNR;
@@ -159,17 +155,17 @@ nvme_loop_timeout(struct request *rq, bool reserved)
return BLK_EH_HANDLED;
}
-static int nvme_loop_queue_rq(struct blk_mq_hw_ctx *hctx,
+static blk_status_t nvme_loop_queue_rq(struct blk_mq_hw_ctx *hctx,
const struct blk_mq_queue_data *bd)
{
struct nvme_ns *ns = hctx->queue->queuedata;
struct nvme_loop_queue *queue = hctx->driver_data;
struct request *req = bd->rq;
struct nvme_loop_iod *iod = blk_mq_rq_to_pdu(req);
- int ret;
+ blk_status_t ret;
ret = nvme_setup_cmd(ns, req, &iod->cmd);
- if (ret != BLK_MQ_RQ_QUEUE_OK)
+ if (ret)
return ret;
iod->cmd.common.flags |= NVME_CMD_SGL_METABUF;
@@ -179,16 +175,15 @@ static int nvme_loop_queue_rq(struct blk_mq_hw_ctx *hctx,
nvme_cleanup_cmd(req);
blk_mq_start_request(req);
nvme_loop_queue_response(&iod->req);
- return BLK_MQ_RQ_QUEUE_OK;
+ return BLK_STS_OK;
}
if (blk_rq_bytes(req)) {
iod->sg_table.sgl = iod->first_sgl;
- ret = sg_alloc_table_chained(&iod->sg_table,
+ if (sg_alloc_table_chained(&iod->sg_table,
blk_rq_nr_phys_segments(req),
- iod->sg_table.sgl);
- if (ret)
- return BLK_MQ_RQ_QUEUE_BUSY;
+ iod->sg_table.sgl))
+ return BLK_STS_RESOURCE;
iod->req.sg = iod->sg_table.sgl;
iod->req.sg_cnt = blk_rq_map_sg(req->q, req, iod->sg_table.sgl);
@@ -197,7 +192,7 @@ static int nvme_loop_queue_rq(struct blk_mq_hw_ctx *hctx,
blk_mq_start_request(req);
schedule_work(&iod->work);
- return BLK_MQ_RQ_QUEUE_OK;
+ return BLK_STS_OK;
}
static void nvme_loop_submit_async_event(struct nvme_ctrl *arg, int aer_idx)
@@ -234,15 +229,10 @@ static int nvme_loop_init_request(struct blk_mq_tag_set *set,
struct request *req, unsigned int hctx_idx,
unsigned int numa_node)
{
- return nvme_loop_init_iod(set->driver_data, blk_mq_rq_to_pdu(req),
- hctx_idx + 1);
-}
+ struct nvme_loop_ctrl *ctrl = set->driver_data;
-static int nvme_loop_init_admin_request(struct blk_mq_tag_set *set,
- struct request *req, unsigned int hctx_idx,
- unsigned int numa_node)
-{
- return nvme_loop_init_iod(set->driver_data, blk_mq_rq_to_pdu(req), 0);
+ return nvme_loop_init_iod(ctrl, blk_mq_rq_to_pdu(req),
+ (set == &ctrl->tag_set) ? hctx_idx + 1 : 0);
}
static int nvme_loop_init_hctx(struct blk_mq_hw_ctx *hctx, void *data,
@@ -280,7 +270,7 @@ static const struct blk_mq_ops nvme_loop_mq_ops = {
static const struct blk_mq_ops nvme_loop_admin_mq_ops = {
.queue_rq = nvme_loop_queue_rq,
.complete = nvme_loop_complete_rq,
- .init_request = nvme_loop_init_admin_request,
+ .init_request = nvme_loop_init_request,
.init_hctx = nvme_loop_init_admin_hctx,
.timeout = nvme_loop_timeout,
};
@@ -467,7 +457,7 @@ static int __nvme_loop_del_ctrl(struct nvme_loop_ctrl *ctrl)
if (!nvme_change_ctrl_state(&ctrl->ctrl, NVME_CTRL_DELETING))
return -EBUSY;
- if (!schedule_work(&ctrl->delete_work))
+ if (!queue_work(nvme_wq, &ctrl->delete_work))
return -EBUSY;
return 0;
@@ -501,8 +491,8 @@ static void nvme_loop_delete_ctrl(struct nvmet_ctrl *nctrl)
static void nvme_loop_reset_ctrl_work(struct work_struct *work)
{
- struct nvme_loop_ctrl *ctrl = container_of(work,
- struct nvme_loop_ctrl, reset_work);
+ struct nvme_loop_ctrl *ctrl =
+ container_of(work, struct nvme_loop_ctrl, ctrl.reset_work);
bool changed;
int ret;
@@ -540,33 +530,16 @@ out_disable:
nvme_put_ctrl(&ctrl->ctrl);
}
-static int nvme_loop_reset_ctrl(struct nvme_ctrl *nctrl)
-{
- struct nvme_loop_ctrl *ctrl = to_loop_ctrl(nctrl);
-
- if (!nvme_change_ctrl_state(&ctrl->ctrl, NVME_CTRL_RESETTING))
- return -EBUSY;
-
- if (!schedule_work(&ctrl->reset_work))
- return -EBUSY;
-
- flush_work(&ctrl->reset_work);
-
- return 0;
-}
-
static const struct nvme_ctrl_ops nvme_loop_ctrl_ops = {
.name = "loop",
.module = THIS_MODULE,
- .is_fabrics = true,
+ .flags = NVME_F_FABRICS,
.reg_read32 = nvmf_reg_read32,
.reg_read64 = nvmf_reg_read64,
.reg_write32 = nvmf_reg_write32,
- .reset_ctrl = nvme_loop_reset_ctrl,
.free_ctrl = nvme_loop_free_ctrl,
.submit_async_event = nvme_loop_submit_async_event,
.delete_ctrl = nvme_loop_del_ctrl,
- .get_subsysnqn = nvmf_get_subsysnqn,
};
static int nvme_loop_create_io_queues(struct nvme_loop_ctrl *ctrl)
@@ -629,15 +602,13 @@ static struct nvme_ctrl *nvme_loop_create_ctrl(struct device *dev,
INIT_LIST_HEAD(&ctrl->list);
INIT_WORK(&ctrl->delete_work, nvme_loop_del_ctrl_work);
- INIT_WORK(&ctrl->reset_work, nvme_loop_reset_ctrl_work);
+ INIT_WORK(&ctrl->ctrl.reset_work, nvme_loop_reset_ctrl_work);
ret = nvme_init_ctrl(&ctrl->ctrl, dev, &nvme_loop_ctrl_ops,
0 /* no quirks, we're perfect! */);
if (ret)
goto out_put_ctrl;
- spin_lock_init(&ctrl->lock);
-
ret = -ENOMEM;
ctrl->ctrl.sqsize = opts->queue_size - 1;
@@ -766,7 +737,7 @@ static void __exit nvme_loop_cleanup_module(void)
__nvme_loop_del_ctrl(ctrl);
mutex_unlock(&nvme_loop_ctrl_mutex);
- flush_scheduled_work();
+ flush_workqueue(nvme_wq);
}
module_init(nvme_loop_init_module);
diff --git a/drivers/nvme/target/nvmet.h b/drivers/nvme/target/nvmet.h
index cfc5c7fb0ab7..747bbdb4f9c6 100644
--- a/drivers/nvme/target/nvmet.h
+++ b/drivers/nvme/target/nvmet.h
@@ -21,6 +21,7 @@
#include <linux/percpu-refcount.h>
#include <linux/list.h>
#include <linux/mutex.h>
+#include <linux/uuid.h>
#include <linux/nvme.h>
#include <linux/configfs.h>
#include <linux/rcupdate.h>
@@ -46,6 +47,7 @@ struct nvmet_ns {
u32 blksize_shift;
loff_t size;
u8 nguid[16];
+ uuid_t uuid;
bool enabled;
struct nvmet_subsys *subsys;
diff --git a/drivers/nvme/target/rdma.c b/drivers/nvme/target/rdma.c
index 9e45cde63376..56a4cba690b5 100644
--- a/drivers/nvme/target/rdma.c
+++ b/drivers/nvme/target/rdma.c
@@ -1027,7 +1027,7 @@ nvmet_rdma_parse_cm_connect_req(struct rdma_conn_param *conn,
queue->recv_queue_size = le16_to_cpu(req->hsqsize) + 1;
queue->send_queue_size = le16_to_cpu(req->hrqsize);
- if (!queue->host_qid && queue->recv_queue_size > NVMF_AQ_DEPTH)
+ if (!queue->host_qid && queue->recv_queue_size > NVME_AQ_DEPTH)
return NVME_RDMA_CM_INVALID_HSQSIZE;
/* XXX: Should we enforce some kind of max for IO queues? */
@@ -1307,53 +1307,44 @@ static void nvmet_rdma_queue_connect_fail(struct rdma_cm_id *cm_id,
/**
* nvme_rdma_device_removal() - Handle RDMA device removal
+ * @cm_id: rdma_cm id, used for nvmet port
* @queue: nvmet rdma queue (cm id qp_context)
- * @addr: nvmet address (cm_id context)
*
* DEVICE_REMOVAL event notifies us that the RDMA device is about
- * to unplug so we should take care of destroying our RDMA resources.
- * This event will be generated for each allocated cm_id.
+ * to unplug. Note that this event can be generated on a normal
+ * queue cm_id and/or a device bound listener cm_id (where in this
+ * case queue will be null).
*
- * Note that this event can be generated on a normal queue cm_id
- * and/or a device bound listener cm_id (where in this case
- * queue will be null).
- *
- * we claim ownership on destroying the cm_id. For queues we move
- * the queue state to NVMET_RDMA_IN_DEVICE_REMOVAL and for port
+ * We registered an ib_client to handle device removal for queues,
+ * so we only need to handle the listening port cm_ids. In this case
* we nullify the priv to prevent double cm_id destruction and destroying
* the cm_id implicitely by returning a non-zero rc to the callout.
*/
static int nvmet_rdma_device_removal(struct rdma_cm_id *cm_id,
struct nvmet_rdma_queue *queue)
{
- unsigned long flags;
-
- if (!queue) {
- struct nvmet_port *port = cm_id->context;
+ struct nvmet_port *port;
+ if (queue) {
/*
- * This is a listener cm_id. Make sure that
- * future remove_port won't invoke a double
- * cm_id destroy. use atomic xchg to make sure
- * we don't compete with remove_port.
- */
- if (xchg(&port->priv, NULL) != cm_id)
- return 0;
- } else {
- /*
- * This is a queue cm_id. Make sure that
- * release queue will not destroy the cm_id
- * and schedule all ctrl queues removal (only
- * if the queue is not disconnecting already).
+ * This is a queue cm_id. we have registered
+ * an ib_client to handle queues removal
+ * so don't interfear and just return.
*/
- spin_lock_irqsave(&queue->state_lock, flags);
- if (queue->state != NVMET_RDMA_Q_DISCONNECTING)
- queue->state = NVMET_RDMA_IN_DEVICE_REMOVAL;
- spin_unlock_irqrestore(&queue->state_lock, flags);
- nvmet_rdma_queue_disconnect(queue);
- flush_scheduled_work();
+ return 0;
}
+ port = cm_id->context;
+
+ /*
+ * This is a listener cm_id. Make sure that
+ * future remove_port won't invoke a double
+ * cm_id destroy. use atomic xchg to make sure
+ * we don't compete with remove_port.
+ */
+ if (xchg(&port->priv, NULL) != cm_id)
+ return 0;
+
/*
* We need to return 1 so that the core will destroy
* it's own ID. What a great API design..
@@ -1519,9 +1510,51 @@ static struct nvmet_fabrics_ops nvmet_rdma_ops = {
.delete_ctrl = nvmet_rdma_delete_ctrl,
};
+static void nvmet_rdma_add_one(struct ib_device *ib_device)
+{
+}
+
+static void nvmet_rdma_remove_one(struct ib_device *ib_device, void *client_data)
+{
+ struct nvmet_rdma_queue *queue;
+
+ /* Device is being removed, delete all queues using this device */
+ mutex_lock(&nvmet_rdma_queue_mutex);
+ list_for_each_entry(queue, &nvmet_rdma_queue_list, queue_list) {
+ if (queue->dev->device != ib_device)
+ continue;
+
+ pr_info("Removing queue %d\n", queue->idx);
+ __nvmet_rdma_queue_disconnect(queue);
+ }
+ mutex_unlock(&nvmet_rdma_queue_mutex);
+
+ flush_scheduled_work();
+}
+
+static struct ib_client nvmet_rdma_ib_client = {
+ .name = "nvmet_rdma",
+ .add = nvmet_rdma_add_one,
+ .remove = nvmet_rdma_remove_one
+};
+
static int __init nvmet_rdma_init(void)
{
- return nvmet_register_transport(&nvmet_rdma_ops);
+ int ret;
+
+ ret = ib_register_client(&nvmet_rdma_ib_client);
+ if (ret)
+ return ret;
+
+ ret = nvmet_register_transport(&nvmet_rdma_ops);
+ if (ret)
+ goto err_ib_client;
+
+ return 0;
+
+err_ib_client:
+ ib_unregister_client(&nvmet_rdma_ib_client);
+ return ret;
}
static void __exit nvmet_rdma_exit(void)
@@ -1544,6 +1577,7 @@ static void __exit nvmet_rdma_exit(void)
mutex_unlock(&nvmet_rdma_queue_mutex);
flush_scheduled_work();
+ ib_unregister_client(&nvmet_rdma_ib_client);
ida_destroy(&nvmet_rdma_queue_ida);
}
diff --git a/drivers/of/device.c b/drivers/of/device.c
index 9416d052cb89..28c38c756f92 100644
--- a/drivers/of/device.c
+++ b/drivers/of/device.c
@@ -144,8 +144,8 @@ int of_dma_configure(struct device *dev, struct device_node *np)
coherent ? " " : " not ");
iommu = of_iommu_configure(dev, np);
- if (IS_ERR(iommu))
- return PTR_ERR(iommu);
+ if (IS_ERR(iommu) && PTR_ERR(iommu) == -EPROBE_DEFER)
+ return -EPROBE_DEFER;
dev_dbg(dev, "device is%sbehind an iommu\n",
iommu ? " " : " not ");
diff --git a/drivers/of/platform.c b/drivers/of/platform.c
index 71fecc2debfc..703a42118ffc 100644
--- a/drivers/of/platform.c
+++ b/drivers/of/platform.c
@@ -523,7 +523,7 @@ static int __init of_platform_default_populate_init(void)
arch_initcall_sync(of_platform_default_populate_init);
#endif
-static int of_platform_device_destroy(struct device *dev, void *data)
+int of_platform_device_destroy(struct device *dev, void *data)
{
/* Do not touch devices not populated from the device tree */
if (!dev->of_node || !of_node_check_flag(dev->of_node, OF_POPULATED))
@@ -544,6 +544,7 @@ static int of_platform_device_destroy(struct device *dev, void *data)
of_node_clear_flag(dev->of_node, OF_POPULATED_BUS);
return 0;
}
+EXPORT_SYMBOL_GPL(of_platform_device_destroy);
/**
* of_platform_depopulate() - Remove devices populated from device tree
diff --git a/drivers/parisc/ccio-dma.c b/drivers/parisc/ccio-dma.c
index e32ca2ef9e54..56c93f096de9 100644
--- a/drivers/parisc/ccio-dma.c
+++ b/drivers/parisc/ccio-dma.c
@@ -741,6 +741,8 @@ ccio_map_single(struct device *dev, void *addr, size_t size,
BUG_ON(!dev);
ioc = GET_IOC(dev);
+ if (!ioc)
+ return DMA_ERROR_CODE;
BUG_ON(size <= 0);
@@ -814,6 +816,10 @@ ccio_unmap_page(struct device *dev, dma_addr_t iova, size_t size,
BUG_ON(!dev);
ioc = GET_IOC(dev);
+ if (!ioc) {
+ WARN_ON(!ioc);
+ return;
+ }
DBG_RUN("%s() iovp 0x%lx/%x\n",
__func__, (long)iova, size);
@@ -918,6 +924,8 @@ ccio_map_sg(struct device *dev, struct scatterlist *sglist, int nents,
BUG_ON(!dev);
ioc = GET_IOC(dev);
+ if (!ioc)
+ return 0;
DBG_RUN_SG("%s() START %d entries\n", __func__, nents);
@@ -990,6 +998,10 @@ ccio_unmap_sg(struct device *dev, struct scatterlist *sglist, int nents,
BUG_ON(!dev);
ioc = GET_IOC(dev);
+ if (!ioc) {
+ WARN_ON(!ioc);
+ return;
+ }
DBG_RUN_SG("%s() START %d entries, %p,%x\n",
__func__, nents, sg_virt(sglist), sglist->length);
diff --git a/drivers/parisc/dino.c b/drivers/parisc/dino.c
index 1133b5cc88ca..5c63b920b471 100644
--- a/drivers/parisc/dino.c
+++ b/drivers/parisc/dino.c
@@ -154,7 +154,10 @@ struct dino_device
};
/* Looks nice and keeps the compiler happy */
-#define DINO_DEV(d) ((struct dino_device *) d)
+#define DINO_DEV(d) ({ \
+ void *__pdata = d; \
+ BUG_ON(!__pdata); \
+ (struct dino_device *)__pdata; })
/*
diff --git a/drivers/parisc/lba_pci.c b/drivers/parisc/lba_pci.c
index 2ec2aef4d211..bc286cbbbc9b 100644
--- a/drivers/parisc/lba_pci.c
+++ b/drivers/parisc/lba_pci.c
@@ -111,8 +111,10 @@ static u32 lba_t32;
/* Looks nice and keeps the compiler happy */
-#define LBA_DEV(d) ((struct lba_device *) (d))
-
+#define LBA_DEV(d) ({ \
+ void *__pdata = d; \
+ BUG_ON(!__pdata); \
+ (struct lba_device *)__pdata; })
/*
** Only allow 8 subsidiary busses per LBA
diff --git a/drivers/parisc/sba_iommu.c b/drivers/parisc/sba_iommu.c
index 33385e574433..87ad5fd6a7a2 100644
--- a/drivers/parisc/sba_iommu.c
+++ b/drivers/parisc/sba_iommu.c
@@ -691,6 +691,8 @@ static int sba_dma_supported( struct device *dev, u64 mask)
return 0;
ioc = GET_IOC(dev);
+ if (!ioc)
+ return 0;
/*
* check if mask is >= than the current max IO Virt Address
@@ -722,6 +724,8 @@ sba_map_single(struct device *dev, void *addr, size_t size,
int pide;
ioc = GET_IOC(dev);
+ if (!ioc)
+ return DMA_ERROR_CODE;
/* save offset bits */
offset = ((dma_addr_t) (long) addr) & ~IOVP_MASK;
@@ -813,6 +817,10 @@ sba_unmap_page(struct device *dev, dma_addr_t iova, size_t size,
DBG_RUN("%s() iovp 0x%lx/%x\n", __func__, (long) iova, size);
ioc = GET_IOC(dev);
+ if (!ioc) {
+ WARN_ON(!ioc);
+ return;
+ }
offset = iova & ~IOVP_MASK;
iova ^= offset; /* clear offset bits */
size += offset;
@@ -952,6 +960,8 @@ sba_map_sg(struct device *dev, struct scatterlist *sglist, int nents,
DBG_RUN_SG("%s() START %d entries\n", __func__, nents);
ioc = GET_IOC(dev);
+ if (!ioc)
+ return 0;
/* Fast path single entry scatterlists. */
if (nents == 1) {
@@ -1037,6 +1047,10 @@ sba_unmap_sg(struct device *dev, struct scatterlist *sglist, int nents,
__func__, nents, sg_virt(sglist), sglist->length);
ioc = GET_IOC(dev);
+ if (!ioc) {
+ WARN_ON(!ioc);
+ return;
+ }
#ifdef SBA_COLLECT_STATS
ioc->usg_calls++;
diff --git a/drivers/pci/Kconfig b/drivers/pci/Kconfig
index e0cacb7b8563..c32a77fc8b03 100644
--- a/drivers/pci/Kconfig
+++ b/drivers/pci/Kconfig
@@ -86,6 +86,9 @@ config PCI_ATS
config PCI_ECAM
bool
+config PCI_LOCKLESS_CONFIG
+ bool
+
config PCI_IOV
bool "PCI IOV support"
depends on PCI
diff --git a/drivers/pci/access.c b/drivers/pci/access.c
index 74cf5fffb1e1..913d6722ece9 100644
--- a/drivers/pci/access.c
+++ b/drivers/pci/access.c
@@ -25,6 +25,14 @@ DEFINE_RAW_SPINLOCK(pci_lock);
#define PCI_word_BAD (pos & 1)
#define PCI_dword_BAD (pos & 3)
+#ifdef CONFIG_PCI_LOCKLESS_CONFIG
+# define pci_lock_config(f) do { (void)(f); } while (0)
+# define pci_unlock_config(f) do { (void)(f); } while (0)
+#else
+# define pci_lock_config(f) raw_spin_lock_irqsave(&pci_lock, f)
+# define pci_unlock_config(f) raw_spin_unlock_irqrestore(&pci_lock, f)
+#endif
+
#define PCI_OP_READ(size, type, len) \
int pci_bus_read_config_##size \
(struct pci_bus *bus, unsigned int devfn, int pos, type *value) \
@@ -33,10 +41,10 @@ int pci_bus_read_config_##size \
unsigned long flags; \
u32 data = 0; \
if (PCI_##size##_BAD) return PCIBIOS_BAD_REGISTER_NUMBER; \
- raw_spin_lock_irqsave(&pci_lock, flags); \
+ pci_lock_config(flags); \
res = bus->ops->read(bus, devfn, pos, len, &data); \
*value = (type)data; \
- raw_spin_unlock_irqrestore(&pci_lock, flags); \
+ pci_unlock_config(flags); \
return res; \
}
@@ -47,9 +55,9 @@ int pci_bus_write_config_##size \
int res; \
unsigned long flags; \
if (PCI_##size##_BAD) return PCIBIOS_BAD_REGISTER_NUMBER; \
- raw_spin_lock_irqsave(&pci_lock, flags); \
+ pci_lock_config(flags); \
res = bus->ops->write(bus, devfn, pos, len, value); \
- raw_spin_unlock_irqrestore(&pci_lock, flags); \
+ pci_unlock_config(flags); \
return res; \
}
@@ -896,7 +904,7 @@ int pci_read_config_byte(const struct pci_dev *dev, int where, u8 *val)
{
if (pci_dev_is_disconnected(dev)) {
*val = ~0;
- return -ENODEV;
+ return PCIBIOS_DEVICE_NOT_FOUND;
}
return pci_bus_read_config_byte(dev->bus, dev->devfn, where, val);
}
@@ -906,7 +914,7 @@ int pci_read_config_word(const struct pci_dev *dev, int where, u16 *val)
{
if (pci_dev_is_disconnected(dev)) {
*val = ~0;
- return -ENODEV;
+ return PCIBIOS_DEVICE_NOT_FOUND;
}
return pci_bus_read_config_word(dev->bus, dev->devfn, where, val);
}
@@ -917,7 +925,7 @@ int pci_read_config_dword(const struct pci_dev *dev, int where,
{
if (pci_dev_is_disconnected(dev)) {
*val = ~0;
- return -ENODEV;
+ return PCIBIOS_DEVICE_NOT_FOUND;
}
return pci_bus_read_config_dword(dev->bus, dev->devfn, where, val);
}
@@ -926,7 +934,7 @@ EXPORT_SYMBOL(pci_read_config_dword);
int pci_write_config_byte(const struct pci_dev *dev, int where, u8 val)
{
if (pci_dev_is_disconnected(dev))
- return -ENODEV;
+ return PCIBIOS_DEVICE_NOT_FOUND;
return pci_bus_write_config_byte(dev->bus, dev->devfn, where, val);
}
EXPORT_SYMBOL(pci_write_config_byte);
@@ -934,7 +942,7 @@ EXPORT_SYMBOL(pci_write_config_byte);
int pci_write_config_word(const struct pci_dev *dev, int where, u16 val)
{
if (pci_dev_is_disconnected(dev))
- return -ENODEV;
+ return PCIBIOS_DEVICE_NOT_FOUND;
return pci_bus_write_config_word(dev->bus, dev->devfn, where, val);
}
EXPORT_SYMBOL(pci_write_config_word);
@@ -943,7 +951,7 @@ int pci_write_config_dword(const struct pci_dev *dev, int where,
u32 val)
{
if (pci_dev_is_disconnected(dev))
- return -ENODEV;
+ return PCIBIOS_DEVICE_NOT_FOUND;
return pci_bus_write_config_dword(dev->bus, dev->devfn, where, val);
}
EXPORT_SYMBOL(pci_write_config_dword);
diff --git a/drivers/pci/dwc/pci-imx6.c b/drivers/pci/dwc/pci-imx6.c
index a98cba55c7f0..19a289b8cc94 100644
--- a/drivers/pci/dwc/pci-imx6.c
+++ b/drivers/pci/dwc/pci-imx6.c
@@ -252,7 +252,34 @@ static void imx6_pcie_reset_phy(struct imx6_pcie *imx6_pcie)
static int imx6q_pcie_abort_handler(unsigned long addr,
unsigned int fsr, struct pt_regs *regs)
{
- return 0;
+ unsigned long pc = instruction_pointer(regs);
+ unsigned long instr = *(unsigned long *)pc;
+ int reg = (instr >> 12) & 15;
+
+ /*
+ * If the instruction being executed was a read,
+ * make it look like it read all-ones.
+ */
+ if ((instr & 0x0c100000) == 0x04100000) {
+ unsigned long val;
+
+ if (instr & 0x00400000)
+ val = 255;
+ else
+ val = -1;
+
+ regs->uregs[reg] = val;
+ regs->ARM_pc += 4;
+ return 0;
+ }
+
+ if ((instr & 0x0e100090) == 0x00100090) {
+ regs->uregs[reg] = -1;
+ regs->ARM_pc += 4;
+ return 0;
+ }
+
+ return 1;
}
static void imx6_pcie_assert_core_reset(struct imx6_pcie *imx6_pcie)
@@ -819,8 +846,8 @@ static int __init imx6_pcie_init(void)
* we can install the handler here without risking it
* accessing some uninitialized driver state.
*/
- hook_fault_code(16 + 6, imx6q_pcie_abort_handler, SIGBUS, 0,
- "imprecise external abort");
+ hook_fault_code(8, imx6q_pcie_abort_handler, SIGBUS, 0,
+ "external abort on non-linefetch");
return platform_driver_register(&imx6_pcie_driver);
}
diff --git a/drivers/pci/endpoint/Kconfig b/drivers/pci/endpoint/Kconfig
index c23f146fb5a6..c09623ca8c3b 100644
--- a/drivers/pci/endpoint/Kconfig
+++ b/drivers/pci/endpoint/Kconfig
@@ -6,6 +6,7 @@ menu "PCI Endpoint"
config PCI_ENDPOINT
bool "PCI Endpoint Support"
+ depends on HAS_DMA
help
Enable this configuration option to support configurable PCI
endpoint. This should be enabled if the platform has a PCI
diff --git a/drivers/pci/endpoint/functions/Kconfig b/drivers/pci/endpoint/functions/Kconfig
index 175edad42d2f..2942066607e0 100644
--- a/drivers/pci/endpoint/functions/Kconfig
+++ b/drivers/pci/endpoint/functions/Kconfig
@@ -5,6 +5,7 @@
config PCI_EPF_TEST
tristate "PCI Endpoint Test driver"
depends on PCI_ENDPOINT
+ select CRC32
help
Enable this configuration option to enable the test driver
for PCI Endpoint.
diff --git a/drivers/pci/host/vmd.c b/drivers/pci/host/vmd.c
index e27ad2a3bd33..31203d69616d 100644
--- a/drivers/pci/host/vmd.c
+++ b/drivers/pci/host/vmd.c
@@ -554,6 +554,7 @@ static int vmd_find_free_domain(void)
static int vmd_enable_domain(struct vmd_dev *vmd)
{
struct pci_sysdata *sd = &vmd->sysdata;
+ struct fwnode_handle *fn;
struct resource *res;
u32 upper_bits;
unsigned long flags;
@@ -617,8 +618,13 @@ static int vmd_enable_domain(struct vmd_dev *vmd)
sd->node = pcibus_to_node(vmd->dev->bus);
- vmd->irq_domain = pci_msi_create_irq_domain(NULL, &vmd_msi_domain_info,
+ fn = irq_domain_alloc_named_id_fwnode("VMD-MSI", vmd->sysdata.domain);
+ if (!fn)
+ return -ENODEV;
+
+ vmd->irq_domain = pci_msi_create_irq_domain(fn, &vmd_msi_domain_info,
x86_vector_domain);
+ irq_domain_free_fwnode(fn);
if (!vmd->irq_domain)
return -ENODEV;
diff --git a/drivers/pci/msi.c b/drivers/pci/msi.c
index ba44fdfda66b..fbad5dca3219 100644
--- a/drivers/pci/msi.c
+++ b/drivers/pci/msi.c
@@ -1463,7 +1463,7 @@ struct irq_domain *pci_msi_create_irq_domain(struct fwnode_handle *fwnode,
if (!domain)
return NULL;
- domain->bus_token = DOMAIN_BUS_PCI_MSI;
+ irq_domain_update_bus_token(domain, DOMAIN_BUS_PCI_MSI);
return domain;
}
EXPORT_SYMBOL_GPL(pci_msi_create_irq_domain);
diff --git a/drivers/pci/pci-acpi.c b/drivers/pci/pci-acpi.c
index 001860361434..47070cff508c 100644
--- a/drivers/pci/pci-acpi.c
+++ b/drivers/pci/pci-acpi.c
@@ -21,13 +21,12 @@
#include "pci.h"
/*
- * The UUID is defined in the PCI Firmware Specification available here:
+ * The GUID is defined in the PCI Firmware Specification available here:
* https://www.pcisig.com/members/downloads/pcifw_r3_1_13Dec10.pdf
*/
-const u8 pci_acpi_dsm_uuid[] = {
- 0xd0, 0x37, 0xc9, 0xe5, 0x53, 0x35, 0x7a, 0x4d,
- 0x91, 0x17, 0xea, 0x4d, 0x19, 0xc3, 0x43, 0x4d
-};
+const guid_t pci_acpi_dsm_guid =
+ GUID_INIT(0xe5c937d0, 0x3553, 0x4d7a,
+ 0x91, 0x17, 0xea, 0x4d, 0x19, 0xc3, 0x43, 0x4d);
#if defined(CONFIG_PCI_QUIRKS) && defined(CONFIG_ARM64)
static int acpi_get_rc_addr(struct acpi_device *adev, struct resource *res)
@@ -680,7 +679,7 @@ void acpi_pci_add_bus(struct pci_bus *bus)
if (!pci_is_root_bus(bus))
return;
- obj = acpi_evaluate_dsm(ACPI_HANDLE(bus->bridge), pci_acpi_dsm_uuid, 3,
+ obj = acpi_evaluate_dsm(ACPI_HANDLE(bus->bridge), &pci_acpi_dsm_guid, 3,
RESET_DELAY_DSM, NULL);
if (!obj)
return;
@@ -745,7 +744,7 @@ static void pci_acpi_optimize_delay(struct pci_dev *pdev,
if (bridge->ignore_reset_delay)
pdev->d3cold_delay = 0;
- obj = acpi_evaluate_dsm(handle, pci_acpi_dsm_uuid, 3,
+ obj = acpi_evaluate_dsm(handle, &pci_acpi_dsm_guid, 3,
FUNCTION_DELAY_DSM, NULL);
if (!obj)
return;
diff --git a/drivers/pci/pci-driver.c b/drivers/pci/pci-driver.c
index 934a78a2fbef..00e10bf7f6a2 100644
--- a/drivers/pci/pci-driver.c
+++ b/drivers/pci/pci-driver.c
@@ -320,10 +320,19 @@ static long local_pci_probe(void *_ddi)
return 0;
}
+static bool pci_physfn_is_probed(struct pci_dev *dev)
+{
+#ifdef CONFIG_PCI_IOV
+ return dev->is_virtfn && dev->physfn->is_probed;
+#else
+ return false;
+#endif
+}
+
static int pci_call_probe(struct pci_driver *drv, struct pci_dev *dev,
const struct pci_device_id *id)
{
- int error, node;
+ int error, node, cpu;
struct drv_dev_and_id ddi = { drv, dev, id };
/*
@@ -332,33 +341,27 @@ static int pci_call_probe(struct pci_driver *drv, struct pci_dev *dev,
* on the right node.
*/
node = dev_to_node(&dev->dev);
+ dev->is_probed = 1;
+
+ cpu_hotplug_disable();
/*
- * On NUMA systems, we are likely to call a PF probe function using
- * work_on_cpu(). If that probe calls pci_enable_sriov() (which
- * adds the VF devices via pci_bus_add_device()), we may re-enter
- * this function to call the VF probe function. Calling
- * work_on_cpu() again will cause a lockdep warning. Since VFs are
- * always on the same node as the PF, we can work around this by
- * avoiding work_on_cpu() when we're already on the correct node.
- *
- * Preemption is enabled, so it's theoretically unsafe to use
- * numa_node_id(), but even if we run the probe function on the
- * wrong node, it should be functionally correct.
+ * Prevent nesting work_on_cpu() for the case where a Virtual Function
+ * device is probed from work_on_cpu() of the Physical device.
*/
- if (node >= 0 && node != numa_node_id()) {
- int cpu;
-
- get_online_cpus();
+ if (node < 0 || node >= MAX_NUMNODES || !node_online(node) ||
+ pci_physfn_is_probed(dev))
+ cpu = nr_cpu_ids;
+ else
cpu = cpumask_any_and(cpumask_of_node(node), cpu_online_mask);
- if (cpu < nr_cpu_ids)
- error = work_on_cpu(cpu, local_pci_probe, &ddi);
- else
- error = local_pci_probe(&ddi);
- put_online_cpus();
- } else
+
+ if (cpu < nr_cpu_ids)
+ error = work_on_cpu(cpu, local_pci_probe, &ddi);
+ else
error = local_pci_probe(&ddi);
+ dev->is_probed = 0;
+ cpu_hotplug_enable();
return error;
}
diff --git a/drivers/pci/pci-label.c b/drivers/pci/pci-label.c
index 51357377efbc..2d8db3ead6e8 100644
--- a/drivers/pci/pci-label.c
+++ b/drivers/pci/pci-label.c
@@ -172,7 +172,7 @@ static int dsm_get_label(struct device *dev, char *buf,
if (!handle)
return -1;
- obj = acpi_evaluate_dsm(handle, pci_acpi_dsm_uuid, 0x2,
+ obj = acpi_evaluate_dsm(handle, &pci_acpi_dsm_guid, 0x2,
DEVICE_LABEL_DSM, NULL);
if (!obj)
return -1;
@@ -212,7 +212,7 @@ static bool device_has_dsm(struct device *dev)
if (!handle)
return false;
- return !!acpi_check_dsm(handle, pci_acpi_dsm_uuid, 0x2,
+ return !!acpi_check_dsm(handle, &pci_acpi_dsm_guid, 0x2,
1 << DEVICE_LABEL_DSM);
}
diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c
index b01bd5bba8e6..563901cd9c06 100644
--- a/drivers/pci/pci.c
+++ b/drivers/pci/pci.c
@@ -2144,7 +2144,8 @@ bool pci_dev_keep_suspended(struct pci_dev *pci_dev)
if (!pm_runtime_suspended(dev)
|| pci_target_state(pci_dev) != pci_dev->current_state
- || platform_pci_need_resume(pci_dev))
+ || platform_pci_need_resume(pci_dev)
+ || (pci_dev->dev_flags & PCI_DEV_FLAGS_NEEDS_RESUME))
return false;
/*
diff --git a/drivers/pci/switch/switchtec.c b/drivers/pci/switch/switchtec.c
index cc6e085008fb..f6a63406c76e 100644
--- a/drivers/pci/switch/switchtec.c
+++ b/drivers/pci/switch/switchtec.c
@@ -1291,7 +1291,6 @@ static struct switchtec_dev *stdev_create(struct pci_dev *pdev)
cdev = &stdev->cdev;
cdev_init(cdev, &switchtec_fops);
cdev->owner = THIS_MODULE;
- cdev->kobj.parent = &dev->kobj;
return stdev;
@@ -1442,12 +1441,15 @@ static int switchtec_init_pci(struct switchtec_dev *stdev,
stdev->mmio_sys_info = stdev->mmio + SWITCHTEC_GAS_SYS_INFO_OFFSET;
stdev->mmio_flash_info = stdev->mmio + SWITCHTEC_GAS_FLASH_INFO_OFFSET;
stdev->mmio_ntb = stdev->mmio + SWITCHTEC_GAS_NTB_OFFSET;
- stdev->partition = ioread8(&stdev->mmio_ntb->partition_id);
+ stdev->partition = ioread8(&stdev->mmio_sys_info->partition_id);
stdev->partition_count = ioread8(&stdev->mmio_ntb->partition_count);
stdev->mmio_part_cfg_all = stdev->mmio + SWITCHTEC_GAS_PART_CFG_OFFSET;
stdev->mmio_part_cfg = &stdev->mmio_part_cfg_all[stdev->partition];
stdev->mmio_pff_csr = stdev->mmio + SWITCHTEC_GAS_PFF_CSR_OFFSET;
+ if (stdev->partition_count < 1)
+ stdev->partition_count = 1;
+
init_pff(stdev);
pci_set_drvdata(pdev, stdev);
@@ -1479,11 +1481,7 @@ static int switchtec_pci_probe(struct pci_dev *pdev,
SWITCHTEC_EVENT_EN_IRQ,
&stdev->mmio_part_cfg->mrpc_comp_hdr);
- rc = cdev_add(&stdev->cdev, stdev->dev.devt, 1);
- if (rc)
- goto err_put;
-
- rc = device_add(&stdev->dev);
+ rc = cdev_device_add(&stdev->cdev, &stdev->dev);
if (rc)
goto err_devadd;
@@ -1492,7 +1490,6 @@ static int switchtec_pci_probe(struct pci_dev *pdev,
return 0;
err_devadd:
- cdev_del(&stdev->cdev);
stdev_kill(stdev);
err_put:
ida_simple_remove(&switchtec_minor_ida, MINOR(stdev->dev.devt));
@@ -1506,8 +1503,7 @@ static void switchtec_pci_remove(struct pci_dev *pdev)
pci_set_drvdata(pdev, NULL);
- device_del(&stdev->dev);
- cdev_del(&stdev->cdev);
+ cdev_device_del(&stdev->cdev, &stdev->dev);
ida_simple_remove(&switchtec_minor_ida, MINOR(stdev->dev.devt));
dev_info(&stdev->dev, "unregistered.\n");
diff --git a/drivers/perf/arm_pmu_acpi.c b/drivers/perf/arm_pmu_acpi.c
index 34c862f213c7..0a9b78705ee8 100644
--- a/drivers/perf/arm_pmu_acpi.c
+++ b/drivers/perf/arm_pmu_acpi.c
@@ -29,6 +29,17 @@ static int arm_pmu_acpi_register_irq(int cpu)
return -EINVAL;
gsi = gicc->performance_interrupt;
+
+ /*
+ * Per the ACPI spec, the MADT cannot describe a PMU that doesn't
+ * have an interrupt. QEMU advertises this by using a GSI of zero,
+ * which is not known to be valid on any hardware despite being
+ * valid per the spec. Take the pragmatic approach and reject a
+ * GSI of zero for now.
+ */
+ if (!gsi)
+ return 0;
+
if (gicc->flags & ACPI_MADT_PERFORMANCE_IRQ_MODE)
trigger = ACPI_EDGE_SENSITIVE;
else
diff --git a/drivers/phy/Kconfig b/drivers/phy/Kconfig
index afaf7b643eeb..c1807d4a0079 100644
--- a/drivers/phy/Kconfig
+++ b/drivers/phy/Kconfig
@@ -15,73 +15,6 @@ config GENERIC_PHY
phy users can obtain reference to the PHY. All the users of this
framework should select this config.
-config PHY_BCM_NS_USB2
- tristate "Broadcom Northstar USB 2.0 PHY Driver"
- depends on ARCH_BCM_IPROC || COMPILE_TEST
- depends on HAS_IOMEM && OF
- select GENERIC_PHY
- help
- Enable this to support Broadcom USB 2.0 PHY connected to the USB
- controller on Northstar family.
-
-config PHY_BCM_NS_USB3
- tristate "Broadcom Northstar USB 3.0 PHY Driver"
- depends on ARCH_BCM_IPROC || COMPILE_TEST
- depends on HAS_IOMEM && OF
- select GENERIC_PHY
- help
- Enable this to support Broadcom USB 3.0 PHY connected to the USB
- controller on Northstar family.
-
-config PHY_BERLIN_USB
- tristate "Marvell Berlin USB PHY Driver"
- depends on ARCH_BERLIN && RESET_CONTROLLER && HAS_IOMEM && OF
- select GENERIC_PHY
- help
- Enable this to support the USB PHY on Marvell Berlin SoCs.
-
-config PHY_BERLIN_SATA
- tristate "Marvell Berlin SATA PHY driver"
- depends on ARCH_BERLIN && HAS_IOMEM && OF
- select GENERIC_PHY
- help
- Enable this to support the SATA PHY on Marvell Berlin SoCs.
-
-config ARMADA375_USBCLUSTER_PHY
- def_bool y
- depends on MACH_ARMADA_375 || COMPILE_TEST
- depends on OF && HAS_IOMEM
- select GENERIC_PHY
-
-config PHY_DA8XX_USB
- tristate "TI DA8xx USB PHY Driver"
- depends on ARCH_DAVINCI_DA8XX
- select GENERIC_PHY
- select MFD_SYSCON
- help
- Enable this to support the USB PHY on DA8xx SoCs.
-
- This driver controls both the USB 1.1 PHY and the USB 2.0 PHY.
-
-config PHY_DM816X_USB
- tristate "TI dm816x USB PHY driver"
- depends on ARCH_OMAP2PLUS
- depends on USB_SUPPORT
- select GENERIC_PHY
- select USB_PHY
- help
- Enable this for dm816x USB to work.
-
-config PHY_EXYNOS_MIPI_VIDEO
- tristate "S5P/EXYNOS SoC series MIPI CSI-2/DSI PHY driver"
- depends on HAS_IOMEM
- depends on ARCH_S5PV210 || ARCH_EXYNOS || COMPILE_TEST
- select GENERIC_PHY
- default y if ARCH_S5PV210 || ARCH_EXYNOS
- help
- Support for MIPI CSI-2 and MIPI DSI DPHY found on Samsung S5P
- and EXYNOS SoCs.
-
config PHY_LPC18XX_USB_OTG
tristate "NXP LPC18xx/43xx SoC USB OTG PHY driver"
depends on OF && (ARCH_LPC18XX || COMPILE_TEST)
@@ -93,146 +26,6 @@ config PHY_LPC18XX_USB_OTG
This driver is need for USB0 support on LPC18xx/43xx and takes
care of enabling and clock setup.
-config PHY_PXA_28NM_HSIC
- tristate "Marvell USB HSIC 28nm PHY Driver"
- depends on HAS_IOMEM
- select GENERIC_PHY
- help
- Enable this to support Marvell USB HSIC PHY driver for Marvell
- SoC. This driver will do the PHY initialization and shutdown.
- The PHY driver will be used by Marvell ehci driver.
-
- To compile this driver as a module, choose M here.
-
-config PHY_PXA_28NM_USB2
- tristate "Marvell USB 2.0 28nm PHY Driver"
- depends on HAS_IOMEM
- select GENERIC_PHY
- help
- Enable this to support Marvell USB 2.0 PHY driver for Marvell
- SoC. This driver will do the PHY initialization and shutdown.
- The PHY driver will be used by Marvell udc/ehci/otg driver.
-
- To compile this driver as a module, choose M here.
-
-config PHY_MVEBU_SATA
- def_bool y
- depends on ARCH_DOVE || MACH_DOVE || MACH_KIRKWOOD
- depends on OF
- select GENERIC_PHY
-
-config PHY_MIPHY28LP
- tristate "STMicroelectronics MIPHY28LP PHY driver for STiH407"
- depends on ARCH_STI
- select GENERIC_PHY
- help
- Enable this to support the miphy transceiver (for SATA/PCIE/USB3)
- that is part of STMicroelectronics STiH407 SoC.
-
-config PHY_RCAR_GEN2
- tristate "Renesas R-Car generation 2 USB PHY driver"
- depends on ARCH_RENESAS
- depends on GENERIC_PHY
- help
- Support for USB PHY found on Renesas R-Car generation 2 SoCs.
-
-config PHY_RCAR_GEN3_USB2
- tristate "Renesas R-Car generation 3 USB 2.0 PHY driver"
- depends on ARCH_RENESAS
- depends on EXTCON
- select GENERIC_PHY
- help
- Support for USB 2.0 PHY found on Renesas R-Car generation 3 SoCs.
-
-config OMAP_CONTROL_PHY
- tristate "OMAP CONTROL PHY Driver"
- depends on ARCH_OMAP2PLUS || COMPILE_TEST
- help
- Enable this to add support for the PHY part present in the control
- module. This driver has API to power on the USB2 PHY and to write to
- the mailbox. The mailbox is present only in omap4 and the register to
- power on the USB2 PHY is present in OMAP4 and OMAP5. OMAP5 has an
- additional register to power on USB3 PHY/SATA PHY/PCIE PHY
- (PIPE3 PHY).
-
-config OMAP_USB2
- tristate "OMAP USB2 PHY Driver"
- depends on ARCH_OMAP2PLUS
- depends on USB_SUPPORT
- select GENERIC_PHY
- select USB_PHY
- select OMAP_CONTROL_PHY
- depends on OMAP_OCP2SCP
- help
- Enable this to support the transceiver that is part of SOC. This
- driver takes care of all the PHY functionality apart from comparator.
- The USB OTG controller communicates with the comparator using this
- driver.
-
-config TI_PIPE3
- tristate "TI PIPE3 PHY Driver"
- depends on ARCH_OMAP2PLUS || COMPILE_TEST
- select GENERIC_PHY
- select OMAP_CONTROL_PHY
- depends on OMAP_OCP2SCP
- help
- Enable this to support the PIPE3 PHY that is part of TI SOCs. This
- driver takes care of all the PHY functionality apart from comparator.
- This driver interacts with the "OMAP Control PHY Driver" to power
- on/off the PHY.
-
-config TWL4030_USB
- tristate "TWL4030 USB Transceiver Driver"
- depends on TWL4030_CORE && REGULATOR_TWL4030 && USB_MUSB_OMAP2PLUS
- depends on USB_SUPPORT
- depends on USB_GADGET || !USB_GADGET # if USB_GADGET=m, this can't 'y'
- select GENERIC_PHY
- select USB_PHY
- help
- Enable this to support the USB OTG transceiver on TWL4030
- family chips (including the TWL5030 and TPS659x0 devices).
- This transceiver supports high and full speed devices plus,
- in host mode, low speed.
-
-config PHY_EXYNOS_DP_VIDEO
- tristate "EXYNOS SoC series Display Port PHY driver"
- depends on OF
- depends on ARCH_EXYNOS || COMPILE_TEST
- default ARCH_EXYNOS
- select GENERIC_PHY
- help
- Support for Display Port PHY found on Samsung EXYNOS SoCs.
-
-config BCM_KONA_USB2_PHY
- tristate "Broadcom Kona USB2 PHY Driver"
- depends on HAS_IOMEM
- select GENERIC_PHY
- help
- Enable this to support the Broadcom Kona USB 2.0 PHY.
-
-config PHY_EXYNOS5250_SATA
- tristate "Exynos5250 Sata SerDes/PHY driver"
- depends on SOC_EXYNOS5250
- depends on HAS_IOMEM
- depends on OF
- select GENERIC_PHY
- select I2C
- select I2C_S3C2410
- select MFD_SYSCON
- help
- Enable this to support SATA SerDes/Phy found on Samsung's
- Exynos5250 based SoCs.This SerDes/Phy supports SATA 1.5 Gb/s,
- SATA 3.0 Gb/s, SATA 6.0 Gb/s speeds. It supports one SATA host
- port to accept one SATA device.
-
-config PHY_HIX5HD2_SATA
- tristate "HIX5HD2 SATA PHY Driver"
- depends on ARCH_HIX5HD2 && OF && HAS_IOMEM
- select GENERIC_PHY
- select MFD_SYSCON
- help
- Support for SATA PHY on Hisilicon hix5hd2 Soc.
-
config PHY_MT65XX_USB3
tristate "Mediatek USB3.0 PHY Driver"
depends on ARCH_MEDIATEK && OF
@@ -241,104 +34,6 @@ config PHY_MT65XX_USB3
Say 'Y' here to add support for Mediatek USB3.0 PHY driver,
it supports multiple usb2.0 and usb3.0 ports.
-config PHY_HI6220_USB
- tristate "hi6220 USB PHY support"
- depends on (ARCH_HISI && ARM64) || COMPILE_TEST
- select GENERIC_PHY
- select MFD_SYSCON
- help
- Enable this to support the HISILICON HI6220 USB PHY.
-
- To compile this driver as a module, choose M here.
-
-config PHY_SUN4I_USB
- tristate "Allwinner sunxi SoC USB PHY driver"
- depends on ARCH_SUNXI && HAS_IOMEM && OF
- depends on RESET_CONTROLLER
- depends on EXTCON
- depends on POWER_SUPPLY
- depends on USB_SUPPORT
- select GENERIC_PHY
- select USB_COMMON
- help
- Enable this to support the transceiver that is part of Allwinner
- sunxi SoCs.
-
- This driver controls the entire USB PHY block, both the USB OTG
- parts, as well as the 2 regular USB 2 host PHYs.
-
-config PHY_SUN9I_USB
- tristate "Allwinner sun9i SoC USB PHY driver"
- depends on ARCH_SUNXI && HAS_IOMEM && OF
- depends on RESET_CONTROLLER
- depends on USB_SUPPORT
- select USB_COMMON
- select GENERIC_PHY
- help
- Enable this to support the transceiver that is part of Allwinner
- sun9i SoCs.
-
- This driver controls each individual USB 2 host PHY.
-
-config PHY_SAMSUNG_USB2
- tristate "Samsung USB 2.0 PHY driver"
- depends on HAS_IOMEM
- depends on USB_EHCI_EXYNOS || USB_OHCI_EXYNOS || USB_DWC2
- select GENERIC_PHY
- select MFD_SYSCON
- default ARCH_EXYNOS
- help
- Enable this to support the Samsung USB 2.0 PHY driver for Samsung
- SoCs. This driver provides the interface for USB 2.0 PHY. Support
- for particular PHYs will be enabled based on the SoC type in addition
- to this driver.
-
-config PHY_S5PV210_USB2
- bool "Support for S5PV210"
- depends on PHY_SAMSUNG_USB2
- depends on ARCH_S5PV210
- help
- Enable USB PHY support for S5PV210. This option requires that Samsung
- USB 2.0 PHY driver is enabled and means that support for this
- particular SoC is compiled in the driver. In case of S5PV210 two phys
- are available - device and host.
-
-config PHY_EXYNOS4210_USB2
- bool
- depends on PHY_SAMSUNG_USB2
- default CPU_EXYNOS4210
-
-config PHY_EXYNOS4X12_USB2
- bool
- depends on PHY_SAMSUNG_USB2
- default SOC_EXYNOS3250 || SOC_EXYNOS4212 || SOC_EXYNOS4412
-
-config PHY_EXYNOS5250_USB2
- bool
- depends on PHY_SAMSUNG_USB2
- default SOC_EXYNOS5250 || SOC_EXYNOS5420
-
-config PHY_EXYNOS5_USBDRD
- tristate "Exynos5 SoC series USB DRD PHY driver"
- depends on ARCH_EXYNOS && OF
- depends on HAS_IOMEM
- depends on USB_DWC3_EXYNOS
- select GENERIC_PHY
- select MFD_SYSCON
- default y
- help
- Enable USB DRD PHY support for Exynos 5 SoC series.
- This driver provides PHY interface for USB 3.0 DRD controller
- present on Exynos5 SoC series.
-
-config PHY_EXYNOS_PCIE
- bool "Exynos PCIe PHY driver"
- depends on OF && (ARCH_EXYNOS || COMPILE_TEST)
- select GENERIC_PHY
- help
- Enable PCIe PHY support for Exynos SoC series.
- This driver provides PHY interface for Exynos PCIe controller.
-
config PHY_PISTACHIO_USB
tristate "IMG Pistachio USB2.0 PHY driver"
depends on MACH_PISTACHIO
@@ -346,83 +41,6 @@ config PHY_PISTACHIO_USB
help
Enable this to support the USB2.0 PHY on the IMG Pistachio SoC.
-config PHY_QCOM_APQ8064_SATA
- tristate "Qualcomm APQ8064 SATA SerDes/PHY driver"
- depends on ARCH_QCOM
- depends on HAS_IOMEM
- depends on OF
- select GENERIC_PHY
-
-config PHY_QCOM_IPQ806X_SATA
- tristate "Qualcomm IPQ806x SATA SerDes/PHY driver"
- depends on ARCH_QCOM
- depends on HAS_IOMEM
- depends on OF
- select GENERIC_PHY
-
-config PHY_ROCKCHIP_USB
- tristate "Rockchip USB2 PHY Driver"
- depends on ARCH_ROCKCHIP && OF
- select GENERIC_PHY
- help
- Enable this to support the Rockchip USB 2.0 PHY.
-
-config PHY_ROCKCHIP_INNO_USB2
- tristate "Rockchip INNO USB2PHY Driver"
- depends on (ARCH_ROCKCHIP || COMPILE_TEST) && OF
- depends on COMMON_CLK
- depends on EXTCON
- depends on USB_SUPPORT
- select GENERIC_PHY
- select USB_COMMON
- help
- Support for Rockchip USB2.0 PHY with Innosilicon IP block.
-
-config PHY_ROCKCHIP_EMMC
- tristate "Rockchip EMMC PHY Driver"
- depends on ARCH_ROCKCHIP && OF
- select GENERIC_PHY
- help
- Enable this to support the Rockchip EMMC PHY.
-
-config PHY_ROCKCHIP_DP
- tristate "Rockchip Display Port PHY Driver"
- depends on ARCH_ROCKCHIP && OF
- select GENERIC_PHY
- help
- Enable this to support the Rockchip Display Port PHY.
-
-config PHY_ROCKCHIP_PCIE
- tristate "Rockchip PCIe PHY Driver"
- depends on (ARCH_ROCKCHIP && OF) || COMPILE_TEST
- select GENERIC_PHY
- select MFD_SYSCON
- help
- Enable this to support the Rockchip PCIe PHY.
-
-config PHY_ROCKCHIP_TYPEC
- tristate "Rockchip TYPEC PHY Driver"
- depends on OF && (ARCH_ROCKCHIP || COMPILE_TEST)
- select EXTCON
- select GENERIC_PHY
- select RESET_CONTROLLER
- help
- Enable this to support the Rockchip USB TYPEC PHY.
-
-config PHY_ST_SPEAR1310_MIPHY
- tristate "ST SPEAR1310-MIPHY driver"
- select GENERIC_PHY
- depends on MACH_SPEAR1310 || COMPILE_TEST
- help
- Support for ST SPEAr1310 MIPHY which can be used for PCIe and SATA.
-
-config PHY_ST_SPEAR1340_MIPHY
- tristate "ST SPEAR1340-MIPHY driver"
- select GENERIC_PHY
- depends on MACH_SPEAR1340 || COMPILE_TEST
- help
- Support for ST SPEAr1340 MIPHY which can be used for PCIe and SATA.
-
config PHY_XGENE
tristate "APM X-Gene 15Gbps PHY support"
depends on HAS_IOMEM && OF && (ARM64 || COMPILE_TEST)
@@ -430,104 +48,18 @@ config PHY_XGENE
help
This option enables support for APM X-Gene SoC multi-purpose PHY.
-config PHY_STIH407_USB
- tristate "STMicroelectronics USB2 picoPHY driver for STiH407 family"
- depends on RESET_CONTROLLER
- depends on ARCH_STI || COMPILE_TEST
- select GENERIC_PHY
- help
- Enable this support to enable the picoPHY device used by USB2
- and USB3 controllers on STMicroelectronics STiH407 SoC families.
-
-config PHY_QCOM_QMP
- tristate "Qualcomm QMP PHY Driver"
- depends on OF && COMMON_CLK && (ARCH_QCOM || COMPILE_TEST)
- select GENERIC_PHY
- help
- Enable this to support the QMP PHY transceiver that is used
- with controllers such as PCIe, UFS, and USB on Qualcomm chips.
-
-config PHY_QCOM_QUSB2
- tristate "Qualcomm QUSB2 PHY Driver"
- depends on OF && (ARCH_QCOM || COMPILE_TEST)
- depends on NVMEM || !NVMEM
- select GENERIC_PHY
- help
- Enable this to support the HighSpeed QUSB2 PHY transceiver for USB
- controllers on Qualcomm chips. This driver supports the high-speed
- PHY which is usually paired with either the ChipIdea or Synopsys DWC3
- USB IPs on MSM SOCs.
-
-config PHY_QCOM_UFS
- tristate "Qualcomm UFS PHY driver"
- depends on OF && ARCH_QCOM
- select GENERIC_PHY
- help
- Support for UFS PHY on QCOM chipsets.
-
-config PHY_QCOM_USB_HS
- tristate "Qualcomm USB HS PHY module"
- depends on USB_ULPI_BUS
- depends on EXTCON || !EXTCON # if EXTCON=m, this cannot be built-in
- select GENERIC_PHY
- help
- Support for the USB high-speed ULPI compliant phy on Qualcomm
- chipsets.
-
-config PHY_QCOM_USB_HSIC
- tristate "Qualcomm USB HSIC ULPI PHY module"
- depends on USB_ULPI_BUS
- select GENERIC_PHY
- help
- Support for the USB HSIC ULPI compliant PHY on QCOM chipsets.
-
-config PHY_TUSB1210
- tristate "TI TUSB1210 ULPI PHY module"
- depends on USB_ULPI_BUS
- select GENERIC_PHY
- help
- Support for TI TUSB1210 USB ULPI PHY.
-
-config PHY_BRCM_SATA
- tristate "Broadcom SATA PHY driver"
- depends on ARCH_BRCMSTB || ARCH_BCM_IPROC || BMIPS_GENERIC || COMPILE_TEST
- depends on OF
- select GENERIC_PHY
- default ARCH_BCM_IPROC
- help
- Enable this to support the Broadcom SATA PHY.
- If unsure, say N.
-
-config PHY_CYGNUS_PCIE
- tristate "Broadcom Cygnus PCIe PHY driver"
- depends on OF && (ARCH_BCM_CYGNUS || COMPILE_TEST)
- select GENERIC_PHY
- default ARCH_BCM_CYGNUS
- help
- Enable this to support the Broadcom Cygnus PCIe PHY.
- If unsure, say N.
-
+source "drivers/phy/allwinner/Kconfig"
+source "drivers/phy/amlogic/Kconfig"
+source "drivers/phy/broadcom/Kconfig"
+source "drivers/phy/hisilicon/Kconfig"
+source "drivers/phy/marvell/Kconfig"
+source "drivers/phy/motorola/Kconfig"
+source "drivers/phy/qualcomm/Kconfig"
+source "drivers/phy/renesas/Kconfig"
+source "drivers/phy/rockchip/Kconfig"
+source "drivers/phy/samsung/Kconfig"
+source "drivers/phy/st/Kconfig"
source "drivers/phy/tegra/Kconfig"
-
-config PHY_NS2_PCIE
- tristate "Broadcom Northstar2 PCIe PHY driver"
- depends on OF && MDIO_BUS_MUX_BCM_IPROC
- select GENERIC_PHY
- default ARCH_BCM_IPROC
- help
- Enable this to support the Broadcom Northstar2 PCIe PHY.
- If unsure, say N.
-
-config PHY_MESON8B_USB2
- tristate "Meson8b and GXBB USB2 PHY driver"
- default ARCH_MESON
- depends on OF && (ARCH_MESON || COMPILE_TEST)
- depends on USB_SUPPORT
- select USB_COMMON
- select GENERIC_PHY
- help
- Enable this to support the Meson USB2 PHYs found in Meson8b
- and GXBB SoCs.
- If unsure, say N.
+source "drivers/phy/ti/Kconfig"
endmenu
diff --git a/drivers/phy/Makefile b/drivers/phy/Makefile
index f8047b4639fa..f252201e0ec9 100644
--- a/drivers/phy/Makefile
+++ b/drivers/phy/Makefile
@@ -3,64 +3,21 @@
#
obj-$(CONFIG_GENERIC_PHY) += phy-core.o
-obj-$(CONFIG_PHY_BCM_NS_USB2) += phy-bcm-ns-usb2.o
-obj-$(CONFIG_PHY_BCM_NS_USB3) += phy-bcm-ns-usb3.o
-obj-$(CONFIG_PHY_BERLIN_USB) += phy-berlin-usb.o
-obj-$(CONFIG_PHY_BERLIN_SATA) += phy-berlin-sata.o
-obj-$(CONFIG_PHY_DA8XX_USB) += phy-da8xx-usb.o
-obj-$(CONFIG_PHY_DM816X_USB) += phy-dm816x-usb.o
-obj-$(CONFIG_ARMADA375_USBCLUSTER_PHY) += phy-armada375-usb2.o
-obj-$(CONFIG_BCM_KONA_USB2_PHY) += phy-bcm-kona-usb2.o
-obj-$(CONFIG_PHY_EXYNOS_DP_VIDEO) += phy-exynos-dp-video.o
-obj-$(CONFIG_PHY_EXYNOS_MIPI_VIDEO) += phy-exynos-mipi-video.o
obj-$(CONFIG_PHY_LPC18XX_USB_OTG) += phy-lpc18xx-usb-otg.o
-obj-$(CONFIG_PHY_PXA_28NM_USB2) += phy-pxa-28nm-usb2.o
-obj-$(CONFIG_PHY_PXA_28NM_HSIC) += phy-pxa-28nm-hsic.o
-obj-$(CONFIG_PHY_MVEBU_SATA) += phy-mvebu-sata.o
-obj-$(CONFIG_PHY_MIPHY28LP) += phy-miphy28lp.o
-obj-$(CONFIG_PHY_RCAR_GEN2) += phy-rcar-gen2.o
-obj-$(CONFIG_PHY_RCAR_GEN3_USB2) += phy-rcar-gen3-usb2.o
-obj-$(CONFIG_OMAP_CONTROL_PHY) += phy-omap-control.o
-obj-$(CONFIG_OMAP_USB2) += phy-omap-usb2.o
-obj-$(CONFIG_TI_PIPE3) += phy-ti-pipe3.o
-obj-$(CONFIG_TWL4030_USB) += phy-twl4030-usb.o
-obj-$(CONFIG_PHY_EXYNOS5250_SATA) += phy-exynos5250-sata.o
-obj-$(CONFIG_PHY_HIX5HD2_SATA) += phy-hix5hd2-sata.o
-obj-$(CONFIG_PHY_HI6220_USB) += phy-hi6220-usb.o
obj-$(CONFIG_PHY_MT65XX_USB3) += phy-mt65xx-usb3.o
-obj-$(CONFIG_PHY_SUN4I_USB) += phy-sun4i-usb.o
-obj-$(CONFIG_PHY_SUN9I_USB) += phy-sun9i-usb.o
-obj-$(CONFIG_PHY_SAMSUNG_USB2) += phy-exynos-usb2.o
-phy-exynos-usb2-y += phy-samsung-usb2.o
-phy-exynos-usb2-$(CONFIG_PHY_EXYNOS4210_USB2) += phy-exynos4210-usb2.o
-phy-exynos-usb2-$(CONFIG_PHY_EXYNOS4X12_USB2) += phy-exynos4x12-usb2.o
-phy-exynos-usb2-$(CONFIG_PHY_EXYNOS5250_USB2) += phy-exynos5250-usb2.o
-phy-exynos-usb2-$(CONFIG_PHY_S5PV210_USB2) += phy-s5pv210-usb2.o
-obj-$(CONFIG_PHY_EXYNOS5_USBDRD) += phy-exynos5-usbdrd.o
-obj-$(CONFIG_PHY_EXYNOS_PCIE) += phy-exynos-pcie.o
-obj-$(CONFIG_PHY_QCOM_APQ8064_SATA) += phy-qcom-apq8064-sata.o
-obj-$(CONFIG_PHY_ROCKCHIP_USB) += phy-rockchip-usb.o
-obj-$(CONFIG_PHY_ROCKCHIP_INNO_USB2) += phy-rockchip-inno-usb2.o
-obj-$(CONFIG_PHY_ROCKCHIP_EMMC) += phy-rockchip-emmc.o
-obj-$(CONFIG_PHY_ROCKCHIP_PCIE) += phy-rockchip-pcie.o
-obj-$(CONFIG_PHY_ROCKCHIP_DP) += phy-rockchip-dp.o
-obj-$(CONFIG_PHY_ROCKCHIP_TYPEC) += phy-rockchip-typec.o
-obj-$(CONFIG_PHY_QCOM_IPQ806X_SATA) += phy-qcom-ipq806x-sata.o
-obj-$(CONFIG_PHY_ST_SPEAR1310_MIPHY) += phy-spear1310-miphy.o
-obj-$(CONFIG_PHY_ST_SPEAR1340_MIPHY) += phy-spear1340-miphy.o
obj-$(CONFIG_PHY_XGENE) += phy-xgene.o
-obj-$(CONFIG_PHY_STIH407_USB) += phy-stih407-usb.o
-obj-$(CONFIG_PHY_QCOM_QMP) += phy-qcom-qmp.o
-obj-$(CONFIG_PHY_QCOM_QUSB2) += phy-qcom-qusb2.o
-obj-$(CONFIG_PHY_QCOM_UFS) += phy-qcom-ufs.o
-obj-$(CONFIG_PHY_QCOM_UFS) += phy-qcom-ufs-qmp-20nm.o
-obj-$(CONFIG_PHY_QCOM_UFS) += phy-qcom-ufs-qmp-14nm.o
-obj-$(CONFIG_PHY_QCOM_USB_HS) += phy-qcom-usb-hs.o
-obj-$(CONFIG_PHY_QCOM_USB_HSIC) += phy-qcom-usb-hsic.o
-obj-$(CONFIG_PHY_TUSB1210) += phy-tusb1210.o
-obj-$(CONFIG_PHY_BRCM_SATA) += phy-brcm-sata.o
obj-$(CONFIG_PHY_PISTACHIO_USB) += phy-pistachio-usb.o
-obj-$(CONFIG_PHY_CYGNUS_PCIE) += phy-bcm-cygnus-pcie.o
-obj-$(CONFIG_ARCH_TEGRA) += tegra/
-obj-$(CONFIG_PHY_NS2_PCIE) += phy-bcm-ns2-pcie.o
-obj-$(CONFIG_PHY_MESON8B_USB2) += phy-meson8b-usb2.o
+
+obj-$(CONFIG_ARCH_SUNXI) += allwinner/
+obj-$(CONFIG_ARCH_MESON) += amlogic/
+obj-$(CONFIG_ARCH_RENESAS) += renesas/
+obj-$(CONFIG_ARCH_ROCKCHIP) += rockchip/
+obj-$(CONFIG_ARCH_TEGRA) += tegra/
+obj-y += broadcom/ \
+ hisilicon/ \
+ marvell/ \
+ motorola/ \
+ qualcomm/ \
+ samsung/ \
+ st/ \
+ ti/
diff --git a/drivers/phy/allwinner/Kconfig b/drivers/phy/allwinner/Kconfig
new file mode 100644
index 000000000000..cdc1e745ba47
--- /dev/null
+++ b/drivers/phy/allwinner/Kconfig
@@ -0,0 +1,31 @@
+#
+# Phy drivers for Allwinner platforms
+#
+config PHY_SUN4I_USB
+ tristate "Allwinner sunxi SoC USB PHY driver"
+ depends on ARCH_SUNXI && HAS_IOMEM && OF
+ depends on RESET_CONTROLLER
+ depends on EXTCON
+ depends on POWER_SUPPLY
+ depends on USB_SUPPORT
+ select GENERIC_PHY
+ select USB_COMMON
+ help
+ Enable this to support the transceiver that is part of Allwinner
+ sunxi SoCs.
+
+ This driver controls the entire USB PHY block, both the USB OTG
+ parts, as well as the 2 regular USB 2 host PHYs.
+
+config PHY_SUN9I_USB
+ tristate "Allwinner sun9i SoC USB PHY driver"
+ depends on ARCH_SUNXI && HAS_IOMEM && OF
+ depends on RESET_CONTROLLER
+ depends on USB_SUPPORT
+ select USB_COMMON
+ select GENERIC_PHY
+ help
+ Enable this to support the transceiver that is part of Allwinner
+ sun9i SoCs.
+
+ This driver controls each individual USB 2 host PHY.
diff --git a/drivers/phy/allwinner/Makefile b/drivers/phy/allwinner/Makefile
new file mode 100644
index 000000000000..8605529c01a1
--- /dev/null
+++ b/drivers/phy/allwinner/Makefile
@@ -0,0 +1,2 @@
+obj-$(CONFIG_PHY_SUN4I_USB) += phy-sun4i-usb.o
+obj-$(CONFIG_PHY_SUN9I_USB) += phy-sun9i-usb.o
diff --git a/drivers/phy/phy-sun4i-usb.c b/drivers/phy/allwinner/phy-sun4i-usb.c
index bbf06cfe5898..bbf06cfe5898 100644
--- a/drivers/phy/phy-sun4i-usb.c
+++ b/drivers/phy/allwinner/phy-sun4i-usb.c
diff --git a/drivers/phy/phy-sun9i-usb.c b/drivers/phy/allwinner/phy-sun9i-usb.c
index 28fce4bce638..28fce4bce638 100644
--- a/drivers/phy/phy-sun9i-usb.c
+++ b/drivers/phy/allwinner/phy-sun9i-usb.c
diff --git a/drivers/phy/amlogic/Kconfig b/drivers/phy/amlogic/Kconfig
new file mode 100644
index 000000000000..cb8f4501652b
--- /dev/null
+++ b/drivers/phy/amlogic/Kconfig
@@ -0,0 +1,27 @@
+#
+# Phy drivers for Amlogic platforms
+#
+config PHY_MESON8B_USB2
+ tristate "Meson8, Meson8b and GXBB USB2 PHY driver"
+ default ARCH_MESON
+ depends on OF && (ARCH_MESON || COMPILE_TEST)
+ depends on USB_SUPPORT
+ select USB_COMMON
+ select GENERIC_PHY
+ help
+ Enable this to support the Meson USB2 PHYs found in Meson8,
+ Meson8b and GXBB SoCs.
+ If unsure, say N.
+
+config PHY_MESON_GXL_USB2
+ tristate "Meson GXL and GXM USB2 PHY drivers"
+ default ARCH_MESON
+ depends on OF && (ARCH_MESON || COMPILE_TEST)
+ depends on USB_SUPPORT
+ select USB_COMMON
+ select GENERIC_PHY
+ select REGMAP_MMIO
+ help
+ Enable this to support the Meson USB2 PHYs found in Meson
+ GXL and GXM SoCs.
+ If unsure, say N.
diff --git a/drivers/phy/amlogic/Makefile b/drivers/phy/amlogic/Makefile
new file mode 100644
index 000000000000..cfdc98715c30
--- /dev/null
+++ b/drivers/phy/amlogic/Makefile
@@ -0,0 +1,2 @@
+obj-$(CONFIG_PHY_MESON8B_USB2) += phy-meson8b-usb2.o
+obj-$(CONFIG_PHY_MESON_GXL_USB2) += phy-meson-gxl-usb2.o
diff --git a/drivers/phy/amlogic/phy-meson-gxl-usb2.c b/drivers/phy/amlogic/phy-meson-gxl-usb2.c
new file mode 100644
index 000000000000..e90c4ee25dfe
--- /dev/null
+++ b/drivers/phy/amlogic/phy-meson-gxl-usb2.c
@@ -0,0 +1,273 @@
+/*
+ * Meson GXL and GXM USB2 PHY driver
+ *
+ * Copyright (C) 2017 Martin Blumenstingl <martin.blumenstingl@googlemail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <linux/delay.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/of_device.h>
+#include <linux/regmap.h>
+#include <linux/phy/phy.h>
+#include <linux/platform_device.h>
+#include <linux/usb/of.h>
+
+/* bits [31:27] are read-only */
+#define U2P_R0 0x0
+ #define U2P_R0_BYPASS_SEL BIT(0)
+ #define U2P_R0_BYPASS_DM_EN BIT(1)
+ #define U2P_R0_BYPASS_DP_EN BIT(2)
+ #define U2P_R0_TXBITSTUFF_ENH BIT(3)
+ #define U2P_R0_TXBITSTUFF_EN BIT(4)
+ #define U2P_R0_DM_PULLDOWN BIT(5)
+ #define U2P_R0_DP_PULLDOWN BIT(6)
+ #define U2P_R0_DP_VBUS_VLD_EXT_SEL BIT(7)
+ #define U2P_R0_DP_VBUS_VLD_EXT BIT(8)
+ #define U2P_R0_ADP_PRB_EN BIT(9)
+ #define U2P_R0_ADP_DISCHARGE BIT(10)
+ #define U2P_R0_ADP_CHARGE BIT(11)
+ #define U2P_R0_DRV_VBUS BIT(12)
+ #define U2P_R0_ID_PULLUP BIT(13)
+ #define U2P_R0_LOOPBACK_EN_B BIT(14)
+ #define U2P_R0_OTG_DISABLE BIT(15)
+ #define U2P_R0_COMMON_ONN BIT(16)
+ #define U2P_R0_FSEL_MASK GENMASK(19, 17)
+ #define U2P_R0_REF_CLK_SEL_MASK GENMASK(21, 20)
+ #define U2P_R0_POWER_ON_RESET BIT(22)
+ #define U2P_R0_V_ATE_TEST_EN_B_MASK GENMASK(24, 23)
+ #define U2P_R0_ID_SET_ID_DQ BIT(25)
+ #define U2P_R0_ATE_RESET BIT(26)
+ #define U2P_R0_FSV_MINUS BIT(27)
+ #define U2P_R0_FSV_PLUS BIT(28)
+ #define U2P_R0_BYPASS_DM_DATA BIT(29)
+ #define U2P_R0_BYPASS_DP_DATA BIT(30)
+
+#define U2P_R1 0x4
+ #define U2P_R1_BURN_IN_TEST BIT(0)
+ #define U2P_R1_ACA_ENABLE BIT(1)
+ #define U2P_R1_DCD_ENABLE BIT(2)
+ #define U2P_R1_VDAT_SRC_EN_B BIT(3)
+ #define U2P_R1_VDAT_DET_EN_B BIT(4)
+ #define U2P_R1_CHARGES_SEL BIT(5)
+ #define U2P_R1_TX_PREEMP_PULSE_TUNE BIT(6)
+ #define U2P_R1_TX_PREEMP_AMP_TUNE_MASK GENMASK(8, 7)
+ #define U2P_R1_TX_RES_TUNE_MASK GENMASK(10, 9)
+ #define U2P_R1_TX_RISE_TUNE_MASK GENMASK(12, 11)
+ #define U2P_R1_TX_VREF_TUNE_MASK GENMASK(16, 13)
+ #define U2P_R1_TX_FSLS_TUNE_MASK GENMASK(20, 17)
+ #define U2P_R1_TX_HSXV_TUNE_MASK GENMASK(22, 21)
+ #define U2P_R1_OTG_TUNE_MASK GENMASK(25, 23)
+ #define U2P_R1_SQRX_TUNE_MASK GENMASK(28, 26)
+ #define U2P_R1_COMP_DIS_TUNE_MASK GENMASK(31, 29)
+
+/* bits [31:14] are read-only */
+#define U2P_R2 0x8
+ #define U2P_R2_DATA_IN_MASK GENMASK(3, 0)
+ #define U2P_R2_DATA_IN_EN_MASK GENMASK(7, 4)
+ #define U2P_R2_ADDR_MASK GENMASK(11, 8)
+ #define U2P_R2_DATA_OUT_SEL BIT(12)
+ #define U2P_R2_CLK BIT(13)
+ #define U2P_R2_DATA_OUT_MASK GENMASK(17, 14)
+ #define U2P_R2_ACA_PIN_RANGE_C BIT(18)
+ #define U2P_R2_ACA_PIN_RANGE_B BIT(19)
+ #define U2P_R2_ACA_PIN_RANGE_A BIT(20)
+ #define U2P_R2_ACA_PIN_GND BIT(21)
+ #define U2P_R2_ACA_PIN_FLOAT BIT(22)
+ #define U2P_R2_CHARGE_DETECT BIT(23)
+ #define U2P_R2_DEVICE_SESSION_VALID BIT(24)
+ #define U2P_R2_ADP_PROBE BIT(25)
+ #define U2P_R2_ADP_SENSE BIT(26)
+ #define U2P_R2_SESSION_END BIT(27)
+ #define U2P_R2_VBUS_VALID BIT(28)
+ #define U2P_R2_B_VALID BIT(29)
+ #define U2P_R2_A_VALID BIT(30)
+ #define U2P_R2_ID_DIG BIT(31)
+
+#define U2P_R3 0xc
+
+#define RESET_COMPLETE_TIME 500
+
+struct phy_meson_gxl_usb2_priv {
+ struct regmap *regmap;
+ enum phy_mode mode;
+ int is_enabled;
+};
+
+static const struct regmap_config phy_meson_gxl_usb2_regmap_conf = {
+ .reg_bits = 8,
+ .val_bits = 32,
+ .reg_stride = 4,
+ .max_register = U2P_R3,
+};
+
+static int phy_meson_gxl_usb2_reset(struct phy *phy)
+{
+ struct phy_meson_gxl_usb2_priv *priv = phy_get_drvdata(phy);
+
+ if (priv->is_enabled) {
+ /* reset the PHY and wait until settings are stabilized */
+ regmap_update_bits(priv->regmap, U2P_R0, U2P_R0_POWER_ON_RESET,
+ U2P_R0_POWER_ON_RESET);
+ udelay(RESET_COMPLETE_TIME);
+ regmap_update_bits(priv->regmap, U2P_R0, U2P_R0_POWER_ON_RESET,
+ 0);
+ udelay(RESET_COMPLETE_TIME);
+ }
+
+ return 0;
+}
+
+static int phy_meson_gxl_usb2_set_mode(struct phy *phy, enum phy_mode mode)
+{
+ struct phy_meson_gxl_usb2_priv *priv = phy_get_drvdata(phy);
+
+ switch (mode) {
+ case PHY_MODE_USB_HOST:
+ case PHY_MODE_USB_OTG:
+ regmap_update_bits(priv->regmap, U2P_R0, U2P_R0_DM_PULLDOWN,
+ U2P_R0_DM_PULLDOWN);
+ regmap_update_bits(priv->regmap, U2P_R0, U2P_R0_DP_PULLDOWN,
+ U2P_R0_DP_PULLDOWN);
+ regmap_update_bits(priv->regmap, U2P_R0, U2P_R0_ID_PULLUP, 0);
+ break;
+
+ case PHY_MODE_USB_DEVICE:
+ regmap_update_bits(priv->regmap, U2P_R0, U2P_R0_DM_PULLDOWN,
+ 0);
+ regmap_update_bits(priv->regmap, U2P_R0, U2P_R0_DP_PULLDOWN,
+ 0);
+ regmap_update_bits(priv->regmap, U2P_R0, U2P_R0_ID_PULLUP,
+ U2P_R0_ID_PULLUP);
+ break;
+
+ default:
+ return -EINVAL;
+ }
+
+ phy_meson_gxl_usb2_reset(phy);
+
+ priv->mode = mode;
+
+ return 0;
+}
+
+static int phy_meson_gxl_usb2_power_off(struct phy *phy)
+{
+ struct phy_meson_gxl_usb2_priv *priv = phy_get_drvdata(phy);
+
+ priv->is_enabled = 0;
+
+ /* power off the PHY by putting it into reset mode */
+ regmap_update_bits(priv->regmap, U2P_R0, U2P_R0_POWER_ON_RESET,
+ U2P_R0_POWER_ON_RESET);
+
+ return 0;
+}
+
+static int phy_meson_gxl_usb2_power_on(struct phy *phy)
+{
+ struct phy_meson_gxl_usb2_priv *priv = phy_get_drvdata(phy);
+ int ret;
+
+ priv->is_enabled = 1;
+
+ /* power on the PHY by taking it out of reset mode */
+ regmap_update_bits(priv->regmap, U2P_R0, U2P_R0_POWER_ON_RESET, 0);
+
+ ret = phy_meson_gxl_usb2_set_mode(phy, priv->mode);
+ if (ret) {
+ phy_meson_gxl_usb2_power_off(phy);
+
+ dev_err(&phy->dev, "Failed to initialize PHY with mode %d\n",
+ priv->mode);
+ return ret;
+ }
+
+ return 0;
+}
+
+static const struct phy_ops phy_meson_gxl_usb2_ops = {
+ .power_on = phy_meson_gxl_usb2_power_on,
+ .power_off = phy_meson_gxl_usb2_power_off,
+ .set_mode = phy_meson_gxl_usb2_set_mode,
+ .reset = phy_meson_gxl_usb2_reset,
+ .owner = THIS_MODULE,
+};
+
+static int phy_meson_gxl_usb2_probe(struct platform_device *pdev)
+{
+ struct device *dev = &pdev->dev;
+ struct phy_provider *phy_provider;
+ struct resource *res;
+ struct phy_meson_gxl_usb2_priv *priv;
+ struct phy *phy;
+ void __iomem *base;
+
+ priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
+ if (!priv)
+ return -ENOMEM;
+
+ platform_set_drvdata(pdev, priv);
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ base = devm_ioremap_resource(dev, res);
+ if (IS_ERR(base))
+ return PTR_ERR(base);
+
+ switch (of_usb_get_dr_mode_by_phy(dev->of_node, -1)) {
+ case USB_DR_MODE_PERIPHERAL:
+ priv->mode = PHY_MODE_USB_DEVICE;
+ break;
+ case USB_DR_MODE_OTG:
+ priv->mode = PHY_MODE_USB_OTG;
+ break;
+ case USB_DR_MODE_HOST:
+ default:
+ priv->mode = PHY_MODE_USB_HOST;
+ break;
+ }
+
+ priv->regmap = devm_regmap_init_mmio(dev, base,
+ &phy_meson_gxl_usb2_regmap_conf);
+ if (IS_ERR(priv->regmap))
+ return PTR_ERR(priv->regmap);
+
+ phy = devm_phy_create(dev, NULL, &phy_meson_gxl_usb2_ops);
+ if (IS_ERR(phy)) {
+ dev_err(dev, "failed to create PHY\n");
+ return PTR_ERR(phy);
+ }
+
+ phy_set_drvdata(phy, priv);
+
+ phy_provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate);
+
+ return PTR_ERR_OR_ZERO(phy_provider);
+}
+
+static const struct of_device_id phy_meson_gxl_usb2_of_match[] = {
+ { .compatible = "amlogic,meson-gxl-usb2-phy", },
+ { },
+};
+MODULE_DEVICE_TABLE(of, phy_meson_gxl_usb2_of_match);
+
+static struct platform_driver phy_meson_gxl_usb2_driver = {
+ .probe = phy_meson_gxl_usb2_probe,
+ .driver = {
+ .name = "phy-meson-gxl-usb2",
+ .of_match_table = phy_meson_gxl_usb2_of_match,
+ },
+};
+module_platform_driver(phy_meson_gxl_usb2_driver);
+
+MODULE_AUTHOR("Martin Blumenstingl <martin.blumenstingl@googlemail.com>");
+MODULE_DESCRIPTION("Meson GXL and GXM USB2 PHY driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/phy/phy-meson8b-usb2.c b/drivers/phy/amlogic/phy-meson8b-usb2.c
index 30f56a6a411f..9c01b7e19b06 100644
--- a/drivers/phy/phy-meson8b-usb2.c
+++ b/drivers/phy/amlogic/phy-meson8b-usb2.c
@@ -1,5 +1,5 @@
/*
- * Meson8b and GXBB USB2 PHY driver
+ * Meson8, Meson8b and GXBB USB2 PHY driver
*
* Copyright (C) 2016 Martin Blumenstingl <martin.blumenstingl@googlemail.com>
*
@@ -266,6 +266,7 @@ static int phy_meson8b_usb2_probe(struct platform_device *pdev)
}
static const struct of_device_id phy_meson8b_usb2_of_match[] = {
+ { .compatible = "amlogic,meson8-usb2-phy", },
{ .compatible = "amlogic,meson8b-usb2-phy", },
{ .compatible = "amlogic,meson-gxbb-usb2-phy", },
{ },
@@ -282,5 +283,5 @@ static struct platform_driver phy_meson8b_usb2_driver = {
module_platform_driver(phy_meson8b_usb2_driver);
MODULE_AUTHOR("Martin Blumenstingl <martin.blumenstingl@googlemail.com>");
-MODULE_DESCRIPTION("Meson8b and GXBB USB2 PHY driver");
+MODULE_DESCRIPTION("Meson8, Meson8b and GXBB USB2 PHY driver");
MODULE_LICENSE("GPL");
diff --git a/drivers/phy/broadcom/Kconfig b/drivers/phy/broadcom/Kconfig
new file mode 100644
index 000000000000..37371b89b14f
--- /dev/null
+++ b/drivers/phy/broadcom/Kconfig
@@ -0,0 +1,69 @@
+#
+# Phy drivers for Broadcom platforms
+#
+config PHY_CYGNUS_PCIE
+ tristate "Broadcom Cygnus PCIe PHY driver"
+ depends on OF && (ARCH_BCM_CYGNUS || COMPILE_TEST)
+ select GENERIC_PHY
+ default ARCH_BCM_CYGNUS
+ help
+ Enable this to support the Broadcom Cygnus PCIe PHY.
+ If unsure, say N.
+
+config BCM_KONA_USB2_PHY
+ tristate "Broadcom Kona USB2 PHY Driver"
+ depends on HAS_IOMEM
+ select GENERIC_PHY
+ help
+ Enable this to support the Broadcom Kona USB 2.0 PHY.
+
+config PHY_BCM_NS_USB2
+ tristate "Broadcom Northstar USB 2.0 PHY Driver"
+ depends on ARCH_BCM_IPROC || COMPILE_TEST
+ depends on HAS_IOMEM && OF
+ select GENERIC_PHY
+ help
+ Enable this to support Broadcom USB 2.0 PHY connected to the USB
+ controller on Northstar family.
+
+config PHY_BCM_NS_USB3
+ tristate "Broadcom Northstar USB 3.0 PHY Driver"
+ depends on ARCH_BCM_IPROC || COMPILE_TEST
+ depends on HAS_IOMEM && OF
+ select GENERIC_PHY
+ select MDIO_DEVICE
+ help
+ Enable this to support Broadcom USB 3.0 PHY connected to the USB
+ controller on Northstar family.
+
+config PHY_NS2_PCIE
+ tristate "Broadcom Northstar2 PCIe PHY driver"
+ depends on OF && MDIO_BUS_MUX_BCM_IPROC
+ select GENERIC_PHY
+ default ARCH_BCM_IPROC
+ help
+ Enable this to support the Broadcom Northstar2 PCIe PHY.
+ If unsure, say N.
+
+config PHY_NS2_USB_DRD
+ tristate "Broadcom Northstar2 USB DRD PHY support"
+ depends on OF && (ARCH_BCM_IPROC || COMPILE_TEST)
+ select GENERIC_PHY
+ select EXTCON
+ default ARCH_BCM_IPROC
+ help
+ Enable this to support the Broadcom Northstar2 USB DRD PHY.
+ This driver initializes the PHY in either HOST or DEVICE mode.
+ The host or device configuration is read from device tree.
+
+ If unsure, say N.
+
+config PHY_BRCM_SATA
+ tristate "Broadcom SATA PHY driver"
+ depends on ARCH_BRCMSTB || ARCH_BCM_IPROC || BMIPS_GENERIC || COMPILE_TEST
+ depends on OF
+ select GENERIC_PHY
+ default ARCH_BCM_IPROC
+ help
+ Enable this to support the Broadcom SATA PHY.
+ If unsure, say N.
diff --git a/drivers/phy/broadcom/Makefile b/drivers/phy/broadcom/Makefile
new file mode 100644
index 000000000000..4eb82ec8d491
--- /dev/null
+++ b/drivers/phy/broadcom/Makefile
@@ -0,0 +1,7 @@
+obj-$(CONFIG_PHY_CYGNUS_PCIE) += phy-bcm-cygnus-pcie.o
+obj-$(CONFIG_BCM_KONA_USB2_PHY) += phy-bcm-kona-usb2.o
+obj-$(CONFIG_PHY_BCM_NS_USB2) += phy-bcm-ns-usb2.o
+obj-$(CONFIG_PHY_BCM_NS_USB3) += phy-bcm-ns-usb3.o
+obj-$(CONFIG_PHY_NS2_PCIE) += phy-bcm-ns2-pcie.o
+obj-$(CONFIG_PHY_NS2_USB_DRD) += phy-bcm-ns2-usbdrd.o
+obj-$(CONFIG_PHY_BRCM_SATA) += phy-brcm-sata.o
diff --git a/drivers/phy/phy-bcm-cygnus-pcie.c b/drivers/phy/broadcom/phy-bcm-cygnus-pcie.c
index 0f4ac5d63cff..0f4ac5d63cff 100644
--- a/drivers/phy/phy-bcm-cygnus-pcie.c
+++ b/drivers/phy/broadcom/phy-bcm-cygnus-pcie.c
diff --git a/drivers/phy/phy-bcm-kona-usb2.c b/drivers/phy/broadcom/phy-bcm-kona-usb2.c
index 7b67fe49e30b..7b67fe49e30b 100644
--- a/drivers/phy/phy-bcm-kona-usb2.c
+++ b/drivers/phy/broadcom/phy-bcm-kona-usb2.c
diff --git a/drivers/phy/phy-bcm-ns-usb2.c b/drivers/phy/broadcom/phy-bcm-ns-usb2.c
index 58dff80e9386..58dff80e9386 100644
--- a/drivers/phy/phy-bcm-ns-usb2.c
+++ b/drivers/phy/broadcom/phy-bcm-ns-usb2.c
diff --git a/drivers/phy/phy-bcm-ns-usb3.c b/drivers/phy/broadcom/phy-bcm-ns-usb3.c
index 22b5e7047fa6..a53ae128eadf 100644
--- a/drivers/phy/phy-bcm-ns-usb3.c
+++ b/drivers/phy/broadcom/phy-bcm-ns-usb3.c
@@ -16,7 +16,9 @@
#include <linux/bcma/bcma.h>
#include <linux/delay.h>
#include <linux/err.h>
+#include <linux/mdio.h>
#include <linux/module.h>
+#include <linux/of_address.h>
#include <linux/of_platform.h>
#include <linux/platform_device.h>
#include <linux/phy/phy.h>
@@ -52,7 +54,10 @@ struct bcm_ns_usb3 {
enum bcm_ns_family family;
void __iomem *dmp;
void __iomem *ccb_mii;
+ struct mdio_device *mdiodev;
struct phy *phy;
+
+ int (*phy_write)(struct bcm_ns_usb3 *usb3, u16 reg, u16 value);
};
static const struct of_device_id bcm_ns_usb3_id_table[] = {
@@ -68,63 +73,16 @@ static const struct of_device_id bcm_ns_usb3_id_table[] = {
};
MODULE_DEVICE_TABLE(of, bcm_ns_usb3_id_table);
-static int bcm_ns_usb3_wait_reg(struct bcm_ns_usb3 *usb3, void __iomem *addr,
- u32 mask, u32 value, unsigned long timeout)
-{
- unsigned long deadline = jiffies + timeout;
- u32 val;
-
- do {
- val = readl(addr);
- if ((val & mask) == value)
- return 0;
- cpu_relax();
- udelay(10);
- } while (!time_after_eq(jiffies, deadline));
-
- dev_err(usb3->dev, "Timeout waiting for register %p\n", addr);
-
- return -EBUSY;
-}
-
-static inline int bcm_ns_usb3_mii_mng_wait_idle(struct bcm_ns_usb3 *usb3)
-{
- return bcm_ns_usb3_wait_reg(usb3, usb3->ccb_mii + BCMA_CCB_MII_MNG_CTL,
- 0x0100, 0x0000,
- usecs_to_jiffies(BCM_NS_USB3_MII_MNG_TIMEOUT_US));
-}
-
static int bcm_ns_usb3_mdio_phy_write(struct bcm_ns_usb3 *usb3, u16 reg,
u16 value)
{
- u32 tmp = 0;
- int err;
-
- err = bcm_ns_usb3_mii_mng_wait_idle(usb3);
- if (err < 0) {
- dev_err(usb3->dev, "Couldn't write 0x%08x value\n", value);
- return err;
- }
-
- /* TODO: Use a proper MDIO bus layer */
- tmp |= 0x58020000; /* Magic value for MDIO PHY write */
- tmp |= reg << 18;
- tmp |= value;
- writel(tmp, usb3->ccb_mii + BCMA_CCB_MII_MNG_CMD_DATA);
-
- return 0;
+ return usb3->phy_write(usb3, reg, value);
}
static int bcm_ns_usb3_phy_init_ns_bx(struct bcm_ns_usb3 *usb3)
{
int err;
- /* Enable MDIO. Setting MDCDIV as 26 */
- writel(0x0000009a, usb3->ccb_mii + BCMA_CCB_MII_MNG_CTL);
-
- /* Wait for MDIO? */
- udelay(2);
-
/* USB3 PLL Block */
err = bcm_ns_usb3_mdio_phy_write(usb3, BCM_NS_USB3_PHY_BASE_ADDR_REG,
BCM_NS_USB3_PHY_PLL30_BLOCK);
@@ -143,9 +101,6 @@ static int bcm_ns_usb3_phy_init_ns_bx(struct bcm_ns_usb3 *usb3)
/* Deaaserting PLL Reset */
bcm_ns_usb3_mdio_phy_write(usb3, BCM_NS_USB3_PLLA_CONTROL1, 0x8000);
- /* Waiting MII Mgt interface idle */
- bcm_ns_usb3_mii_mng_wait_idle(usb3);
-
/* Deasserting USB3 system reset */
writel(0, usb3->dmp + BCMA_RESET_CTL);
@@ -169,9 +124,6 @@ static int bcm_ns_usb3_phy_init_ns_bx(struct bcm_ns_usb3 *usb3)
/* Enabling SSC */
bcm_ns_usb3_mdio_phy_write(usb3, BCM_NS_USB3_TX_PMD_CONTROL1, 0x1003);
- /* Waiting MII Mgt interface idle */
- bcm_ns_usb3_mii_mng_wait_idle(usb3);
-
return 0;
}
@@ -179,12 +131,6 @@ static int bcm_ns_usb3_phy_init_ns_ax(struct bcm_ns_usb3 *usb3)
{
int err;
- /* Enable MDIO. Setting MDCDIV as 26 */
- writel(0x0000009a, usb3->ccb_mii + BCMA_CCB_MII_MNG_CTL);
-
- /* Wait for MDIO? */
- udelay(2);
-
/* PLL30 block */
err = bcm_ns_usb3_mdio_phy_write(usb3, BCM_NS_USB3_PHY_BASE_ADDR_REG,
BCM_NS_USB3_PHY_PLL30_BLOCK);
@@ -205,9 +151,6 @@ static int bcm_ns_usb3_phy_init_ns_ax(struct bcm_ns_usb3 *usb3)
bcm_ns_usb3_mdio_phy_write(usb3, BCM_NS_USB3_TX_PMD_CONTROL1, 0x1003);
- /* Waiting MII Mgt interface idle */
- bcm_ns_usb3_mii_mng_wait_idle(usb3);
-
/* Deasserting USB3 system reset */
writel(0, usb3->dmp + BCMA_RESET_CTL);
@@ -242,6 +185,128 @@ static const struct phy_ops ops = {
.owner = THIS_MODULE,
};
+/**************************************************
+ * MDIO driver code
+ **************************************************/
+
+static int bcm_ns_usb3_mdiodev_phy_write(struct bcm_ns_usb3 *usb3, u16 reg,
+ u16 value)
+{
+ struct mdio_device *mdiodev = usb3->mdiodev;
+
+ return mdiobus_write(mdiodev->bus, mdiodev->addr, reg, value);
+}
+
+static int bcm_ns_usb3_mdio_probe(struct mdio_device *mdiodev)
+{
+ struct device *dev = &mdiodev->dev;
+ const struct of_device_id *of_id;
+ struct phy_provider *phy_provider;
+ struct device_node *syscon_np;
+ struct bcm_ns_usb3 *usb3;
+ struct resource res;
+ int err;
+
+ usb3 = devm_kzalloc(dev, sizeof(*usb3), GFP_KERNEL);
+ if (!usb3)
+ return -ENOMEM;
+
+ usb3->dev = dev;
+ usb3->mdiodev = mdiodev;
+
+ of_id = of_match_device(bcm_ns_usb3_id_table, dev);
+ if (!of_id)
+ return -EINVAL;
+ usb3->family = (enum bcm_ns_family)of_id->data;
+
+ syscon_np = of_parse_phandle(dev->of_node, "usb3-dmp-syscon", 0);
+ err = of_address_to_resource(syscon_np, 0, &res);
+ of_node_put(syscon_np);
+ if (err)
+ return err;
+
+ usb3->dmp = devm_ioremap_resource(dev, &res);
+ if (IS_ERR(usb3->dmp)) {
+ dev_err(dev, "Failed to map DMP regs\n");
+ return PTR_ERR(usb3->dmp);
+ }
+
+ usb3->phy_write = bcm_ns_usb3_mdiodev_phy_write;
+
+ usb3->phy = devm_phy_create(dev, NULL, &ops);
+ if (IS_ERR(usb3->phy)) {
+ dev_err(dev, "Failed to create PHY\n");
+ return PTR_ERR(usb3->phy);
+ }
+
+ phy_set_drvdata(usb3->phy, usb3);
+
+ phy_provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate);
+
+ return PTR_ERR_OR_ZERO(phy_provider);
+}
+
+static struct mdio_driver bcm_ns_usb3_mdio_driver = {
+ .mdiodrv = {
+ .driver = {
+ .name = "bcm_ns_mdio_usb3",
+ .of_match_table = bcm_ns_usb3_id_table,
+ },
+ },
+ .probe = bcm_ns_usb3_mdio_probe,
+};
+
+/**************************************************
+ * Platform driver code
+ **************************************************/
+
+static int bcm_ns_usb3_wait_reg(struct bcm_ns_usb3 *usb3, void __iomem *addr,
+ u32 mask, u32 value, unsigned long timeout)
+{
+ unsigned long deadline = jiffies + timeout;
+ u32 val;
+
+ do {
+ val = readl(addr);
+ if ((val & mask) == value)
+ return 0;
+ cpu_relax();
+ udelay(10);
+ } while (!time_after_eq(jiffies, deadline));
+
+ dev_err(usb3->dev, "Timeout waiting for register %p\n", addr);
+
+ return -EBUSY;
+}
+
+static inline int bcm_ns_usb3_mii_mng_wait_idle(struct bcm_ns_usb3 *usb3)
+{
+ return bcm_ns_usb3_wait_reg(usb3, usb3->ccb_mii + BCMA_CCB_MII_MNG_CTL,
+ 0x0100, 0x0000,
+ usecs_to_jiffies(BCM_NS_USB3_MII_MNG_TIMEOUT_US));
+}
+
+static int bcm_ns_usb3_platform_phy_write(struct bcm_ns_usb3 *usb3, u16 reg,
+ u16 value)
+{
+ u32 tmp = 0;
+ int err;
+
+ err = bcm_ns_usb3_mii_mng_wait_idle(usb3);
+ if (err < 0) {
+ dev_err(usb3->dev, "Couldn't write 0x%08x value\n", value);
+ return err;
+ }
+
+ /* TODO: Use a proper MDIO bus layer */
+ tmp |= 0x58020000; /* Magic value for MDIO PHY write */
+ tmp |= reg << 18;
+ tmp |= value;
+ writel(tmp, usb3->ccb_mii + BCMA_CCB_MII_MNG_CMD_DATA);
+
+ return bcm_ns_usb3_mii_mng_wait_idle(usb3);
+}
+
static int bcm_ns_usb3_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
@@ -275,6 +340,14 @@ static int bcm_ns_usb3_probe(struct platform_device *pdev)
return PTR_ERR(usb3->ccb_mii);
}
+ /* Enable MDIO. Setting MDCDIV as 26 */
+ writel(0x0000009a, usb3->ccb_mii + BCMA_CCB_MII_MNG_CTL);
+
+ /* Wait for MDIO? */
+ udelay(2);
+
+ usb3->phy_write = bcm_ns_usb3_platform_phy_write;
+
usb3->phy = devm_phy_create(dev, NULL, &ops);
if (IS_ERR(usb3->phy)) {
dev_err(dev, "Failed to create PHY\n");
@@ -298,6 +371,35 @@ static struct platform_driver bcm_ns_usb3_driver = {
.of_match_table = bcm_ns_usb3_id_table,
},
};
-module_platform_driver(bcm_ns_usb3_driver);
+
+static int __init bcm_ns_usb3_module_init(void)
+{
+ int err;
+
+ /*
+ * For backward compatibility we register as MDIO and platform driver.
+ * After getting MDIO binding commonly used (e.g. switching all DT files
+ * to use it) we should deprecate the old binding and eventually drop
+ * support for it.
+ */
+
+ err = mdio_driver_register(&bcm_ns_usb3_mdio_driver);
+ if (err)
+ return err;
+
+ err = platform_driver_register(&bcm_ns_usb3_driver);
+ if (err)
+ mdio_driver_unregister(&bcm_ns_usb3_mdio_driver);
+
+ return err;
+}
+module_init(bcm_ns_usb3_module_init);
+
+static void __exit bcm_ns_usb3_module_exit(void)
+{
+ platform_driver_unregister(&bcm_ns_usb3_driver);
+ mdio_driver_unregister(&bcm_ns_usb3_mdio_driver);
+}
+module_exit(bcm_ns_usb3_module_exit)
MODULE_LICENSE("GPL v2");
diff --git a/drivers/phy/phy-bcm-ns2-pcie.c b/drivers/phy/broadcom/phy-bcm-ns2-pcie.c
index 4c7d11d2b378..4c7d11d2b378 100644
--- a/drivers/phy/phy-bcm-ns2-pcie.c
+++ b/drivers/phy/broadcom/phy-bcm-ns2-pcie.c
diff --git a/drivers/phy/broadcom/phy-bcm-ns2-usbdrd.c b/drivers/phy/broadcom/phy-bcm-ns2-usbdrd.c
new file mode 100644
index 000000000000..9ae59e223131
--- /dev/null
+++ b/drivers/phy/broadcom/phy-bcm-ns2-usbdrd.c
@@ -0,0 +1,437 @@
+/*
+ * Copyright (C) 2017 Broadcom
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation version 2.
+ *
+ * This program is distributed "as is" WITHOUT ANY WARRANTY of any
+ * kind, whether express or implied; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/delay.h>
+#include <linux/extcon.h>
+#include <linux/gpio.h>
+#include <linux/gpio/consumer.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/irq.h>
+#include <linux/mfd/syscon.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/phy/phy.h>
+#include <linux/platform_device.h>
+#include <linux/regmap.h>
+#include <linux/slab.h>
+#include <linux/workqueue.h>
+
+#define ICFG_DRD_AFE 0x0
+#define ICFG_MISC_STAT 0x18
+#define ICFG_DRD_P0CTL 0x1C
+#define ICFG_STRAP_CTRL 0x20
+#define ICFG_FSM_CTRL 0x24
+
+#define ICFG_DEV_BIT BIT(2)
+#define IDM_RST_BIT BIT(0)
+#define AFE_CORERDY_VDDC BIT(18)
+#define PHY_PLL_RESETB BIT(15)
+#define PHY_RESETB BIT(14)
+#define PHY_PLL_LOCK BIT(0)
+
+#define DRD_DEV_MODE BIT(20)
+#define OHCI_OVRCUR_POL BIT(11)
+#define ICFG_OFF_MODE BIT(6)
+#define PLL_LOCK_RETRY 1000
+
+#define EVT_DEVICE 0
+#define EVT_HOST 1
+
+#define DRD_HOST_MODE (BIT(2) | BIT(3))
+#define DRD_DEVICE_MODE (BIT(4) | BIT(5))
+#define DRD_HOST_VAL 0x803
+#define DRD_DEV_VAL 0x807
+#define GPIO_DELAY 20
+
+struct ns2_phy_data;
+struct ns2_phy_driver {
+ void __iomem *icfgdrd_regs;
+ void __iomem *idmdrd_rst_ctrl;
+ void __iomem *crmu_usb2_ctrl;
+ void __iomem *usb2h_strap_reg;
+ struct ns2_phy_data *data;
+ struct extcon_dev *edev;
+ struct gpio_desc *vbus_gpiod;
+ struct gpio_desc *id_gpiod;
+ int id_irq;
+ int vbus_irq;
+ unsigned long debounce_jiffies;
+ struct delayed_work wq_extcon;
+};
+
+struct ns2_phy_data {
+ struct ns2_phy_driver *driver;
+ struct phy *phy;
+ int new_state;
+};
+
+static const unsigned int usb_extcon_cable[] = {
+ EXTCON_USB,
+ EXTCON_USB_HOST,
+ EXTCON_NONE,
+};
+
+static inline int pll_lock_stat(u32 usb_reg, int reg_mask,
+ struct ns2_phy_driver *driver)
+{
+ int retry = PLL_LOCK_RETRY;
+ u32 val;
+
+ do {
+ udelay(1);
+ val = readl(driver->icfgdrd_regs + usb_reg);
+ if (val & reg_mask)
+ return 0;
+ } while (--retry > 0);
+
+ return -EBUSY;
+}
+
+static int ns2_drd_phy_init(struct phy *phy)
+{
+ struct ns2_phy_data *data = phy_get_drvdata(phy);
+ struct ns2_phy_driver *driver = data->driver;
+ u32 val;
+
+ val = readl(driver->icfgdrd_regs + ICFG_FSM_CTRL);
+
+ if (data->new_state == EVT_HOST) {
+ val &= ~DRD_DEVICE_MODE;
+ val |= DRD_HOST_MODE;
+ } else {
+ val &= ~DRD_HOST_MODE;
+ val |= DRD_DEVICE_MODE;
+ }
+ writel(val, driver->icfgdrd_regs + ICFG_FSM_CTRL);
+
+ return 0;
+}
+
+static int ns2_drd_phy_poweroff(struct phy *phy)
+{
+ struct ns2_phy_data *data = phy_get_drvdata(phy);
+ struct ns2_phy_driver *driver = data->driver;
+ u32 val;
+
+ val = readl(driver->crmu_usb2_ctrl);
+ val &= ~AFE_CORERDY_VDDC;
+ writel(val, driver->crmu_usb2_ctrl);
+
+ val = readl(driver->crmu_usb2_ctrl);
+ val &= ~DRD_DEV_MODE;
+ writel(val, driver->crmu_usb2_ctrl);
+
+ /* Disable Host and Device Mode */
+ val = readl(driver->icfgdrd_regs + ICFG_FSM_CTRL);
+ val &= ~(DRD_HOST_MODE | DRD_DEVICE_MODE | ICFG_OFF_MODE);
+ writel(val, driver->icfgdrd_regs + ICFG_FSM_CTRL);
+
+ return 0;
+}
+
+static int ns2_drd_phy_poweron(struct phy *phy)
+{
+ struct ns2_phy_data *data = phy_get_drvdata(phy);
+ struct ns2_phy_driver *driver = data->driver;
+ u32 extcon_event = data->new_state;
+ int ret;
+ u32 val;
+
+ if (extcon_event == EVT_DEVICE) {
+ writel(DRD_DEV_VAL, driver->icfgdrd_regs + ICFG_DRD_P0CTL);
+
+ val = readl(driver->idmdrd_rst_ctrl);
+ val &= ~IDM_RST_BIT;
+ writel(val, driver->idmdrd_rst_ctrl);
+
+ val = readl(driver->crmu_usb2_ctrl);
+ val |= (AFE_CORERDY_VDDC | DRD_DEV_MODE);
+ writel(val, driver->crmu_usb2_ctrl);
+
+ /* Bring PHY and PHY_PLL out of Reset */
+ val = readl(driver->crmu_usb2_ctrl);
+ val |= (PHY_PLL_RESETB | PHY_RESETB);
+ writel(val, driver->crmu_usb2_ctrl);
+
+ ret = pll_lock_stat(ICFG_MISC_STAT, PHY_PLL_LOCK, driver);
+ if (ret < 0) {
+ dev_err(&phy->dev, "Phy PLL lock failed\n");
+ return ret;
+ }
+ } else {
+ writel(DRD_HOST_VAL, driver->icfgdrd_regs + ICFG_DRD_P0CTL);
+
+ val = readl(driver->crmu_usb2_ctrl);
+ val |= AFE_CORERDY_VDDC;
+ writel(val, driver->crmu_usb2_ctrl);
+
+ ret = pll_lock_stat(ICFG_MISC_STAT, PHY_PLL_LOCK, driver);
+ if (ret < 0) {
+ dev_err(&phy->dev, "Phy PLL lock failed\n");
+ return ret;
+ }
+
+ val = readl(driver->idmdrd_rst_ctrl);
+ val &= ~IDM_RST_BIT;
+ writel(val, driver->idmdrd_rst_ctrl);
+
+ /* port over current Polarity */
+ val = readl(driver->usb2h_strap_reg);
+ val |= OHCI_OVRCUR_POL;
+ writel(val, driver->usb2h_strap_reg);
+ }
+
+ return 0;
+}
+
+static void connect_change(struct ns2_phy_driver *driver)
+{
+ u32 extcon_event;
+ u32 val;
+
+ extcon_event = driver->data->new_state;
+ val = readl(driver->icfgdrd_regs + ICFG_FSM_CTRL);
+
+ switch (extcon_event) {
+ case EVT_DEVICE:
+ val &= ~(DRD_HOST_MODE | DRD_DEVICE_MODE);
+ writel(val, driver->icfgdrd_regs + ICFG_FSM_CTRL);
+
+ val = (val & ~DRD_HOST_MODE) | DRD_DEVICE_MODE;
+ writel(val, driver->icfgdrd_regs + ICFG_FSM_CTRL);
+
+ val = readl(driver->icfgdrd_regs + ICFG_DRD_P0CTL);
+ val |= ICFG_DEV_BIT;
+ writel(val, driver->icfgdrd_regs + ICFG_DRD_P0CTL);
+ break;
+
+ case EVT_HOST:
+ val &= ~(DRD_HOST_MODE | DRD_DEVICE_MODE);
+ writel(val, driver->icfgdrd_regs + ICFG_FSM_CTRL);
+
+ val = (val & ~DRD_DEVICE_MODE) | DRD_HOST_MODE;
+ writel(val, driver->icfgdrd_regs + ICFG_FSM_CTRL);
+
+ val = readl(driver->usb2h_strap_reg);
+ val |= OHCI_OVRCUR_POL;
+ writel(val, driver->usb2h_strap_reg);
+
+ val = readl(driver->icfgdrd_regs + ICFG_DRD_P0CTL);
+ val &= ~ICFG_DEV_BIT;
+ writel(val, driver->icfgdrd_regs + ICFG_DRD_P0CTL);
+ break;
+
+ default:
+ pr_err("Invalid extcon event\n");
+ break;
+ }
+}
+
+static void extcon_work(struct work_struct *work)
+{
+ struct ns2_phy_driver *driver;
+ int vbus;
+ int id;
+
+ driver = container_of(to_delayed_work(work),
+ struct ns2_phy_driver, wq_extcon);
+
+ id = gpiod_get_value_cansleep(driver->id_gpiod);
+ vbus = gpiod_get_value_cansleep(driver->vbus_gpiod);
+
+ if (!id && vbus) { /* Host connected */
+ extcon_set_cable_state_(driver->edev, EXTCON_USB_HOST, true);
+ pr_debug("Host cable connected\n");
+ driver->data->new_state = EVT_HOST;
+ connect_change(driver);
+ } else if (id && !vbus) { /* Disconnected */
+ extcon_set_cable_state_(driver->edev, EXTCON_USB_HOST, false);
+ extcon_set_cable_state_(driver->edev, EXTCON_USB, false);
+ pr_debug("Cable disconnected\n");
+ } else if (id && vbus) { /* Device connected */
+ extcon_set_cable_state_(driver->edev, EXTCON_USB, true);
+ pr_debug("Device cable connected\n");
+ driver->data->new_state = EVT_DEVICE;
+ connect_change(driver);
+ }
+}
+
+static irqreturn_t gpio_irq_handler(int irq, void *dev_id)
+{
+ struct ns2_phy_driver *driver = dev_id;
+
+ queue_delayed_work(system_power_efficient_wq, &driver->wq_extcon,
+ driver->debounce_jiffies);
+
+ return IRQ_HANDLED;
+}
+
+static struct phy_ops ops = {
+ .init = ns2_drd_phy_init,
+ .power_on = ns2_drd_phy_poweron,
+ .power_off = ns2_drd_phy_poweroff,
+ .owner = THIS_MODULE,
+};
+
+static const struct of_device_id ns2_drd_phy_dt_ids[] = {
+ { .compatible = "brcm,ns2-drd-phy", },
+ { }
+};
+MODULE_DEVICE_TABLE(of, ns2_drd_phy_dt_ids);
+
+static int ns2_drd_phy_probe(struct platform_device *pdev)
+{
+ struct phy_provider *phy_provider;
+ struct device *dev = &pdev->dev;
+ struct ns2_phy_driver *driver;
+ struct ns2_phy_data *data;
+ struct resource *res;
+ int ret;
+ u32 val;
+
+ driver = devm_kzalloc(dev, sizeof(struct ns2_phy_driver),
+ GFP_KERNEL);
+ if (!driver)
+ return -ENOMEM;
+
+ driver->data = devm_kzalloc(dev, sizeof(struct ns2_phy_data),
+ GFP_KERNEL);
+ if (!driver->data)
+ return -ENOMEM;
+
+ res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "icfg");
+ driver->icfgdrd_regs = devm_ioremap_resource(dev, res);
+ if (IS_ERR(driver->icfgdrd_regs))
+ return PTR_ERR(driver->icfgdrd_regs);
+
+ res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "rst-ctrl");
+ driver->idmdrd_rst_ctrl = devm_ioremap_resource(dev, res);
+ if (IS_ERR(driver->idmdrd_rst_ctrl))
+ return PTR_ERR(driver->idmdrd_rst_ctrl);
+
+ res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "crmu-ctrl");
+ driver->crmu_usb2_ctrl = devm_ioremap_resource(dev, res);
+ if (IS_ERR(driver->crmu_usb2_ctrl))
+ return PTR_ERR(driver->crmu_usb2_ctrl);
+
+ res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "usb2-strap");
+ driver->usb2h_strap_reg = devm_ioremap_resource(dev, res);
+ if (IS_ERR(driver->usb2h_strap_reg))
+ return PTR_ERR(driver->usb2h_strap_reg);
+
+ /* create extcon */
+ driver->id_gpiod = devm_gpiod_get(&pdev->dev, "id", GPIOD_IN);
+ if (IS_ERR(driver->id_gpiod)) {
+ dev_err(dev, "failed to get ID GPIO\n");
+ return PTR_ERR(driver->id_gpiod);
+ }
+ driver->vbus_gpiod = devm_gpiod_get(&pdev->dev, "vbus", GPIOD_IN);
+ if (IS_ERR(driver->vbus_gpiod)) {
+ dev_err(dev, "failed to get VBUS GPIO\n");
+ return PTR_ERR(driver->vbus_gpiod);
+ }
+
+ driver->edev = devm_extcon_dev_allocate(dev, usb_extcon_cable);
+ if (IS_ERR(driver->edev)) {
+ dev_err(dev, "failed to allocate extcon device\n");
+ return -ENOMEM;
+ }
+
+ ret = devm_extcon_dev_register(dev, driver->edev);
+ if (ret < 0) {
+ dev_err(dev, "failed to register extcon device\n");
+ return ret;
+ }
+
+ ret = gpiod_set_debounce(driver->id_gpiod, GPIO_DELAY * 1000);
+ if (ret < 0)
+ driver->debounce_jiffies = msecs_to_jiffies(GPIO_DELAY);
+
+ INIT_DELAYED_WORK(&driver->wq_extcon, extcon_work);
+
+ driver->id_irq = gpiod_to_irq(driver->id_gpiod);
+ if (driver->id_irq < 0) {
+ dev_err(dev, "failed to get ID IRQ\n");
+ return driver->id_irq;
+ }
+
+ driver->vbus_irq = gpiod_to_irq(driver->vbus_gpiod);
+ if (driver->vbus_irq < 0) {
+ dev_err(dev, "failed to get ID IRQ\n");
+ return driver->vbus_irq;
+ }
+
+ ret = devm_request_irq(dev, driver->id_irq, gpio_irq_handler,
+ IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
+ "usb_id", driver);
+ if (ret < 0) {
+ dev_err(dev, "failed to request handler for ID IRQ\n");
+ return ret;
+ }
+
+ ret = devm_request_irq(dev, driver->vbus_irq, gpio_irq_handler,
+ IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
+ "usb_vbus", driver);
+ if (ret < 0) {
+ dev_err(dev, "failed to request handler for VBUS IRQ\n");
+ return ret;
+ }
+
+ dev_set_drvdata(dev, driver);
+
+ /* Shutdown all ports. They can be powered up as required */
+ val = readl(driver->crmu_usb2_ctrl);
+ val &= ~(AFE_CORERDY_VDDC | PHY_RESETB);
+ writel(val, driver->crmu_usb2_ctrl);
+
+ data = driver->data;
+ data->phy = devm_phy_create(dev, dev->of_node, &ops);
+ if (IS_ERR(data->phy)) {
+ dev_err(dev, "Failed to create usb drd phy\n");
+ return PTR_ERR(data->phy);
+ }
+
+ data->driver = driver;
+ phy_set_drvdata(data->phy, data);
+
+ phy_provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate);
+ if (IS_ERR(phy_provider)) {
+ dev_err(dev, "Failed to register as phy provider\n");
+ return PTR_ERR(phy_provider);
+ }
+
+ platform_set_drvdata(pdev, driver);
+
+ dev_info(dev, "Registered NS2 DRD Phy device\n");
+ queue_delayed_work(system_power_efficient_wq, &driver->wq_extcon,
+ driver->debounce_jiffies);
+
+ return 0;
+}
+
+static struct platform_driver ns2_drd_phy_driver = {
+ .probe = ns2_drd_phy_probe,
+ .driver = {
+ .name = "bcm-ns2-usbphy",
+ .of_match_table = of_match_ptr(ns2_drd_phy_dt_ids),
+ },
+};
+module_platform_driver(ns2_drd_phy_driver);
+
+MODULE_ALIAS("platform:bcm-ns2-drd-phy");
+MODULE_AUTHOR("Broadcom");
+MODULE_DESCRIPTION("Broadcom NS2 USB2 PHY driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/phy/phy-brcm-sata.c b/drivers/phy/broadcom/phy-brcm-sata.c
index ccbc3d994998..e6544c8b1ace 100644
--- a/drivers/phy/phy-brcm-sata.c
+++ b/drivers/phy/broadcom/phy-brcm-sata.c
@@ -46,6 +46,7 @@ enum brcm_sata_phy_version {
BRCM_SATA_PHY_STB_40NM,
BRCM_SATA_PHY_IPROC_NS2,
BRCM_SATA_PHY_IPROC_NSP,
+ BRCM_SATA_PHY_IPROC_SR,
};
struct brcm_sata_port {
@@ -81,12 +82,17 @@ enum sata_phy_regs {
PLL_ACTRL2 = 0x8b,
PLL_ACTRL2_SELDIV_MASK = 0x1f,
PLL_ACTRL2_SELDIV_SHIFT = 9,
+ PLL_ACTRL6 = 0x86,
PLL1_REG_BANK = 0x060,
PLL1_ACTRL2 = 0x82,
PLL1_ACTRL3 = 0x83,
PLL1_ACTRL4 = 0x84,
+ TX_REG_BANK = 0x070,
+ TX_ACTRL0 = 0x80,
+ TX_ACTRL0_TXPOL_FLIP = BIT(6),
+
OOB_REG_BANK = 0x150,
OOB1_REG_BANK = 0x160,
OOB_CTRL1 = 0x80,
@@ -347,6 +353,68 @@ static int brcm_nsp_sata_init(struct brcm_sata_port *port)
return 0;
}
+/* SR PHY PLL0 registers */
+#define SR_PLL0_ACTRL6_MAGIC 0xa
+
+/* SR PHY PLL1 registers */
+#define SR_PLL1_ACTRL2_MAGIC 0x32
+#define SR_PLL1_ACTRL3_MAGIC 0x2
+#define SR_PLL1_ACTRL4_MAGIC 0x3e8
+
+static int brcm_sr_sata_init(struct brcm_sata_port *port)
+{
+ struct brcm_sata_phy *priv = port->phy_priv;
+ struct device *dev = port->phy_priv->dev;
+ void __iomem *base = priv->phy_base;
+ unsigned int val, try;
+
+ /* Configure PHY PLL register bank 1 */
+ val = SR_PLL1_ACTRL2_MAGIC;
+ brcm_sata_phy_wr(base, PLL1_REG_BANK, PLL1_ACTRL2, 0x0, val);
+ val = SR_PLL1_ACTRL3_MAGIC;
+ brcm_sata_phy_wr(base, PLL1_REG_BANK, PLL1_ACTRL3, 0x0, val);
+ val = SR_PLL1_ACTRL4_MAGIC;
+ brcm_sata_phy_wr(base, PLL1_REG_BANK, PLL1_ACTRL4, 0x0, val);
+
+ /* Configure PHY PLL register bank 0 */
+ val = SR_PLL0_ACTRL6_MAGIC;
+ brcm_sata_phy_wr(base, PLL_REG_BANK_0, PLL_ACTRL6, 0x0, val);
+
+ /* Wait for PHY PLL lock by polling pll_lock bit */
+ try = 50;
+ do {
+ val = brcm_sata_phy_rd(base, BLOCK0_REG_BANK,
+ BLOCK0_XGXSSTATUS);
+ if (val & BLOCK0_XGXSSTATUS_PLL_LOCK)
+ break;
+ msleep(20);
+ try--;
+ } while (try);
+
+ if ((val & BLOCK0_XGXSSTATUS_PLL_LOCK) == 0) {
+ /* PLL did not lock; give up */
+ dev_err(dev, "port%d PLL did not lock\n", port->portnum);
+ return -ETIMEDOUT;
+ }
+
+ /* Invert Tx polarity */
+ brcm_sata_phy_wr(base, TX_REG_BANK, TX_ACTRL0,
+ ~TX_ACTRL0_TXPOL_FLIP, TX_ACTRL0_TXPOL_FLIP);
+
+ /* Configure OOB control to handle 100MHz reference clock */
+ val = ((0xc << OOB_CTRL1_BURST_MAX_SHIFT) |
+ (0x4 << OOB_CTRL1_BURST_MIN_SHIFT) |
+ (0x8 << OOB_CTRL1_WAKE_IDLE_MAX_SHIFT) |
+ (0x3 << OOB_CTRL1_WAKE_IDLE_MIN_SHIFT));
+ brcm_sata_phy_wr(base, OOB_REG_BANK, OOB_CTRL1, 0x0, val);
+ val = ((0x1b << OOB_CTRL2_RESET_IDLE_MAX_SHIFT) |
+ (0x2 << OOB_CTRL2_BURST_CNT_SHIFT) |
+ (0x9 << OOB_CTRL2_RESET_IDLE_MIN_SHIFT));
+ brcm_sata_phy_wr(base, OOB_REG_BANK, OOB_CTRL2, 0x0, val);
+
+ return 0;
+}
+
static int brcm_sata_phy_init(struct phy *phy)
{
int rc;
@@ -363,6 +431,9 @@ static int brcm_sata_phy_init(struct phy *phy)
case BRCM_SATA_PHY_IPROC_NSP:
rc = brcm_nsp_sata_init(port);
break;
+ case BRCM_SATA_PHY_IPROC_SR:
+ rc = brcm_sr_sata_init(port);
+ break;
default:
rc = -ENODEV;
}
@@ -384,6 +455,8 @@ static const struct of_device_id brcm_sata_phy_of_match[] = {
.data = (void *)BRCM_SATA_PHY_IPROC_NS2 },
{ .compatible = "brcm,iproc-nsp-sata-phy",
.data = (void *)BRCM_SATA_PHY_IPROC_NSP },
+ { .compatible = "brcm,iproc-sr-sata-phy",
+ .data = (void *)BRCM_SATA_PHY_IPROC_SR },
{},
};
MODULE_DEVICE_TABLE(of, brcm_sata_phy_of_match);
diff --git a/drivers/phy/hisilicon/Kconfig b/drivers/phy/hisilicon/Kconfig
new file mode 100644
index 000000000000..6164c4cd0f65
--- /dev/null
+++ b/drivers/phy/hisilicon/Kconfig
@@ -0,0 +1,20 @@
+#
+# Phy drivers for Hisilicon platforms
+#
+config PHY_HI6220_USB
+ tristate "hi6220 USB PHY support"
+ depends on (ARCH_HISI && ARM64) || COMPILE_TEST
+ select GENERIC_PHY
+ select MFD_SYSCON
+ help
+ Enable this to support the HISILICON HI6220 USB PHY.
+
+ To compile this driver as a module, choose M here.
+
+config PHY_HIX5HD2_SATA
+ tristate "HIX5HD2 SATA PHY Driver"
+ depends on ARCH_HIX5HD2 && OF && HAS_IOMEM
+ select GENERIC_PHY
+ select MFD_SYSCON
+ help
+ Support for SATA PHY on Hisilicon hix5hd2 Soc.
diff --git a/drivers/phy/hisilicon/Makefile b/drivers/phy/hisilicon/Makefile
new file mode 100644
index 000000000000..541b348187a8
--- /dev/null
+++ b/drivers/phy/hisilicon/Makefile
@@ -0,0 +1,2 @@
+obj-$(CONFIG_PHY_HI6220_USB) += phy-hi6220-usb.o
+obj-$(CONFIG_PHY_HIX5HD2_SATA) += phy-hix5hd2-sata.o
diff --git a/drivers/phy/phy-hi6220-usb.c b/drivers/phy/hisilicon/phy-hi6220-usb.c
index 398c1021deec..398c1021deec 100644
--- a/drivers/phy/phy-hi6220-usb.c
+++ b/drivers/phy/hisilicon/phy-hi6220-usb.c
diff --git a/drivers/phy/phy-hix5hd2-sata.c b/drivers/phy/hisilicon/phy-hix5hd2-sata.c
index e5ab3aa78b9d..e5ab3aa78b9d 100644
--- a/drivers/phy/phy-hix5hd2-sata.c
+++ b/drivers/phy/hisilicon/phy-hix5hd2-sata.c
diff --git a/drivers/phy/marvell/Kconfig b/drivers/phy/marvell/Kconfig
new file mode 100644
index 000000000000..048d8893bc2e
--- /dev/null
+++ b/drivers/phy/marvell/Kconfig
@@ -0,0 +1,50 @@
+#
+# Phy drivers for Marvell platforms
+#
+config ARMADA375_USBCLUSTER_PHY
+ def_bool y
+ depends on MACH_ARMADA_375 || COMPILE_TEST
+ depends on OF && HAS_IOMEM
+ select GENERIC_PHY
+
+config PHY_BERLIN_SATA
+ tristate "Marvell Berlin SATA PHY driver"
+ depends on ARCH_BERLIN && HAS_IOMEM && OF
+ select GENERIC_PHY
+ help
+ Enable this to support the SATA PHY on Marvell Berlin SoCs.
+
+config PHY_BERLIN_USB
+ tristate "Marvell Berlin USB PHY Driver"
+ depends on ARCH_BERLIN && RESET_CONTROLLER && HAS_IOMEM && OF
+ select GENERIC_PHY
+ help
+ Enable this to support the USB PHY on Marvell Berlin SoCs.
+
+config PHY_MVEBU_SATA
+ def_bool y
+ depends on ARCH_DOVE || MACH_DOVE || MACH_KIRKWOOD
+ depends on OF
+ select GENERIC_PHY
+
+config PHY_PXA_28NM_HSIC
+ tristate "Marvell USB HSIC 28nm PHY Driver"
+ depends on HAS_IOMEM
+ select GENERIC_PHY
+ help
+ Enable this to support Marvell USB HSIC PHY driver for Marvell
+ SoC. This driver will do the PHY initialization and shutdown.
+ The PHY driver will be used by Marvell ehci driver.
+
+ To compile this driver as a module, choose M here.
+
+config PHY_PXA_28NM_USB2
+ tristate "Marvell USB 2.0 28nm PHY Driver"
+ depends on HAS_IOMEM
+ select GENERIC_PHY
+ help
+ Enable this to support Marvell USB 2.0 PHY driver for Marvell
+ SoC. This driver will do the PHY initialization and shutdown.
+ The PHY driver will be used by Marvell udc/ehci/otg driver.
+
+ To compile this driver as a module, choose M here.
diff --git a/drivers/phy/marvell/Makefile b/drivers/phy/marvell/Makefile
new file mode 100644
index 000000000000..3fc188f59118
--- /dev/null
+++ b/drivers/phy/marvell/Makefile
@@ -0,0 +1,6 @@
+obj-$(CONFIG_ARMADA375_USBCLUSTER_PHY) += phy-armada375-usb2.o
+obj-$(CONFIG_PHY_BERLIN_SATA) += phy-berlin-sata.o
+obj-$(CONFIG_PHY_BERLIN_USB) += phy-berlin-usb.o
+obj-$(CONFIG_PHY_MVEBU_SATA) += phy-mvebu-sata.o
+obj-$(CONFIG_PHY_PXA_28NM_HSIC) += phy-pxa-28nm-hsic.o
+obj-$(CONFIG_PHY_PXA_28NM_USB2) += phy-pxa-28nm-usb2.o
diff --git a/drivers/phy/phy-armada375-usb2.c b/drivers/phy/marvell/phy-armada375-usb2.c
index 1a3db288c0a9..1a3db288c0a9 100644
--- a/drivers/phy/phy-armada375-usb2.c
+++ b/drivers/phy/marvell/phy-armada375-usb2.c
diff --git a/drivers/phy/phy-berlin-sata.c b/drivers/phy/marvell/phy-berlin-sata.c
index 2c7a57f2d595..2c7a57f2d595 100644
--- a/drivers/phy/phy-berlin-sata.c
+++ b/drivers/phy/marvell/phy-berlin-sata.c
diff --git a/drivers/phy/phy-berlin-usb.c b/drivers/phy/marvell/phy-berlin-usb.c
index 2017751ede26..2017751ede26 100644
--- a/drivers/phy/phy-berlin-usb.c
+++ b/drivers/phy/marvell/phy-berlin-usb.c
diff --git a/drivers/phy/phy-mvebu-sata.c b/drivers/phy/marvell/phy-mvebu-sata.c
index 768ce92e81ce..768ce92e81ce 100644
--- a/drivers/phy/phy-mvebu-sata.c
+++ b/drivers/phy/marvell/phy-mvebu-sata.c
diff --git a/drivers/phy/phy-pxa-28nm-hsic.c b/drivers/phy/marvell/phy-pxa-28nm-hsic.c
index 234aacf4db20..234aacf4db20 100644
--- a/drivers/phy/phy-pxa-28nm-hsic.c
+++ b/drivers/phy/marvell/phy-pxa-28nm-hsic.c
diff --git a/drivers/phy/phy-pxa-28nm-usb2.c b/drivers/phy/marvell/phy-pxa-28nm-usb2.c
index 37e9c8ca4983..37e9c8ca4983 100644
--- a/drivers/phy/phy-pxa-28nm-usb2.c
+++ b/drivers/phy/marvell/phy-pxa-28nm-usb2.c
diff --git a/drivers/phy/motorola/Kconfig b/drivers/phy/motorola/Kconfig
new file mode 100644
index 000000000000..6bb7d6bdf1bf
--- /dev/null
+++ b/drivers/phy/motorola/Kconfig
@@ -0,0 +1,12 @@
+#
+# Phy drivers for Motorola devices
+#
+config PHY_CPCAP_USB
+ tristate "CPCAP PMIC USB PHY driver"
+ depends on USB_SUPPORT && IIO
+ depends on USB_MUSB_HDRC || USB_MUSB_HDRC=n
+ select GENERIC_PHY
+ select USB_PHY
+ help
+ Enable this for USB to work on Motorola phones and tablets
+ such as Droid 4.
diff --git a/drivers/phy/motorola/Makefile b/drivers/phy/motorola/Makefile
new file mode 100644
index 000000000000..b6cd618d671a
--- /dev/null
+++ b/drivers/phy/motorola/Makefile
@@ -0,0 +1,5 @@
+#
+# Makefile for the phy drivers.
+#
+
+obj-$(CONFIG_PHY_CPCAP_USB) += phy-cpcap-usb.o
diff --git a/drivers/phy/motorola/phy-cpcap-usb.c b/drivers/phy/motorola/phy-cpcap-usb.c
new file mode 100644
index 000000000000..9b63efa5ae4d
--- /dev/null
+++ b/drivers/phy/motorola/phy-cpcap-usb.c
@@ -0,0 +1,676 @@
+/*
+ * Motorola CPCAP PMIC USB PHY driver
+ * Copyright (C) 2017 Tony Lindgren <tony@atomide.com>
+ *
+ * Some parts based on earlier Motorola Linux kernel tree code in
+ * board-mapphone-usb.c and cpcap-usb-det.c:
+ * Copyright (C) 2007 - 2011 Motorola, Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation version 2.
+ *
+ * This program is distributed "as is" WITHOUT ANY WARRANTY of any
+ * kind, whether express or implied; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/atomic.h>
+#include <linux/clk.h>
+#include <linux/delay.h>
+#include <linux/err.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_platform.h>
+#include <linux/iio/consumer.h>
+#include <linux/pinctrl/consumer.h>
+#include <linux/platform_device.h>
+#include <linux/regmap.h>
+#include <linux/slab.h>
+
+#include <linux/gpio/consumer.h>
+#include <linux/mfd/motorola-cpcap.h>
+#include <linux/phy/omap_usb.h>
+#include <linux/phy/phy.h>
+#include <linux/regulator/consumer.h>
+#include <linux/usb/musb.h>
+
+/* CPCAP_REG_USBC1 register bits */
+#define CPCAP_BIT_IDPULSE BIT(15)
+#define CPCAP_BIT_ID100KPU BIT(14)
+#define CPCAP_BIT_IDPUCNTRL BIT(13)
+#define CPCAP_BIT_IDPU BIT(12)
+#define CPCAP_BIT_IDPD BIT(11)
+#define CPCAP_BIT_VBUSCHRGTMR3 BIT(10)
+#define CPCAP_BIT_VBUSCHRGTMR2 BIT(9)
+#define CPCAP_BIT_VBUSCHRGTMR1 BIT(8)
+#define CPCAP_BIT_VBUSCHRGTMR0 BIT(7)
+#define CPCAP_BIT_VBUSPU BIT(6)
+#define CPCAP_BIT_VBUSPD BIT(5)
+#define CPCAP_BIT_DMPD BIT(4)
+#define CPCAP_BIT_DPPD BIT(3)
+#define CPCAP_BIT_DM1K5PU BIT(2)
+#define CPCAP_BIT_DP1K5PU BIT(1)
+#define CPCAP_BIT_DP150KPU BIT(0)
+
+/* CPCAP_REG_USBC2 register bits */
+#define CPCAP_BIT_ZHSDRV1 BIT(15)
+#define CPCAP_BIT_ZHSDRV0 BIT(14)
+#define CPCAP_BIT_DPLLCLKREQ BIT(13)
+#define CPCAP_BIT_SE0CONN BIT(12)
+#define CPCAP_BIT_UARTTXTRI BIT(11)
+#define CPCAP_BIT_UARTSWAP BIT(10)
+#define CPCAP_BIT_UARTMUX1 BIT(9)
+#define CPCAP_BIT_UARTMUX0 BIT(8)
+#define CPCAP_BIT_ULPISTPLOW BIT(7)
+#define CPCAP_BIT_TXENPOL BIT(6)
+#define CPCAP_BIT_USBXCVREN BIT(5)
+#define CPCAP_BIT_USBCNTRL BIT(4)
+#define CPCAP_BIT_USBSUSPEND BIT(3)
+#define CPCAP_BIT_EMUMODE2 BIT(2)
+#define CPCAP_BIT_EMUMODE1 BIT(1)
+#define CPCAP_BIT_EMUMODE0 BIT(0)
+
+/* CPCAP_REG_USBC3 register bits */
+#define CPCAP_BIT_SPARE_898_15 BIT(15)
+#define CPCAP_BIT_IHSTX03 BIT(14)
+#define CPCAP_BIT_IHSTX02 BIT(13)
+#define CPCAP_BIT_IHSTX01 BIT(12)
+#define CPCAP_BIT_IHSTX0 BIT(11)
+#define CPCAP_BIT_IDPU_SPI BIT(10)
+#define CPCAP_BIT_UNUSED_898_9 BIT(9)
+#define CPCAP_BIT_VBUSSTBY_EN BIT(8)
+#define CPCAP_BIT_VBUSEN_SPI BIT(7)
+#define CPCAP_BIT_VBUSPU_SPI BIT(6)
+#define CPCAP_BIT_VBUSPD_SPI BIT(5)
+#define CPCAP_BIT_DMPD_SPI BIT(4)
+#define CPCAP_BIT_DPPD_SPI BIT(3)
+#define CPCAP_BIT_SUSPEND_SPI BIT(2)
+#define CPCAP_BIT_PU_SPI BIT(1)
+#define CPCAP_BIT_ULPI_SPI_SEL BIT(0)
+
+struct cpcap_usb_ints_state {
+ bool id_ground;
+ bool id_float;
+ bool chrg_det;
+ bool rvrs_chrg;
+ bool vbusov;
+
+ bool chrg_se1b;
+ bool se0conn;
+ bool rvrs_mode;
+ bool chrgcurr1;
+ bool vbusvld;
+ bool sessvld;
+ bool sessend;
+ bool se1;
+
+ bool battdetb;
+ bool dm;
+ bool dp;
+};
+
+enum cpcap_gpio_mode {
+ CPCAP_DM_DP,
+ CPCAP_MDM_RX_TX,
+ CPCAP_UNKNOWN,
+ CPCAP_OTG_DM_DP,
+};
+
+struct cpcap_phy_ddata {
+ struct regmap *reg;
+ struct device *dev;
+ struct clk *refclk;
+ struct usb_phy phy;
+ struct delayed_work detect_work;
+ struct pinctrl *pins;
+ struct pinctrl_state *pins_ulpi;
+ struct pinctrl_state *pins_utmi;
+ struct pinctrl_state *pins_uart;
+ struct gpio_desc *gpio[2];
+ struct iio_channel *vbus;
+ struct iio_channel *id;
+ struct regulator *vusb;
+ atomic_t active;
+};
+
+static bool cpcap_usb_vbus_valid(struct cpcap_phy_ddata *ddata)
+{
+ int error, value = 0;
+
+ error = iio_read_channel_processed(ddata->vbus, &value);
+ if (error >= 0)
+ return value > 3900 ? true : false;
+
+ dev_err(ddata->dev, "error reading VBUS: %i\n", error);
+
+ return false;
+}
+
+static int cpcap_usb_phy_set_host(struct usb_otg *otg, struct usb_bus *host)
+{
+ otg->host = host;
+ if (!host)
+ otg->state = OTG_STATE_UNDEFINED;
+
+ return 0;
+}
+
+static int cpcap_usb_phy_set_peripheral(struct usb_otg *otg,
+ struct usb_gadget *gadget)
+{
+ otg->gadget = gadget;
+ if (!gadget)
+ otg->state = OTG_STATE_UNDEFINED;
+
+ return 0;
+}
+
+static const struct phy_ops ops = {
+ .owner = THIS_MODULE,
+};
+
+static int cpcap_phy_get_ints_state(struct cpcap_phy_ddata *ddata,
+ struct cpcap_usb_ints_state *s)
+{
+ int val, error;
+
+ error = regmap_read(ddata->reg, CPCAP_REG_INTS1, &val);
+ if (error)
+ return error;
+
+ s->id_ground = val & BIT(15);
+ s->id_float = val & BIT(14);
+ s->vbusov = val & BIT(11);
+
+ error = regmap_read(ddata->reg, CPCAP_REG_INTS2, &val);
+ if (error)
+ return error;
+
+ s->vbusvld = val & BIT(3);
+ s->sessvld = val & BIT(2);
+ s->sessend = val & BIT(1);
+ s->se1 = val & BIT(0);
+
+ error = regmap_read(ddata->reg, CPCAP_REG_INTS4, &val);
+ if (error)
+ return error;
+
+ s->dm = val & BIT(1);
+ s->dp = val & BIT(0);
+
+ return 0;
+}
+
+static int cpcap_usb_set_uart_mode(struct cpcap_phy_ddata *ddata);
+static int cpcap_usb_set_usb_mode(struct cpcap_phy_ddata *ddata);
+
+static void cpcap_usb_detect(struct work_struct *work)
+{
+ struct cpcap_phy_ddata *ddata;
+ struct cpcap_usb_ints_state s;
+ bool vbus = false;
+ int error;
+
+ ddata = container_of(work, struct cpcap_phy_ddata, detect_work.work);
+
+ error = cpcap_phy_get_ints_state(ddata, &s);
+ if (error)
+ return;
+
+ if (s.id_ground) {
+ dev_dbg(ddata->dev, "id ground, USB host mode\n");
+ error = cpcap_usb_set_usb_mode(ddata);
+ if (error)
+ goto out_err;
+
+ error = musb_mailbox(MUSB_ID_GROUND);
+ if (error)
+ goto out_err;
+
+ error = regmap_update_bits(ddata->reg, CPCAP_REG_USBC3,
+ CPCAP_BIT_VBUSSTBY_EN,
+ CPCAP_BIT_VBUSSTBY_EN);
+ if (error)
+ goto out_err;
+
+ return;
+ }
+
+ error = regmap_update_bits(ddata->reg, CPCAP_REG_USBC3,
+ CPCAP_BIT_VBUSSTBY_EN, 0);
+ if (error)
+ goto out_err;
+
+ vbus = cpcap_usb_vbus_valid(ddata);
+
+ if (vbus) {
+ /* Are we connected to a docking station with vbus? */
+ if (s.id_ground) {
+ dev_dbg(ddata->dev, "connected to a dock\n");
+
+ /* No VBUS needed with docks */
+ error = cpcap_usb_set_usb_mode(ddata);
+ if (error)
+ goto out_err;
+ error = musb_mailbox(MUSB_ID_GROUND);
+ if (error)
+ goto out_err;
+
+ return;
+ }
+
+ /* Otherwise assume we're connected to a USB host */
+ dev_dbg(ddata->dev, "connected to USB host\n");
+ error = cpcap_usb_set_usb_mode(ddata);
+ if (error)
+ goto out_err;
+ error = musb_mailbox(MUSB_VBUS_VALID);
+ if (error)
+ goto out_err;
+
+ return;
+ }
+
+ /* Default to debug UART mode */
+ error = cpcap_usb_set_uart_mode(ddata);
+ if (error)
+ goto out_err;
+
+ error = musb_mailbox(MUSB_VBUS_OFF);
+ if (error)
+ goto out_err;
+
+ dev_dbg(ddata->dev, "set UART mode\n");
+
+ return;
+
+out_err:
+ dev_err(ddata->dev, "error setting cable state: %i\n", error);
+}
+
+static irqreturn_t cpcap_phy_irq_thread(int irq, void *data)
+{
+ struct cpcap_phy_ddata *ddata = data;
+
+ if (!atomic_read(&ddata->active))
+ return IRQ_NONE;
+
+ schedule_delayed_work(&ddata->detect_work, msecs_to_jiffies(1));
+
+ return IRQ_HANDLED;
+}
+
+static int cpcap_usb_init_irq(struct platform_device *pdev,
+ struct cpcap_phy_ddata *ddata,
+ const char *name)
+{
+ int irq, error;
+
+ irq = platform_get_irq_byname(pdev, name);
+ if (!irq)
+ return -ENODEV;
+
+ error = devm_request_threaded_irq(ddata->dev, irq, NULL,
+ cpcap_phy_irq_thread,
+ IRQF_SHARED,
+ name, ddata);
+ if (error) {
+ dev_err(ddata->dev, "could not get irq %s: %i\n",
+ name, error);
+
+ return error;
+ }
+
+ return 0;
+}
+
+static const char * const cpcap_phy_irqs[] = {
+ /* REG_INT_0 */
+ "id_ground", "id_float",
+
+ /* REG_INT1 */
+ "se0conn", "vbusvld", "sessvld", "sessend", "se1",
+
+ /* REG_INT_3 */
+ "dm", "dp",
+};
+
+static int cpcap_usb_init_interrupts(struct platform_device *pdev,
+ struct cpcap_phy_ddata *ddata)
+{
+ int i, error;
+
+ for (i = 0; i < ARRAY_SIZE(cpcap_phy_irqs); i++) {
+ error = cpcap_usb_init_irq(pdev, ddata, cpcap_phy_irqs[i]);
+ if (error)
+ return error;
+ }
+
+ return 0;
+}
+
+/*
+ * Optional pins and modes. At least Motorola mapphone devices
+ * are using two GPIOs and dynamic pinctrl to multiplex PHY pins
+ * to UART, ULPI or UTMI mode.
+ */
+
+static int cpcap_usb_gpio_set_mode(struct cpcap_phy_ddata *ddata,
+ enum cpcap_gpio_mode mode)
+{
+ if (!ddata->gpio[0] || !ddata->gpio[1])
+ return 0;
+
+ gpiod_set_value(ddata->gpio[0], mode & 1);
+ gpiod_set_value(ddata->gpio[1], mode >> 1);
+
+ return 0;
+}
+
+static int cpcap_usb_set_uart_mode(struct cpcap_phy_ddata *ddata)
+{
+ int error;
+
+ error = cpcap_usb_gpio_set_mode(ddata, CPCAP_DM_DP);
+ if (error)
+ goto out_err;
+
+ if (ddata->pins_uart) {
+ error = pinctrl_select_state(ddata->pins, ddata->pins_uart);
+ if (error)
+ goto out_err;
+ }
+
+ error = regmap_update_bits(ddata->reg, CPCAP_REG_USBC1,
+ CPCAP_BIT_VBUSPD,
+ CPCAP_BIT_VBUSPD);
+ if (error)
+ goto out_err;
+
+ error = regmap_update_bits(ddata->reg, CPCAP_REG_USBC2,
+ 0xffff, CPCAP_BIT_UARTMUX0 |
+ CPCAP_BIT_EMUMODE0);
+ if (error)
+ goto out_err;
+
+ error = regmap_update_bits(ddata->reg, CPCAP_REG_USBC3, 0x7fff,
+ CPCAP_BIT_IDPU_SPI);
+ if (error)
+ goto out_err;
+
+ return 0;
+
+out_err:
+ dev_err(ddata->dev, "%s failed with %i\n", __func__, error);
+
+ return error;
+}
+
+static int cpcap_usb_set_usb_mode(struct cpcap_phy_ddata *ddata)
+{
+ int error;
+
+ error = cpcap_usb_gpio_set_mode(ddata, CPCAP_OTG_DM_DP);
+ if (error)
+ return error;
+
+ if (ddata->pins_utmi) {
+ error = pinctrl_select_state(ddata->pins, ddata->pins_utmi);
+ if (error) {
+ dev_err(ddata->dev, "could not set usb mode: %i\n",
+ error);
+
+ return error;
+ }
+ }
+
+ error = regmap_update_bits(ddata->reg, CPCAP_REG_USBC1,
+ CPCAP_BIT_VBUSPD, 0);
+ if (error)
+ goto out_err;
+
+ error = regmap_update_bits(ddata->reg, CPCAP_REG_USBC2,
+ CPCAP_BIT_USBXCVREN,
+ CPCAP_BIT_USBXCVREN);
+ if (error)
+ goto out_err;
+
+ error = regmap_update_bits(ddata->reg, CPCAP_REG_USBC3,
+ CPCAP_BIT_PU_SPI |
+ CPCAP_BIT_DMPD_SPI |
+ CPCAP_BIT_DPPD_SPI |
+ CPCAP_BIT_SUSPEND_SPI |
+ CPCAP_BIT_ULPI_SPI_SEL, 0);
+ if (error)
+ goto out_err;
+
+ error = regmap_update_bits(ddata->reg, CPCAP_REG_USBC2,
+ CPCAP_BIT_USBXCVREN,
+ CPCAP_BIT_USBXCVREN);
+ if (error)
+ goto out_err;
+
+ return 0;
+
+out_err:
+ dev_err(ddata->dev, "%s failed with %i\n", __func__, error);
+
+ return error;
+}
+
+static int cpcap_usb_init_optional_pins(struct cpcap_phy_ddata *ddata)
+{
+ ddata->pins = devm_pinctrl_get(ddata->dev);
+ if (IS_ERR(ddata->pins)) {
+ dev_info(ddata->dev, "default pins not configured: %ld\n",
+ PTR_ERR(ddata->pins));
+ ddata->pins = NULL;
+
+ return 0;
+ }
+
+ ddata->pins_ulpi = pinctrl_lookup_state(ddata->pins, "ulpi");
+ if (IS_ERR(ddata->pins_ulpi)) {
+ dev_info(ddata->dev, "ulpi pins not configured\n");
+ ddata->pins_ulpi = NULL;
+ }
+
+ ddata->pins_utmi = pinctrl_lookup_state(ddata->pins, "utmi");
+ if (IS_ERR(ddata->pins_utmi)) {
+ dev_info(ddata->dev, "utmi pins not configured\n");
+ ddata->pins_utmi = NULL;
+ }
+
+ ddata->pins_uart = pinctrl_lookup_state(ddata->pins, "uart");
+ if (IS_ERR(ddata->pins_uart)) {
+ dev_info(ddata->dev, "uart pins not configured\n");
+ ddata->pins_uart = NULL;
+ }
+
+ if (ddata->pins_uart)
+ return pinctrl_select_state(ddata->pins, ddata->pins_uart);
+
+ return 0;
+}
+
+static void cpcap_usb_init_optional_gpios(struct cpcap_phy_ddata *ddata)
+{
+ int i;
+
+ for (i = 0; i < 2; i++) {
+ ddata->gpio[i] = devm_gpiod_get_index(ddata->dev, "mode",
+ i, GPIOD_OUT_HIGH);
+ if (IS_ERR(ddata->gpio[i])) {
+ dev_info(ddata->dev, "no mode change GPIO%i: %li\n",
+ i, PTR_ERR(ddata->gpio[i]));
+ ddata->gpio[i] = NULL;
+ }
+ }
+}
+
+static int cpcap_usb_init_iio(struct cpcap_phy_ddata *ddata)
+{
+ enum iio_chan_type type;
+ int error;
+
+ ddata->vbus = devm_iio_channel_get(ddata->dev, "vbus");
+ if (IS_ERR(ddata->vbus)) {
+ error = PTR_ERR(ddata->vbus);
+ goto out_err;
+ }
+
+ if (!ddata->vbus->indio_dev) {
+ error = -ENXIO;
+ goto out_err;
+ }
+
+ error = iio_get_channel_type(ddata->vbus, &type);
+ if (error < 0)
+ goto out_err;
+
+ if (type != IIO_VOLTAGE) {
+ error = -EINVAL;
+ goto out_err;
+ }
+
+ return 0;
+
+out_err:
+ dev_err(ddata->dev, "could not initialize VBUS or ID IIO: %i\n",
+ error);
+
+ return error;
+}
+
+#ifdef CONFIG_OF
+static const struct of_device_id cpcap_usb_phy_id_table[] = {
+ {
+ .compatible = "motorola,cpcap-usb-phy",
+ },
+ {
+ .compatible = "motorola,mapphone-cpcap-usb-phy",
+ },
+ {},
+};
+MODULE_DEVICE_TABLE(of, cpcap_usb_phy_id_table);
+#endif
+
+static int cpcap_usb_phy_probe(struct platform_device *pdev)
+{
+ struct cpcap_phy_ddata *ddata;
+ struct phy *generic_phy;
+ struct phy_provider *phy_provider;
+ struct usb_otg *otg;
+ const struct of_device_id *of_id;
+ int error;
+
+ of_id = of_match_device(of_match_ptr(cpcap_usb_phy_id_table),
+ &pdev->dev);
+ if (!of_id)
+ return -EINVAL;
+
+ ddata = devm_kzalloc(&pdev->dev, sizeof(*ddata), GFP_KERNEL);
+ if (!ddata)
+ return -ENOMEM;
+
+ ddata->reg = dev_get_regmap(pdev->dev.parent, NULL);
+ if (!ddata->reg)
+ return -ENODEV;
+
+ otg = devm_kzalloc(&pdev->dev, sizeof(*otg), GFP_KERNEL);
+ if (!otg)
+ return -ENOMEM;
+
+ ddata->dev = &pdev->dev;
+ ddata->phy.dev = ddata->dev;
+ ddata->phy.label = "cpcap_usb_phy";
+ ddata->phy.otg = otg;
+ ddata->phy.type = USB_PHY_TYPE_USB2;
+ otg->set_host = cpcap_usb_phy_set_host;
+ otg->set_peripheral = cpcap_usb_phy_set_peripheral;
+ otg->usb_phy = &ddata->phy;
+ INIT_DELAYED_WORK(&ddata->detect_work, cpcap_usb_detect);
+ platform_set_drvdata(pdev, ddata);
+
+ ddata->vusb = devm_regulator_get(&pdev->dev, "vusb");
+ if (IS_ERR(ddata->vusb))
+ return PTR_ERR(ddata->vusb);
+
+ error = regulator_enable(ddata->vusb);
+ if (error)
+ return error;
+
+ generic_phy = devm_phy_create(ddata->dev, NULL, &ops);
+ if (IS_ERR(generic_phy)) {
+ error = PTR_ERR(generic_phy);
+ return PTR_ERR(generic_phy);
+ }
+
+ phy_set_drvdata(generic_phy, ddata);
+
+ phy_provider = devm_of_phy_provider_register(ddata->dev,
+ of_phy_simple_xlate);
+ if (IS_ERR(phy_provider))
+ return PTR_ERR(phy_provider);
+
+ error = cpcap_usb_init_optional_pins(ddata);
+ if (error)
+ return error;
+
+ cpcap_usb_init_optional_gpios(ddata);
+
+ error = cpcap_usb_init_iio(ddata);
+ if (error)
+ return error;
+
+ error = cpcap_usb_init_interrupts(pdev, ddata);
+ if (error)
+ return error;
+
+ usb_add_phy_dev(&ddata->phy);
+ atomic_set(&ddata->active, 1);
+ schedule_delayed_work(&ddata->detect_work, msecs_to_jiffies(1));
+
+ return 0;
+}
+
+static int cpcap_usb_phy_remove(struct platform_device *pdev)
+{
+ struct cpcap_phy_ddata *ddata = platform_get_drvdata(pdev);
+ int error;
+
+ atomic_set(&ddata->active, 0);
+ error = cpcap_usb_set_uart_mode(ddata);
+ if (error)
+ dev_err(ddata->dev, "could not set UART mode\n");
+
+ error = musb_mailbox(MUSB_VBUS_OFF);
+ if (error)
+ dev_err(ddata->dev, "could not set mailbox\n");
+
+ usb_remove_phy(&ddata->phy);
+ cancel_delayed_work_sync(&ddata->detect_work);
+ clk_unprepare(ddata->refclk);
+ regulator_disable(ddata->vusb);
+
+ return 0;
+}
+
+static struct platform_driver cpcap_usb_phy_driver = {
+ .probe = cpcap_usb_phy_probe,
+ .remove = cpcap_usb_phy_remove,
+ .driver = {
+ .name = "cpcap-usb-phy",
+ .of_match_table = of_match_ptr(cpcap_usb_phy_id_table),
+ },
+};
+
+module_platform_driver(cpcap_usb_phy_driver);
+
+MODULE_ALIAS("platform:cpcap_usb");
+MODULE_AUTHOR("Tony Lindgren <tony@atomide.com>");
+MODULE_DESCRIPTION("CPCAP usb phy driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/phy/qualcomm/Kconfig b/drivers/phy/qualcomm/Kconfig
new file mode 100644
index 000000000000..7bfa64baf837
--- /dev/null
+++ b/drivers/phy/qualcomm/Kconfig
@@ -0,0 +1,58 @@
+#
+# Phy drivers for Qualcomm platforms
+#
+config PHY_QCOM_APQ8064_SATA
+ tristate "Qualcomm APQ8064 SATA SerDes/PHY driver"
+ depends on ARCH_QCOM
+ depends on HAS_IOMEM
+ depends on OF
+ select GENERIC_PHY
+
+config PHY_QCOM_IPQ806X_SATA
+ tristate "Qualcomm IPQ806x SATA SerDes/PHY driver"
+ depends on ARCH_QCOM
+ depends on HAS_IOMEM
+ depends on OF
+ select GENERIC_PHY
+
+config PHY_QCOM_QMP
+ tristate "Qualcomm QMP PHY Driver"
+ depends on OF && COMMON_CLK && (ARCH_QCOM || COMPILE_TEST)
+ select GENERIC_PHY
+ help
+ Enable this to support the QMP PHY transceiver that is used
+ with controllers such as PCIe, UFS, and USB on Qualcomm chips.
+
+config PHY_QCOM_QUSB2
+ tristate "Qualcomm QUSB2 PHY Driver"
+ depends on OF && (ARCH_QCOM || COMPILE_TEST)
+ depends on NVMEM || !NVMEM
+ select GENERIC_PHY
+ help
+ Enable this to support the HighSpeed QUSB2 PHY transceiver for USB
+ controllers on Qualcomm chips. This driver supports the high-speed
+ PHY which is usually paired with either the ChipIdea or Synopsys DWC3
+ USB IPs on MSM SOCs.
+
+config PHY_QCOM_UFS
+ tristate "Qualcomm UFS PHY driver"
+ depends on OF && ARCH_QCOM
+ select GENERIC_PHY
+ help
+ Support for UFS PHY on QCOM chipsets.
+
+config PHY_QCOM_USB_HS
+ tristate "Qualcomm USB HS PHY module"
+ depends on USB_ULPI_BUS
+ depends on EXTCON || !EXTCON # if EXTCON=m, this cannot be built-in
+ select GENERIC_PHY
+ help
+ Support for the USB high-speed ULPI compliant phy on Qualcomm
+ chipsets.
+
+config PHY_QCOM_USB_HSIC
+ tristate "Qualcomm USB HSIC ULPI PHY module"
+ depends on USB_ULPI_BUS
+ select GENERIC_PHY
+ help
+ Support for the USB HSIC ULPI compliant PHY on QCOM chipsets.
diff --git a/drivers/phy/qualcomm/Makefile b/drivers/phy/qualcomm/Makefile
new file mode 100644
index 000000000000..2e183d7695fd
--- /dev/null
+++ b/drivers/phy/qualcomm/Makefile
@@ -0,0 +1,9 @@
+obj-$(CONFIG_PHY_QCOM_APQ8064_SATA) += phy-qcom-apq8064-sata.o
+obj-$(CONFIG_PHY_QCOM_IPQ806X_SATA) += phy-qcom-ipq806x-sata.o
+obj-$(CONFIG_PHY_QCOM_QMP) += phy-qcom-qmp.o
+obj-$(CONFIG_PHY_QCOM_QUSB2) += phy-qcom-qusb2.o
+obj-$(CONFIG_PHY_QCOM_UFS) += phy-qcom-ufs.o
+obj-$(CONFIG_PHY_QCOM_UFS) += phy-qcom-ufs-qmp-14nm.o
+obj-$(CONFIG_PHY_QCOM_UFS) += phy-qcom-ufs-qmp-20nm.o
+obj-$(CONFIG_PHY_QCOM_USB_HS) += phy-qcom-usb-hs.o
+obj-$(CONFIG_PHY_QCOM_USB_HSIC) += phy-qcom-usb-hsic.o
diff --git a/drivers/phy/phy-qcom-apq8064-sata.c b/drivers/phy/qualcomm/phy-qcom-apq8064-sata.c
index 69ce2afac015..69ce2afac015 100644
--- a/drivers/phy/phy-qcom-apq8064-sata.c
+++ b/drivers/phy/qualcomm/phy-qcom-apq8064-sata.c
diff --git a/drivers/phy/phy-qcom-ipq806x-sata.c b/drivers/phy/qualcomm/phy-qcom-ipq806x-sata.c
index 0ad127cc9298..0ad127cc9298 100644
--- a/drivers/phy/phy-qcom-ipq806x-sata.c
+++ b/drivers/phy/qualcomm/phy-qcom-ipq806x-sata.c
diff --git a/drivers/phy/phy-qcom-qmp.c b/drivers/phy/qualcomm/phy-qcom-qmp.c
index 727e23be7cac..78ca62897784 100644
--- a/drivers/phy/phy-qcom-qmp.c
+++ b/drivers/phy/qualcomm/phy-qcom-qmp.c
@@ -844,7 +844,7 @@ static int qcom_qmp_phy_vreg_init(struct device *dev)
int num = qmp->cfg->num_vregs;
int i;
- qmp->vregs = devm_kcalloc(dev, num, sizeof(qmp->vregs), GFP_KERNEL);
+ qmp->vregs = devm_kcalloc(dev, num, sizeof(*qmp->vregs), GFP_KERNEL);
if (!qmp->vregs)
return -ENOMEM;
@@ -983,16 +983,16 @@ int qcom_qmp_phy_create(struct device *dev, struct device_node *np, int id)
* Resources are indexed as: tx -> 0; rx -> 1; pcs -> 2.
*/
qphy->tx = of_iomap(np, 0);
- if (IS_ERR(qphy->tx))
- return PTR_ERR(qphy->tx);
+ if (!qphy->tx)
+ return -ENOMEM;
qphy->rx = of_iomap(np, 1);
- if (IS_ERR(qphy->rx))
- return PTR_ERR(qphy->rx);
+ if (!qphy->rx)
+ return -ENOMEM;
qphy->pcs = of_iomap(np, 2);
- if (IS_ERR(qphy->pcs))
- return PTR_ERR(qphy->pcs);
+ if (!qphy->pcs)
+ return -ENOMEM;
/*
* Get PHY's Pipe clock, if any. USB3 and PCIe are PIPE3
diff --git a/drivers/phy/phy-qcom-qusb2.c b/drivers/phy/qualcomm/phy-qcom-qusb2.c
index 6c575244c0fb..6c575244c0fb 100644
--- a/drivers/phy/phy-qcom-qusb2.c
+++ b/drivers/phy/qualcomm/phy-qcom-qusb2.c
diff --git a/drivers/phy/phy-qcom-ufs-i.h b/drivers/phy/qualcomm/phy-qcom-ufs-i.h
index 13b02b7de30b..13b02b7de30b 100644
--- a/drivers/phy/phy-qcom-ufs-i.h
+++ b/drivers/phy/qualcomm/phy-qcom-ufs-i.h
diff --git a/drivers/phy/phy-qcom-ufs-qmp-14nm.c b/drivers/phy/qualcomm/phy-qcom-ufs-qmp-14nm.c
index 12a1b498dc4b..12a1b498dc4b 100644
--- a/drivers/phy/phy-qcom-ufs-qmp-14nm.c
+++ b/drivers/phy/qualcomm/phy-qcom-ufs-qmp-14nm.c
diff --git a/drivers/phy/phy-qcom-ufs-qmp-14nm.h b/drivers/phy/qualcomm/phy-qcom-ufs-qmp-14nm.h
index 3aefdbacbcd0..3aefdbacbcd0 100644
--- a/drivers/phy/phy-qcom-ufs-qmp-14nm.h
+++ b/drivers/phy/qualcomm/phy-qcom-ufs-qmp-14nm.h
diff --git a/drivers/phy/phy-qcom-ufs-qmp-20nm.c b/drivers/phy/qualcomm/phy-qcom-ufs-qmp-20nm.c
index 4f68acb58b73..4f68acb58b73 100644
--- a/drivers/phy/phy-qcom-ufs-qmp-20nm.c
+++ b/drivers/phy/qualcomm/phy-qcom-ufs-qmp-20nm.c
diff --git a/drivers/phy/phy-qcom-ufs-qmp-20nm.h b/drivers/phy/qualcomm/phy-qcom-ufs-qmp-20nm.h
index 4f3076bb3d71..4f3076bb3d71 100644
--- a/drivers/phy/phy-qcom-ufs-qmp-20nm.h
+++ b/drivers/phy/qualcomm/phy-qcom-ufs-qmp-20nm.h
diff --git a/drivers/phy/phy-qcom-ufs.c b/drivers/phy/qualcomm/phy-qcom-ufs.c
index 43865ef340e2..43865ef340e2 100644
--- a/drivers/phy/phy-qcom-ufs.c
+++ b/drivers/phy/qualcomm/phy-qcom-ufs.c
diff --git a/drivers/phy/phy-qcom-usb-hs.c b/drivers/phy/qualcomm/phy-qcom-usb-hs.c
index 94dfbfd739c3..4b20abc3ae2f 100644
--- a/drivers/phy/phy-qcom-usb-hs.c
+++ b/drivers/phy/qualcomm/phy-qcom-usb-hs.c
@@ -11,12 +11,11 @@
#include <linux/clk.h>
#include <linux/regulator/consumer.h>
#include <linux/of_device.h>
+#include <linux/phy/phy.h>
#include <linux/reset.h>
#include <linux/extcon.h>
#include <linux/notifier.h>
-#include "ulpi_phy.h"
-
#define ULPI_PWR_CLK_MNG_REG 0x88
# define ULPI_PWR_OTG_COMP_DISABLE BIT(0)
diff --git a/drivers/phy/phy-qcom-usb-hsic.c b/drivers/phy/qualcomm/phy-qcom-usb-hsic.c
index 47690f9945b9..c110563a73cb 100644
--- a/drivers/phy/phy-qcom-usb-hsic.c
+++ b/drivers/phy/qualcomm/phy-qcom-usb-hsic.c
@@ -8,13 +8,12 @@
#include <linux/module.h>
#include <linux/ulpi/driver.h>
#include <linux/ulpi/regs.h>
+#include <linux/phy/phy.h>
#include <linux/pinctrl/consumer.h>
#include <linux/pinctrl/pinctrl-state.h>
#include <linux/delay.h>
#include <linux/clk.h>
-#include "ulpi_phy.h"
-
#define ULPI_HSIC_CFG 0x30
#define ULPI_HSIC_IO_CAL 0x33
diff --git a/drivers/phy/renesas/Kconfig b/drivers/phy/renesas/Kconfig
new file mode 100644
index 000000000000..cb09245e9b4c
--- /dev/null
+++ b/drivers/phy/renesas/Kconfig
@@ -0,0 +1,24 @@
+#
+# Phy drivers for Renesas platforms
+#
+config PHY_RCAR_GEN2
+ tristate "Renesas R-Car generation 2 USB PHY driver"
+ depends on ARCH_RENESAS
+ depends on GENERIC_PHY
+ help
+ Support for USB PHY found on Renesas R-Car generation 2 SoCs.
+
+config PHY_RCAR_GEN3_USB2
+ tristate "Renesas R-Car generation 3 USB 2.0 PHY driver"
+ depends on ARCH_RENESAS
+ depends on EXTCON
+ select GENERIC_PHY
+ help
+ Support for USB 2.0 PHY found on Renesas R-Car generation 3 SoCs.
+
+config PHY_RCAR_GEN3_USB3
+ tristate "Renesas R-Car generation 3 USB 3.0 PHY driver"
+ depends on ARCH_RENESAS || COMPILE_TEST
+ select GENERIC_PHY
+ help
+ Support for USB 3.0 PHY found on Renesas R-Car generation 3 SoCs.
diff --git a/drivers/phy/renesas/Makefile b/drivers/phy/renesas/Makefile
new file mode 100644
index 000000000000..8b6025916a93
--- /dev/null
+++ b/drivers/phy/renesas/Makefile
@@ -0,0 +1,3 @@
+obj-$(CONFIG_PHY_RCAR_GEN2) += phy-rcar-gen2.o
+obj-$(CONFIG_PHY_RCAR_GEN3_USB2) += phy-rcar-gen3-usb2.o
+obj-$(CONFIG_PHY_RCAR_GEN3_USB3) += phy-rcar-gen3-usb3.o
diff --git a/drivers/phy/phy-rcar-gen2.c b/drivers/phy/renesas/phy-rcar-gen2.c
index 97d4dd6ea924..97d4dd6ea924 100644
--- a/drivers/phy/phy-rcar-gen2.c
+++ b/drivers/phy/renesas/phy-rcar-gen2.c
diff --git a/drivers/phy/phy-rcar-gen3-usb2.c b/drivers/phy/renesas/phy-rcar-gen3-usb2.c
index 54c34298a000..54c34298a000 100644
--- a/drivers/phy/phy-rcar-gen3-usb2.c
+++ b/drivers/phy/renesas/phy-rcar-gen3-usb2.c
diff --git a/drivers/phy/renesas/phy-rcar-gen3-usb3.c b/drivers/phy/renesas/phy-rcar-gen3-usb3.c
new file mode 100644
index 000000000000..88c83c9b8ff9
--- /dev/null
+++ b/drivers/phy/renesas/phy-rcar-gen3-usb3.c
@@ -0,0 +1,226 @@
+/*
+ * Renesas R-Car Gen3 for USB3.0 PHY driver
+ *
+ * Copyright (C) 2017 Renesas Electronics Corporation
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/clk.h>
+#include <linux/delay.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/phy/phy.h>
+#include <linux/platform_device.h>
+#include <linux/pm_runtime.h>
+
+#define USB30_CLKSET0 0x034
+#define USB30_CLKSET1 0x036
+#define USB30_SSC_SET 0x038
+#define USB30_PHY_ENABLE 0x060
+#define USB30_VBUS_EN 0x064
+
+/* USB30_CLKSET0 */
+#define CLKSET0_PRIVATE 0x05c0
+#define CLKSET0_USB30_FSEL_USB_EXTAL 0x0002
+
+/* USB30_CLKSET1 */
+#define CLKSET1_USB30_PLL_MULTI_SHIFT 6
+#define CLKSET1_USB30_PLL_MULTI_USB_EXTAL (0x64 << \
+ CLKSET1_USB30_PLL_MULTI_SHIFT)
+#define CLKSET1_PHYRESET BIT(4) /* 1: reset */
+#define CLKSET1_REF_CLKDIV BIT(3) /* 1: USB_EXTAL */
+#define CLKSET1_PRIVATE_2_1 BIT(1) /* Write B'01 */
+#define CLKSET1_REF_CLK_SEL BIT(0) /* 1: USB3S0_CLK_P */
+
+/* USB30_SSC_SET */
+#define SSC_SET_SSC_EN BIT(12)
+#define SSC_SET_RANGE_SHIFT 9
+#define SSC_SET_RANGE_4980 (0x0 << SSC_SET_RANGE_SHIFT)
+#define SSC_SET_RANGE_4492 (0x1 << SSC_SET_RANGE_SHIFT)
+#define SSC_SET_RANGE_4003 (0x2 << SSC_SET_RANGE_SHIFT)
+
+/* USB30_PHY_ENABLE */
+#define PHY_ENABLE_RESET_EN BIT(4)
+
+/* USB30_VBUS_EN */
+#define VBUS_EN_VBUS_EN BIT(1)
+
+struct rcar_gen3_usb3 {
+ void __iomem *base;
+ struct phy *phy;
+ u32 ssc_range;
+ bool usb3s_clk;
+ bool usb_extal;
+};
+
+static void write_clkset1_for_usb_extal(struct rcar_gen3_usb3 *r, bool reset)
+{
+ u16 val = CLKSET1_USB30_PLL_MULTI_USB_EXTAL |
+ CLKSET1_REF_CLKDIV | CLKSET1_PRIVATE_2_1;
+
+ if (reset)
+ val |= CLKSET1_PHYRESET;
+
+ writew(val, r->base + USB30_CLKSET1);
+}
+
+static void rcar_gen3_phy_usb3_enable_ssc(struct rcar_gen3_usb3 *r)
+{
+ u16 val = SSC_SET_SSC_EN;
+
+ switch (r->ssc_range) {
+ case 4980:
+ val |= SSC_SET_RANGE_4980;
+ break;
+ case 4492:
+ val |= SSC_SET_RANGE_4492;
+ break;
+ case 4003:
+ val |= SSC_SET_RANGE_4003;
+ break;
+ default:
+ dev_err(&r->phy->dev, "%s: unsupported range (%x)\n", __func__,
+ r->ssc_range);
+ return;
+ }
+
+ writew(val, r->base + USB30_SSC_SET);
+}
+
+static void rcar_gen3_phy_usb3_select_usb_extal(struct rcar_gen3_usb3 *r)
+{
+ write_clkset1_for_usb_extal(r, false);
+ if (r->ssc_range)
+ rcar_gen3_phy_usb3_enable_ssc(r);
+ writew(CLKSET0_PRIVATE | CLKSET0_USB30_FSEL_USB_EXTAL,
+ r->base + USB30_CLKSET0);
+ writew(PHY_ENABLE_RESET_EN, r->base + USB30_PHY_ENABLE);
+ write_clkset1_for_usb_extal(r, true);
+ usleep_range(10, 20);
+ write_clkset1_for_usb_extal(r, false);
+}
+
+static int rcar_gen3_phy_usb3_init(struct phy *p)
+{
+ struct rcar_gen3_usb3 *r = phy_get_drvdata(p);
+
+ dev_vdbg(&r->phy->dev, "%s: enter (%d, %d, %d)\n", __func__,
+ r->usb3s_clk, r->usb_extal, r->ssc_range);
+
+ if (!r->usb3s_clk && r->usb_extal)
+ rcar_gen3_phy_usb3_select_usb_extal(r);
+
+ /* Enables VBUS detection anyway */
+ writew(VBUS_EN_VBUS_EN, r->base + USB30_VBUS_EN);
+
+ return 0;
+}
+
+static const struct phy_ops rcar_gen3_phy_usb3_ops = {
+ .init = rcar_gen3_phy_usb3_init,
+ .owner = THIS_MODULE,
+};
+
+static const struct of_device_id rcar_gen3_phy_usb3_match_table[] = {
+ { .compatible = "renesas,rcar-gen3-usb3-phy" },
+ { }
+};
+MODULE_DEVICE_TABLE(of, rcar_gen3_phy_usb3_match_table);
+
+static int rcar_gen3_phy_usb3_probe(struct platform_device *pdev)
+{
+ struct device *dev = &pdev->dev;
+ struct rcar_gen3_usb3 *r;
+ struct phy_provider *provider;
+ struct resource *res;
+ int ret = 0;
+ struct clk *clk;
+
+ if (!dev->of_node) {
+ dev_err(dev, "This driver needs device tree\n");
+ return -EINVAL;
+ }
+
+ r = devm_kzalloc(dev, sizeof(*r), GFP_KERNEL);
+ if (!r)
+ return -ENOMEM;
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ r->base = devm_ioremap_resource(dev, res);
+ if (IS_ERR(r->base))
+ return PTR_ERR(r->base);
+
+ clk = devm_clk_get(dev, "usb3s_clk");
+ if (!IS_ERR(clk) && !clk_prepare_enable(clk)) {
+ r->usb3s_clk = !!clk_get_rate(clk);
+ clk_disable_unprepare(clk);
+ }
+ clk = devm_clk_get(dev, "usb_extal");
+ if (!IS_ERR(clk) && !clk_prepare_enable(clk)) {
+ r->usb_extal = !!clk_get_rate(clk);
+ clk_disable_unprepare(clk);
+ }
+
+ if (!r->usb3s_clk && !r->usb_extal) {
+ dev_err(dev, "This driver needs usb3s_clk and/or usb_extal\n");
+ ret = -EINVAL;
+ goto error;
+ }
+
+ /*
+ * devm_phy_create() will call pm_runtime_enable(&phy->dev);
+ * And then, phy-core will manage runtime pm for this device.
+ */
+ pm_runtime_enable(dev);
+
+ r->phy = devm_phy_create(dev, NULL, &rcar_gen3_phy_usb3_ops);
+ if (IS_ERR(r->phy)) {
+ dev_err(dev, "Failed to create USB3 PHY\n");
+ ret = PTR_ERR(r->phy);
+ goto error;
+ }
+
+ of_property_read_u32(dev->of_node, "renesas,ssc-range", &r->ssc_range);
+
+ platform_set_drvdata(pdev, r);
+ phy_set_drvdata(r->phy, r);
+
+ provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate);
+ if (IS_ERR(provider)) {
+ dev_err(dev, "Failed to register PHY provider\n");
+ ret = PTR_ERR(provider);
+ goto error;
+ }
+
+ return 0;
+
+error:
+ pm_runtime_disable(dev);
+
+ return ret;
+}
+
+static int rcar_gen3_phy_usb3_remove(struct platform_device *pdev)
+{
+ pm_runtime_disable(&pdev->dev);
+
+ return 0;
+};
+
+static struct platform_driver rcar_gen3_phy_usb3_driver = {
+ .driver = {
+ .name = "phy_rcar_gen3_usb3",
+ .of_match_table = rcar_gen3_phy_usb3_match_table,
+ },
+ .probe = rcar_gen3_phy_usb3_probe,
+ .remove = rcar_gen3_phy_usb3_remove,
+};
+module_platform_driver(rcar_gen3_phy_usb3_driver);
+
+MODULE_LICENSE("GPL v2");
+MODULE_DESCRIPTION("Renesas R-Car Gen3 USB 3.0 PHY");
+MODULE_AUTHOR("Yoshihiro Shimoda <yoshihiro.shimoda.uh@renesas.com>");
diff --git a/drivers/phy/rockchip/Kconfig b/drivers/phy/rockchip/Kconfig
new file mode 100644
index 000000000000..f5325b2b679e
--- /dev/null
+++ b/drivers/phy/rockchip/Kconfig
@@ -0,0 +1,51 @@
+#
+# Phy drivers for Rockchip platforms
+#
+config PHY_ROCKCHIP_DP
+ tristate "Rockchip Display Port PHY Driver"
+ depends on ARCH_ROCKCHIP && OF
+ select GENERIC_PHY
+ help
+ Enable this to support the Rockchip Display Port PHY.
+
+config PHY_ROCKCHIP_EMMC
+ tristate "Rockchip EMMC PHY Driver"
+ depends on ARCH_ROCKCHIP && OF
+ select GENERIC_PHY
+ help
+ Enable this to support the Rockchip EMMC PHY.
+
+config PHY_ROCKCHIP_INNO_USB2
+ tristate "Rockchip INNO USB2PHY Driver"
+ depends on (ARCH_ROCKCHIP || COMPILE_TEST) && OF
+ depends on COMMON_CLK
+ depends on EXTCON
+ depends on USB_SUPPORT
+ select GENERIC_PHY
+ select USB_COMMON
+ help
+ Support for Rockchip USB2.0 PHY with Innosilicon IP block.
+
+config PHY_ROCKCHIP_PCIE
+ tristate "Rockchip PCIe PHY Driver"
+ depends on (ARCH_ROCKCHIP && OF) || COMPILE_TEST
+ select GENERIC_PHY
+ select MFD_SYSCON
+ help
+ Enable this to support the Rockchip PCIe PHY.
+
+config PHY_ROCKCHIP_TYPEC
+ tristate "Rockchip TYPEC PHY Driver"
+ depends on OF && (ARCH_ROCKCHIP || COMPILE_TEST)
+ select EXTCON
+ select GENERIC_PHY
+ select RESET_CONTROLLER
+ help
+ Enable this to support the Rockchip USB TYPEC PHY.
+
+config PHY_ROCKCHIP_USB
+ tristate "Rockchip USB2 PHY Driver"
+ depends on ARCH_ROCKCHIP && OF
+ select GENERIC_PHY
+ help
+ Enable this to support the Rockchip USB 2.0 PHY.
diff --git a/drivers/phy/rockchip/Makefile b/drivers/phy/rockchip/Makefile
new file mode 100644
index 000000000000..bd0acdf38e0f
--- /dev/null
+++ b/drivers/phy/rockchip/Makefile
@@ -0,0 +1,6 @@
+obj-$(CONFIG_PHY_ROCKCHIP_DP) += phy-rockchip-dp.o
+obj-$(CONFIG_PHY_ROCKCHIP_EMMC) += phy-rockchip-emmc.o
+obj-$(CONFIG_PHY_ROCKCHIP_INNO_USB2) += phy-rockchip-inno-usb2.o
+obj-$(CONFIG_PHY_ROCKCHIP_PCIE) += phy-rockchip-pcie.o
+obj-$(CONFIG_PHY_ROCKCHIP_TYPEC) += phy-rockchip-typec.o
+obj-$(CONFIG_PHY_ROCKCHIP_USB) += phy-rockchip-usb.o
diff --git a/drivers/phy/phy-rockchip-dp.c b/drivers/phy/rockchip/phy-rockchip-dp.c
index 8b267a746576..8b267a746576 100644
--- a/drivers/phy/phy-rockchip-dp.c
+++ b/drivers/phy/rockchip/phy-rockchip-dp.c
diff --git a/drivers/phy/phy-rockchip-emmc.c b/drivers/phy/rockchip/phy-rockchip-emmc.c
index f1b24f18e9b2..f1b24f18e9b2 100644
--- a/drivers/phy/phy-rockchip-emmc.c
+++ b/drivers/phy/rockchip/phy-rockchip-emmc.c
diff --git a/drivers/phy/phy-rockchip-inno-usb2.c b/drivers/phy/rockchip/phy-rockchip-inno-usb2.c
index 8efe78a49916..626883d9d176 100644
--- a/drivers/phy/phy-rockchip-inno-usb2.c
+++ b/drivers/phy/rockchip/phy-rockchip-inno-usb2.c
@@ -406,7 +406,8 @@ static int rockchip_usb2phy_init(struct phy *phy)
mutex_lock(&rport->mutex);
if (rport->port_id == USB2PHY_PORT_OTG) {
- if (rport->mode != USB_DR_MODE_HOST) {
+ if (rport->mode != USB_DR_MODE_HOST &&
+ rport->mode != USB_DR_MODE_UNKNOWN) {
/* clear bvalid status and enable bvalid detect irq */
ret = property_enable(rphy,
&rport->port_cfg->bvalid_det_clr,
@@ -421,7 +422,7 @@ static int rockchip_usb2phy_init(struct phy *phy)
goto out;
schedule_delayed_work(&rport->otg_sm_work,
- OTG_SCHEDULE_DELAY);
+ OTG_SCHEDULE_DELAY * 3);
} else {
/* If OTG works in host only mode, do nothing. */
dev_dbg(&rport->phy->dev, "mode %d\n", rport->mode);
@@ -463,6 +464,9 @@ static int rockchip_usb2phy_power_on(struct phy *phy)
if (ret)
return ret;
+ /* waiting for the utmi_clk to become stable */
+ usleep_range(1500, 2000);
+
rport->suspended = false;
return 0;
}
@@ -493,7 +497,8 @@ static int rockchip_usb2phy_exit(struct phy *phy)
struct rockchip_usb2phy_port *rport = phy_get_drvdata(phy);
if (rport->port_id == USB2PHY_PORT_OTG &&
- rport->mode != USB_DR_MODE_HOST) {
+ rport->mode != USB_DR_MODE_HOST &&
+ rport->mode != USB_DR_MODE_UNKNOWN) {
cancel_delayed_work_sync(&rport->otg_sm_work);
cancel_delayed_work_sync(&rport->chg_work);
} else if (rport->port_id == USB2PHY_PORT_HOST)
@@ -970,7 +975,8 @@ static int rockchip_usb2phy_otg_port_init(struct rockchip_usb2phy *rphy,
mutex_init(&rport->mutex);
rport->mode = of_usb_get_dr_mode_by_phy(child_np, -1);
- if (rport->mode == USB_DR_MODE_HOST) {
+ if (rport->mode == USB_DR_MODE_HOST ||
+ rport->mode == USB_DR_MODE_UNKNOWN) {
ret = 0;
goto out;
}
@@ -1138,6 +1144,65 @@ disable_clks:
return ret;
}
+static const struct rockchip_usb2phy_cfg rk3228_phy_cfgs[] = {
+ {
+ .reg = 0x760,
+ .num_ports = 2,
+ .clkout_ctl = { 0x0768, 4, 4, 1, 0 },
+ .port_cfgs = {
+ [USB2PHY_PORT_OTG] = {
+ .phy_sus = { 0x0760, 15, 0, 0, 0x1d1 },
+ .bvalid_det_en = { 0x0680, 3, 3, 0, 1 },
+ .bvalid_det_st = { 0x0690, 3, 3, 0, 1 },
+ .bvalid_det_clr = { 0x06a0, 3, 3, 0, 1 },
+ .ls_det_en = { 0x0680, 2, 2, 0, 1 },
+ .ls_det_st = { 0x0690, 2, 2, 0, 1 },
+ .ls_det_clr = { 0x06a0, 2, 2, 0, 1 },
+ .utmi_bvalid = { 0x0480, 4, 4, 0, 1 },
+ .utmi_ls = { 0x0480, 3, 2, 0, 1 },
+ },
+ [USB2PHY_PORT_HOST] = {
+ .phy_sus = { 0x0764, 15, 0, 0, 0x1d1 },
+ .ls_det_en = { 0x0680, 4, 4, 0, 1 },
+ .ls_det_st = { 0x0690, 4, 4, 0, 1 },
+ .ls_det_clr = { 0x06a0, 4, 4, 0, 1 }
+ }
+ },
+ .chg_det = {
+ .opmode = { 0x0760, 3, 0, 5, 1 },
+ .cp_det = { 0x0884, 4, 4, 0, 1 },
+ .dcp_det = { 0x0884, 3, 3, 0, 1 },
+ .dp_det = { 0x0884, 5, 5, 0, 1 },
+ .idm_sink_en = { 0x0768, 8, 8, 0, 1 },
+ .idp_sink_en = { 0x0768, 7, 7, 0, 1 },
+ .idp_src_en = { 0x0768, 9, 9, 0, 1 },
+ .rdm_pdwn_en = { 0x0768, 10, 10, 0, 1 },
+ .vdm_src_en = { 0x0768, 12, 12, 0, 1 },
+ .vdp_src_en = { 0x0768, 11, 11, 0, 1 },
+ },
+ },
+ {
+ .reg = 0x800,
+ .num_ports = 2,
+ .clkout_ctl = { 0x0808, 4, 4, 1, 0 },
+ .port_cfgs = {
+ [USB2PHY_PORT_OTG] = {
+ .phy_sus = { 0x800, 15, 0, 0, 0x1d1 },
+ .ls_det_en = { 0x0684, 0, 0, 0, 1 },
+ .ls_det_st = { 0x0694, 0, 0, 0, 1 },
+ .ls_det_clr = { 0x06a4, 0, 0, 0, 1 }
+ },
+ [USB2PHY_PORT_HOST] = {
+ .phy_sus = { 0x804, 15, 0, 0, 0x1d1 },
+ .ls_det_en = { 0x0684, 1, 1, 0, 1 },
+ .ls_det_st = { 0x0694, 1, 1, 0, 1 },
+ .ls_det_clr = { 0x06a4, 1, 1, 0, 1 }
+ }
+ },
+ },
+ { /* sentinel */ }
+};
+
static const struct rockchip_usb2phy_cfg rk3328_phy_cfgs[] = {
{
.reg = 0x100,
@@ -1263,6 +1328,7 @@ static const struct rockchip_usb2phy_cfg rk3399_phy_cfgs[] = {
};
static const struct of_device_id rockchip_usb2phy_dt_match[] = {
+ { .compatible = "rockchip,rk3228-usb2phy", .data = &rk3228_phy_cfgs },
{ .compatible = "rockchip,rk3328-usb2phy", .data = &rk3328_phy_cfgs },
{ .compatible = "rockchip,rk3366-usb2phy", .data = &rk3366_phy_cfgs },
{ .compatible = "rockchip,rk3399-usb2phy", .data = &rk3399_phy_cfgs },
diff --git a/drivers/phy/phy-rockchip-pcie.c b/drivers/phy/rockchip/phy-rockchip-pcie.c
index 6904633cad68..6904633cad68 100644
--- a/drivers/phy/phy-rockchip-pcie.c
+++ b/drivers/phy/rockchip/phy-rockchip-pcie.c
diff --git a/drivers/phy/phy-rockchip-typec.c b/drivers/phy/rockchip/phy-rockchip-typec.c
index 7cfb0f8995de..7cfb0f8995de 100644
--- a/drivers/phy/phy-rockchip-typec.c
+++ b/drivers/phy/rockchip/phy-rockchip-typec.c
diff --git a/drivers/phy/phy-rockchip-usb.c b/drivers/phy/rockchip/phy-rockchip-usb.c
index 3378eeb7a562..3378eeb7a562 100644
--- a/drivers/phy/phy-rockchip-usb.c
+++ b/drivers/phy/rockchip/phy-rockchip-usb.c
diff --git a/drivers/phy/samsung/Kconfig b/drivers/phy/samsung/Kconfig
new file mode 100644
index 000000000000..b7e0645a7bd9
--- /dev/null
+++ b/drivers/phy/samsung/Kconfig
@@ -0,0 +1,95 @@
+#
+# Phy drivers for Samsung platforms
+#
+config PHY_EXYNOS_DP_VIDEO
+ tristate "EXYNOS SoC series Display Port PHY driver"
+ depends on OF
+ depends on ARCH_EXYNOS || COMPILE_TEST
+ default ARCH_EXYNOS
+ select GENERIC_PHY
+ help
+ Support for Display Port PHY found on Samsung EXYNOS SoCs.
+
+config PHY_EXYNOS_MIPI_VIDEO
+ tristate "S5P/EXYNOS SoC series MIPI CSI-2/DSI PHY driver"
+ depends on HAS_IOMEM
+ depends on ARCH_S5PV210 || ARCH_EXYNOS || COMPILE_TEST
+ select GENERIC_PHY
+ default y if ARCH_S5PV210 || ARCH_EXYNOS
+ help
+ Support for MIPI CSI-2 and MIPI DSI DPHY found on Samsung S5P
+ and EXYNOS SoCs.
+
+config PHY_EXYNOS_PCIE
+ bool "Exynos PCIe PHY driver"
+ depends on OF && (ARCH_EXYNOS || COMPILE_TEST)
+ select GENERIC_PHY
+ help
+ Enable PCIe PHY support for Exynos SoC series.
+ This driver provides PHY interface for Exynos PCIe controller.
+
+config PHY_SAMSUNG_USB2
+ tristate "Samsung USB 2.0 PHY driver"
+ depends on HAS_IOMEM
+ depends on USB_EHCI_EXYNOS || USB_OHCI_EXYNOS || USB_DWC2
+ select GENERIC_PHY
+ select MFD_SYSCON
+ default ARCH_EXYNOS
+ help
+ Enable this to support the Samsung USB 2.0 PHY driver for Samsung
+ SoCs. This driver provides the interface for USB 2.0 PHY. Support
+ for particular PHYs will be enabled based on the SoC type in addition
+ to this driver.
+
+config PHY_EXYNOS4210_USB2
+ bool
+ depends on PHY_SAMSUNG_USB2
+ default CPU_EXYNOS4210
+
+config PHY_EXYNOS4X12_USB2
+ bool
+ depends on PHY_SAMSUNG_USB2
+ default SOC_EXYNOS3250 || SOC_EXYNOS4212 || SOC_EXYNOS4412
+
+config PHY_EXYNOS5250_USB2
+ bool
+ depends on PHY_SAMSUNG_USB2
+ default SOC_EXYNOS5250 || SOC_EXYNOS5420
+
+config PHY_S5PV210_USB2
+ bool "Support for S5PV210"
+ depends on PHY_SAMSUNG_USB2
+ depends on ARCH_S5PV210
+ help
+ Enable USB PHY support for S5PV210. This option requires that Samsung
+ USB 2.0 PHY driver is enabled and means that support for this
+ particular SoC is compiled in the driver. In case of S5PV210 two phys
+ are available - device and host.
+
+config PHY_EXYNOS5_USBDRD
+ tristate "Exynos5 SoC series USB DRD PHY driver"
+ depends on ARCH_EXYNOS && OF
+ depends on HAS_IOMEM
+ depends on USB_DWC3_EXYNOS
+ select GENERIC_PHY
+ select MFD_SYSCON
+ default y
+ help
+ Enable USB DRD PHY support for Exynos 5 SoC series.
+ This driver provides PHY interface for USB 3.0 DRD controller
+ present on Exynos5 SoC series.
+
+config PHY_EXYNOS5250_SATA
+ tristate "Exynos5250 Sata SerDes/PHY driver"
+ depends on SOC_EXYNOS5250
+ depends on HAS_IOMEM
+ depends on OF
+ select GENERIC_PHY
+ select I2C
+ select I2C_S3C2410
+ select MFD_SYSCON
+ help
+ Enable this to support SATA SerDes/Phy found on Samsung's
+ Exynos5250 based SoCs.This SerDes/Phy supports SATA 1.5 Gb/s,
+ SATA 3.0 Gb/s, SATA 6.0 Gb/s speeds. It supports one SATA host
+ port to accept one SATA device.
diff --git a/drivers/phy/samsung/Makefile b/drivers/phy/samsung/Makefile
new file mode 100644
index 000000000000..20d7f2424772
--- /dev/null
+++ b/drivers/phy/samsung/Makefile
@@ -0,0 +1,11 @@
+obj-$(CONFIG_PHY_EXYNOS_DP_VIDEO) += phy-exynos-dp-video.o
+obj-$(CONFIG_PHY_EXYNOS_MIPI_VIDEO) += phy-exynos-mipi-video.o
+obj-$(CONFIG_PHY_EXYNOS_PCIE) += phy-exynos-pcie.o
+obj-$(CONFIG_PHY_SAMSUNG_USB2) += phy-exynos-usb2.o
+phy-exynos-usb2-y += phy-samsung-usb2.o
+phy-exynos-usb2-$(CONFIG_PHY_EXYNOS4210_USB2) += phy-exynos4210-usb2.o
+phy-exynos-usb2-$(CONFIG_PHY_EXYNOS4X12_USB2) += phy-exynos4x12-usb2.o
+phy-exynos-usb2-$(CONFIG_PHY_EXYNOS5250_USB2) += phy-exynos5250-usb2.o
+phy-exynos-usb2-$(CONFIG_PHY_S5PV210_USB2) += phy-s5pv210-usb2.o
+obj-$(CONFIG_PHY_EXYNOS5_USBDRD) += phy-exynos5-usbdrd.o
+obj-$(CONFIG_PHY_EXYNOS5250_SATA) += phy-exynos5250-sata.o
diff --git a/drivers/phy/phy-exynos-dp-video.c b/drivers/phy/samsung/phy-exynos-dp-video.c
index bb3279dbf88c..bb3279dbf88c 100644
--- a/drivers/phy/phy-exynos-dp-video.c
+++ b/drivers/phy/samsung/phy-exynos-dp-video.c
diff --git a/drivers/phy/phy-exynos-mipi-video.c b/drivers/phy/samsung/phy-exynos-mipi-video.c
index c198886f80a3..c198886f80a3 100644
--- a/drivers/phy/phy-exynos-mipi-video.c
+++ b/drivers/phy/samsung/phy-exynos-mipi-video.c
diff --git a/drivers/phy/phy-exynos-pcie.c b/drivers/phy/samsung/phy-exynos-pcie.c
index a89c12faff39..a89c12faff39 100644
--- a/drivers/phy/phy-exynos-pcie.c
+++ b/drivers/phy/samsung/phy-exynos-pcie.c
diff --git a/drivers/phy/phy-exynos4210-usb2.c b/drivers/phy/samsung/phy-exynos4210-usb2.c
index 1f50e1004828..1f50e1004828 100644
--- a/drivers/phy/phy-exynos4210-usb2.c
+++ b/drivers/phy/samsung/phy-exynos4210-usb2.c
diff --git a/drivers/phy/phy-exynos4x12-usb2.c b/drivers/phy/samsung/phy-exynos4x12-usb2.c
index 7f27a91acf87..7f27a91acf87 100644
--- a/drivers/phy/phy-exynos4x12-usb2.c
+++ b/drivers/phy/samsung/phy-exynos4x12-usb2.c
diff --git a/drivers/phy/phy-exynos5-usbdrd.c b/drivers/phy/samsung/phy-exynos5-usbdrd.c
index 7c41daa2c625..7c41daa2c625 100644
--- a/drivers/phy/phy-exynos5-usbdrd.c
+++ b/drivers/phy/samsung/phy-exynos5-usbdrd.c
diff --git a/drivers/phy/phy-exynos5250-sata.c b/drivers/phy/samsung/phy-exynos5250-sata.c
index 60e13afcd9b8..60e13afcd9b8 100644
--- a/drivers/phy/phy-exynos5250-sata.c
+++ b/drivers/phy/samsung/phy-exynos5250-sata.c
diff --git a/drivers/phy/phy-exynos5250-usb2.c b/drivers/phy/samsung/phy-exynos5250-usb2.c
index aad806272305..aad806272305 100644
--- a/drivers/phy/phy-exynos5250-usb2.c
+++ b/drivers/phy/samsung/phy-exynos5250-usb2.c
diff --git a/drivers/phy/phy-s5pv210-usb2.c b/drivers/phy/samsung/phy-s5pv210-usb2.c
index f6f72339bbc3..f6f72339bbc3 100644
--- a/drivers/phy/phy-s5pv210-usb2.c
+++ b/drivers/phy/samsung/phy-s5pv210-usb2.c
diff --git a/drivers/phy/phy-samsung-usb2.c b/drivers/phy/samsung/phy-samsung-usb2.c
index 1d22d93b552d..1d22d93b552d 100644
--- a/drivers/phy/phy-samsung-usb2.c
+++ b/drivers/phy/samsung/phy-samsung-usb2.c
diff --git a/drivers/phy/phy-samsung-usb2.h b/drivers/phy/samsung/phy-samsung-usb2.h
index 6563e7ca0ac4..6563e7ca0ac4 100644
--- a/drivers/phy/phy-samsung-usb2.h
+++ b/drivers/phy/samsung/phy-samsung-usb2.h
diff --git a/drivers/phy/st/Kconfig b/drivers/phy/st/Kconfig
new file mode 100644
index 000000000000..0814d3f87ec6
--- /dev/null
+++ b/drivers/phy/st/Kconfig
@@ -0,0 +1,33 @@
+#
+# Phy drivers for STMicro platforms
+#
+config PHY_MIPHY28LP
+ tristate "STMicroelectronics MIPHY28LP PHY driver for STiH407"
+ depends on ARCH_STI
+ select GENERIC_PHY
+ help
+ Enable this to support the miphy transceiver (for SATA/PCIE/USB3)
+ that is part of STMicroelectronics STiH407 SoC.
+
+config PHY_ST_SPEAR1310_MIPHY
+ tristate "ST SPEAR1310-MIPHY driver"
+ select GENERIC_PHY
+ depends on MACH_SPEAR1310 || COMPILE_TEST
+ help
+ Support for ST SPEAr1310 MIPHY which can be used for PCIe and SATA.
+
+config PHY_ST_SPEAR1340_MIPHY
+ tristate "ST SPEAR1340-MIPHY driver"
+ select GENERIC_PHY
+ depends on MACH_SPEAR1340 || COMPILE_TEST
+ help
+ Support for ST SPEAr1340 MIPHY which can be used for PCIe and SATA.
+
+config PHY_STIH407_USB
+ tristate "STMicroelectronics USB2 picoPHY driver for STiH407 family"
+ depends on RESET_CONTROLLER
+ depends on ARCH_STI || COMPILE_TEST
+ select GENERIC_PHY
+ help
+ Enable this support to enable the picoPHY device used by USB2
+ and USB3 controllers on STMicroelectronics STiH407 SoC families.
diff --git a/drivers/phy/st/Makefile b/drivers/phy/st/Makefile
new file mode 100644
index 000000000000..e2adfe2166d2
--- /dev/null
+++ b/drivers/phy/st/Makefile
@@ -0,0 +1,4 @@
+obj-$(CONFIG_PHY_MIPHY28LP) += phy-miphy28lp.o
+obj-$(CONFIG_PHY_ST_SPEAR1310_MIPHY) += phy-spear1310-miphy.o
+obj-$(CONFIG_PHY_ST_SPEAR1340_MIPHY) += phy-spear1340-miphy.o
+obj-$(CONFIG_PHY_STIH407_USB) += phy-stih407-usb.o
diff --git a/drivers/phy/phy-miphy28lp.c b/drivers/phy/st/phy-miphy28lp.c
index 213e2e15339c..213e2e15339c 100644
--- a/drivers/phy/phy-miphy28lp.c
+++ b/drivers/phy/st/phy-miphy28lp.c
diff --git a/drivers/phy/phy-spear1310-miphy.c b/drivers/phy/st/phy-spear1310-miphy.c
index ed67e98e54ca..ed67e98e54ca 100644
--- a/drivers/phy/phy-spear1310-miphy.c
+++ b/drivers/phy/st/phy-spear1310-miphy.c
diff --git a/drivers/phy/phy-spear1340-miphy.c b/drivers/phy/st/phy-spear1340-miphy.c
index 97280c0cf612..97280c0cf612 100644
--- a/drivers/phy/phy-spear1340-miphy.c
+++ b/drivers/phy/st/phy-spear1340-miphy.c
diff --git a/drivers/phy/phy-stih407-usb.c b/drivers/phy/st/phy-stih407-usb.c
index b1f44ab669fb..b1f44ab669fb 100644
--- a/drivers/phy/phy-stih407-usb.c
+++ b/drivers/phy/st/phy-stih407-usb.c
diff --git a/drivers/phy/ti/Kconfig b/drivers/phy/ti/Kconfig
new file mode 100644
index 000000000000..20503562666c
--- /dev/null
+++ b/drivers/phy/ti/Kconfig
@@ -0,0 +1,78 @@
+#
+# Phy drivers for TI platforms
+#
+config PHY_DA8XX_USB
+ tristate "TI DA8xx USB PHY Driver"
+ depends on ARCH_DAVINCI_DA8XX
+ select GENERIC_PHY
+ select MFD_SYSCON
+ help
+ Enable this to support the USB PHY on DA8xx SoCs.
+
+ This driver controls both the USB 1.1 PHY and the USB 2.0 PHY.
+
+config PHY_DM816X_USB
+ tristate "TI dm816x USB PHY driver"
+ depends on ARCH_OMAP2PLUS
+ depends on USB_SUPPORT
+ select GENERIC_PHY
+ select USB_PHY
+ help
+ Enable this for dm816x USB to work.
+
+config OMAP_CONTROL_PHY
+ tristate "OMAP CONTROL PHY Driver"
+ depends on ARCH_OMAP2PLUS || COMPILE_TEST
+ help
+ Enable this to add support for the PHY part present in the control
+ module. This driver has API to power on the USB2 PHY and to write to
+ the mailbox. The mailbox is present only in omap4 and the register to
+ power on the USB2 PHY is present in OMAP4 and OMAP5. OMAP5 has an
+ additional register to power on USB3 PHY/SATA PHY/PCIE PHY
+ (PIPE3 PHY).
+
+config OMAP_USB2
+ tristate "OMAP USB2 PHY Driver"
+ depends on ARCH_OMAP2PLUS
+ depends on USB_SUPPORT
+ select GENERIC_PHY
+ select USB_PHY
+ select OMAP_CONTROL_PHY
+ depends on OMAP_OCP2SCP
+ help
+ Enable this to support the transceiver that is part of SOC. This
+ driver takes care of all the PHY functionality apart from comparator.
+ The USB OTG controller communicates with the comparator using this
+ driver.
+
+config TI_PIPE3
+ tristate "TI PIPE3 PHY Driver"
+ depends on ARCH_OMAP2PLUS || COMPILE_TEST
+ select GENERIC_PHY
+ select OMAP_CONTROL_PHY
+ depends on OMAP_OCP2SCP
+ help
+ Enable this to support the PIPE3 PHY that is part of TI SOCs. This
+ driver takes care of all the PHY functionality apart from comparator.
+ This driver interacts with the "OMAP Control PHY Driver" to power
+ on/off the PHY.
+
+config PHY_TUSB1210
+ tristate "TI TUSB1210 ULPI PHY module"
+ depends on USB_ULPI_BUS
+ select GENERIC_PHY
+ help
+ Support for TI TUSB1210 USB ULPI PHY.
+
+config TWL4030_USB
+ tristate "TWL4030 USB Transceiver Driver"
+ depends on TWL4030_CORE && REGULATOR_TWL4030 && USB_MUSB_OMAP2PLUS
+ depends on USB_SUPPORT
+ depends on USB_GADGET || !USB_GADGET # if USB_GADGET=m, this can't 'y'
+ select GENERIC_PHY
+ select USB_PHY
+ help
+ Enable this to support the USB OTG transceiver on TWL4030
+ family chips (including the TWL5030 and TPS659x0 devices).
+ This transceiver supports high and full speed devices plus,
+ in host mode, low speed.
diff --git a/drivers/phy/ti/Makefile b/drivers/phy/ti/Makefile
new file mode 100644
index 000000000000..0cc3a1a557a3
--- /dev/null
+++ b/drivers/phy/ti/Makefile
@@ -0,0 +1,7 @@
+obj-$(CONFIG_PHY_DA8XX_USB) += phy-da8xx-usb.o
+obj-$(CONFIG_PHY_DM816X_USB) += phy-dm816x-usb.o
+obj-$(CONFIG_OMAP_CONTROL_PHY) += phy-omap-control.o
+obj-$(CONFIG_OMAP_USB2) += phy-omap-usb2.o
+obj-$(CONFIG_TI_PIPE3) += phy-ti-pipe3.o
+obj-$(CONFIG_PHY_TUSB1210) += phy-tusb1210.o
+obj-$(CONFIG_TWL4030_USB) += phy-twl4030-usb.o
diff --git a/drivers/phy/phy-da8xx-usb.c b/drivers/phy/ti/phy-da8xx-usb.c
index 1b82bff6330f..1b82bff6330f 100644
--- a/drivers/phy/phy-da8xx-usb.c
+++ b/drivers/phy/ti/phy-da8xx-usb.c
diff --git a/drivers/phy/phy-dm816x-usb.c b/drivers/phy/ti/phy-dm816x-usb.c
index cbcce7cf0028..cbcce7cf0028 100644
--- a/drivers/phy/phy-dm816x-usb.c
+++ b/drivers/phy/ti/phy-dm816x-usb.c
diff --git a/drivers/phy/phy-omap-control.c b/drivers/phy/ti/phy-omap-control.c
index e9c41b3fa0ee..e9c41b3fa0ee 100644
--- a/drivers/phy/phy-omap-control.c
+++ b/drivers/phy/ti/phy-omap-control.c
diff --git a/drivers/phy/phy-omap-usb2.c b/drivers/phy/ti/phy-omap-usb2.c
index fe909fd8144f..fe909fd8144f 100644
--- a/drivers/phy/phy-omap-usb2.c
+++ b/drivers/phy/ti/phy-omap-usb2.c
diff --git a/drivers/phy/phy-ti-pipe3.c b/drivers/phy/ti/phy-ti-pipe3.c
index 9c84d32c6f60..9c84d32c6f60 100644
--- a/drivers/phy/phy-ti-pipe3.c
+++ b/drivers/phy/ti/phy-ti-pipe3.c
diff --git a/drivers/phy/phy-tusb1210.c b/drivers/phy/ti/phy-tusb1210.c
index 4f6d5e71507d..b8ec39ac4dfc 100644
--- a/drivers/phy/phy-tusb1210.c
+++ b/drivers/phy/ti/phy-tusb1210.c
@@ -11,9 +11,9 @@
*/
#include <linux/module.h>
#include <linux/ulpi/driver.h>
+#include <linux/ulpi/regs.h>
#include <linux/gpio/consumer.h>
-
-#include "ulpi_phy.h"
+#include <linux/phy/ulpi_phy.h>
#define TUSB1210_VENDOR_SPECIFIC2 0x80
#define TUSB1210_VENDOR_SPECIFIC2_IHSTX_SHIFT 0
@@ -53,9 +53,43 @@ static int tusb1210_power_off(struct phy *phy)
return 0;
}
+static int tusb1210_set_mode(struct phy *phy, enum phy_mode mode)
+{
+ struct tusb1210 *tusb = phy_get_drvdata(phy);
+ int ret;
+
+ ret = ulpi_read(tusb->ulpi, ULPI_OTG_CTRL);
+ if (ret < 0)
+ return ret;
+
+ switch (mode) {
+ case PHY_MODE_USB_HOST:
+ ret |= (ULPI_OTG_CTRL_DRVVBUS_EXT
+ | ULPI_OTG_CTRL_ID_PULLUP
+ | ULPI_OTG_CTRL_DP_PULLDOWN
+ | ULPI_OTG_CTRL_DM_PULLDOWN);
+ ulpi_write(tusb->ulpi, ULPI_OTG_CTRL, ret);
+ ret |= ULPI_OTG_CTRL_DRVVBUS;
+ break;
+ case PHY_MODE_USB_DEVICE:
+ ret &= ~(ULPI_OTG_CTRL_DRVVBUS
+ | ULPI_OTG_CTRL_DP_PULLDOWN
+ | ULPI_OTG_CTRL_DM_PULLDOWN);
+ ulpi_write(tusb->ulpi, ULPI_OTG_CTRL, ret);
+ ret &= ~ULPI_OTG_CTRL_DRVVBUS_EXT;
+ break;
+ default:
+ /* nothing */
+ return 0;
+ }
+
+ return ulpi_write(tusb->ulpi, ULPI_OTG_CTRL, ret);
+}
+
static const struct phy_ops phy_ops = {
.power_on = tusb1210_power_on,
.power_off = tusb1210_power_off,
+ .set_mode = tusb1210_set_mode,
.owner = THIS_MODULE,
};
@@ -125,7 +159,8 @@ static void tusb1210_remove(struct ulpi *ulpi)
#define TI_VENDOR_ID 0x0451
static const struct ulpi_device_id tusb1210_ulpi_id[] = {
- { TI_VENDOR_ID, 0x1507, },
+ { TI_VENDOR_ID, 0x1507, }, /* TUSB1210 */
+ { TI_VENDOR_ID, 0x1508, }, /* TUSB1211 */
{ },
};
MODULE_DEVICE_TABLE(ulpi, tusb1210_ulpi_id);
diff --git a/drivers/phy/phy-twl4030-usb.c b/drivers/phy/ti/phy-twl4030-usb.c
index 2990b3965460..2990b3965460 100644
--- a/drivers/phy/phy-twl4030-usb.c
+++ b/drivers/phy/ti/phy-twl4030-usb.c
diff --git a/drivers/phy/ulpi_phy.h b/drivers/phy/ulpi_phy.h
deleted file mode 100644
index f2ebe490a4bc..000000000000
--- a/drivers/phy/ulpi_phy.h
+++ /dev/null
@@ -1,31 +0,0 @@
-#include <linux/phy/phy.h>
-
-/**
- * Helper that registers PHY for a ULPI device and adds a lookup for binding it
- * and it's controller, which is always the parent.
- */
-static inline struct phy
-*ulpi_phy_create(struct ulpi *ulpi, const struct phy_ops *ops)
-{
- struct phy *phy;
- int ret;
-
- phy = phy_create(&ulpi->dev, NULL, ops);
- if (IS_ERR(phy))
- return phy;
-
- ret = phy_create_lookup(phy, "usb2-phy", dev_name(ulpi->dev.parent));
- if (ret) {
- phy_destroy(phy);
- return ERR_PTR(ret);
- }
-
- return phy;
-}
-
-/* Remove a PHY that was created with ulpi_phy_create() and it's lookup. */
-static inline void ulpi_phy_destroy(struct ulpi *ulpi, struct phy *phy)
-{
- phy_remove_lookup(phy, "usb2-phy", dev_name(ulpi->dev.parent));
- phy_destroy(phy);
-}
diff --git a/drivers/pinctrl/core.c b/drivers/pinctrl/core.c
index 1653cbda6a82..bd459a93b0e7 100644
--- a/drivers/pinctrl/core.c
+++ b/drivers/pinctrl/core.c
@@ -680,30 +680,16 @@ EXPORT_SYMBOL_GPL(pinctrl_generic_remove_group);
* pinctrl_generic_free_groups() - removes all pin groups
* @pctldev: pin controller device
*
- * Note that the caller must take care of locking.
+ * Note that the caller must take care of locking. The pinctrl groups
+ * are allocated with devm_kzalloc() so no need to free them here.
*/
static void pinctrl_generic_free_groups(struct pinctrl_dev *pctldev)
{
struct radix_tree_iter iter;
- struct group_desc *group;
- unsigned long *indices;
void **slot;
- int i = 0;
-
- indices = devm_kzalloc(pctldev->dev, sizeof(*indices) *
- pctldev->num_groups, GFP_KERNEL);
- if (!indices)
- return;
radix_tree_for_each_slot(slot, &pctldev->pin_group_tree, &iter, 0)
- indices[i++] = iter.index;
-
- for (i = 0; i < pctldev->num_groups; i++) {
- group = radix_tree_lookup(&pctldev->pin_group_tree,
- indices[i]);
- radix_tree_delete(&pctldev->pin_group_tree, indices[i]);
- devm_kfree(pctldev->dev, group);
- }
+ radix_tree_delete(&pctldev->pin_group_tree, iter.index);
pctldev->num_groups = 0;
}
diff --git a/drivers/pinctrl/freescale/pinctrl-mxs.c b/drivers/pinctrl/freescale/pinctrl-mxs.c
index 41b5b07d5a2b..6852010a6d70 100644
--- a/drivers/pinctrl/freescale/pinctrl-mxs.c
+++ b/drivers/pinctrl/freescale/pinctrl-mxs.c
@@ -194,6 +194,16 @@ static int mxs_pinctrl_get_func_groups(struct pinctrl_dev *pctldev,
return 0;
}
+static void mxs_pinctrl_rmwl(u32 value, u32 mask, u8 shift, void __iomem *reg)
+{
+ u32 tmp;
+
+ tmp = readl(reg);
+ tmp &= ~(mask << shift);
+ tmp |= value << shift;
+ writel(tmp, reg);
+}
+
static int mxs_pinctrl_set_mux(struct pinctrl_dev *pctldev, unsigned selector,
unsigned group)
{
@@ -211,8 +221,7 @@ static int mxs_pinctrl_set_mux(struct pinctrl_dev *pctldev, unsigned selector,
reg += bank * 0x20 + pin / 16 * 0x10;
shift = pin % 16 * 2;
- writel(0x3 << shift, reg + CLR);
- writel(g->muxsel[i] << shift, reg + SET);
+ mxs_pinctrl_rmwl(g->muxsel[i], 0x3, shift, reg);
}
return 0;
@@ -279,8 +288,7 @@ static int mxs_pinconf_group_set(struct pinctrl_dev *pctldev,
/* mA */
if (config & MA_PRESENT) {
shift = pin % 8 * 4;
- writel(0x3 << shift, reg + CLR);
- writel(ma << shift, reg + SET);
+ mxs_pinctrl_rmwl(ma, 0x3, shift, reg);
}
/* vol */
diff --git a/drivers/pinctrl/intel/pinctrl-cherryview.c b/drivers/pinctrl/intel/pinctrl-cherryview.c
index 2debba62fac9..20f1b4493994 100644
--- a/drivers/pinctrl/intel/pinctrl-cherryview.c
+++ b/drivers/pinctrl/intel/pinctrl-cherryview.c
@@ -1539,15 +1539,29 @@ static void chv_gpio_irq_handler(struct irq_desc *desc)
* is not listed below.
*/
static const struct dmi_system_id chv_no_valid_mask[] = {
+ /* See https://bugzilla.kernel.org/show_bug.cgi?id=194945 */
{
- /* See https://bugzilla.kernel.org/show_bug.cgi?id=194945 */
- .ident = "Acer Chromebook (CYAN)",
+ .ident = "Intel_Strago based Chromebooks (All models)",
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "GOOGLE"),
- DMI_MATCH(DMI_PRODUCT_NAME, "Edgar"),
- DMI_MATCH(DMI_BIOS_DATE, "05/21/2016"),
+ DMI_MATCH(DMI_PRODUCT_FAMILY, "Intel_Strago"),
},
- }
+ },
+ {
+ .ident = "Acer Chromebook R11 (Cyan)",
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "GOOGLE"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "Cyan"),
+ },
+ },
+ {
+ .ident = "Samsung Chromebook 3 (Celes)",
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "GOOGLE"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "Celes"),
+ },
+ },
+ {}
};
static int chv_gpio_probe(struct chv_pinctrl *pctrl, int irq)
diff --git a/drivers/pinctrl/pinconf-generic.c b/drivers/pinctrl/pinconf-generic.c
index 0d6b7f4b82af..720a19fd38d2 100644
--- a/drivers/pinctrl/pinconf-generic.c
+++ b/drivers/pinctrl/pinconf-generic.c
@@ -35,7 +35,6 @@ static const struct pin_config_item conf_items[] = {
PCONFDUMP(PIN_CONFIG_BIAS_PULL_PIN_DEFAULT,
"input bias pull to pin specific state", NULL, false),
PCONFDUMP(PIN_CONFIG_BIAS_PULL_UP, "input bias pull up", NULL, false),
- PCONFDUMP(PIN_CONFIG_BIDIRECTIONAL, "bi-directional pin operations", NULL, false),
PCONFDUMP(PIN_CONFIG_DRIVE_OPEN_DRAIN, "output drive open drain", NULL, false),
PCONFDUMP(PIN_CONFIG_DRIVE_OPEN_SOURCE, "output drive open source", NULL, false),
PCONFDUMP(PIN_CONFIG_DRIVE_PUSH_PULL, "output drive push pull", NULL, false),
@@ -161,7 +160,6 @@ static const struct pinconf_generic_params dt_params[] = {
{ "bias-pull-up", PIN_CONFIG_BIAS_PULL_UP, 1 },
{ "bias-pull-pin-default", PIN_CONFIG_BIAS_PULL_PIN_DEFAULT, 1 },
{ "bias-pull-down", PIN_CONFIG_BIAS_PULL_DOWN, 1 },
- { "bi-directional", PIN_CONFIG_BIDIRECTIONAL, 1 },
{ "drive-open-drain", PIN_CONFIG_DRIVE_OPEN_DRAIN, 0 },
{ "drive-open-source", PIN_CONFIG_DRIVE_OPEN_SOURCE, 0 },
{ "drive-push-pull", PIN_CONFIG_DRIVE_PUSH_PULL, 0 },
@@ -174,7 +172,6 @@ static const struct pinconf_generic_params dt_params[] = {
{ "input-schmitt-enable", PIN_CONFIG_INPUT_SCHMITT_ENABLE, 1 },
{ "low-power-disable", PIN_CONFIG_LOW_POWER_MODE, 0 },
{ "low-power-enable", PIN_CONFIG_LOW_POWER_MODE, 1 },
- { "output-enable", PIN_CONFIG_OUTPUT, 1, },
{ "output-high", PIN_CONFIG_OUTPUT, 1, },
{ "output-low", PIN_CONFIG_OUTPUT, 0, },
{ "power-source", PIN_CONFIG_POWER_SOURCE, 0 },
diff --git a/drivers/pinctrl/pinctrl-amd.c b/drivers/pinctrl/pinctrl-amd.c
index 1482d132fbb8..e432ec887479 100644
--- a/drivers/pinctrl/pinctrl-amd.c
+++ b/drivers/pinctrl/pinctrl-amd.c
@@ -495,64 +495,54 @@ static struct irq_chip amd_gpio_irqchip = {
.flags = IRQCHIP_SKIP_SET_WAKE,
};
-static void amd_gpio_irq_handler(struct irq_desc *desc)
+#define PIN_IRQ_PENDING (BIT(INTERRUPT_STS_OFF) | BIT(WAKE_STS_OFF))
+
+static irqreturn_t amd_gpio_irq_handler(int irq, void *dev_id)
{
- u32 i;
- u32 off;
- u32 reg;
- u32 pin_reg;
- u64 reg64;
- int handled = 0;
- unsigned int irq;
+ struct amd_gpio *gpio_dev = dev_id;
+ struct gpio_chip *gc = &gpio_dev->gc;
+ irqreturn_t ret = IRQ_NONE;
+ unsigned int i, irqnr;
unsigned long flags;
- struct irq_chip *chip = irq_desc_get_chip(desc);
- struct gpio_chip *gc = irq_desc_get_handler_data(desc);
- struct amd_gpio *gpio_dev = gpiochip_get_data(gc);
+ u32 *regs, regval;
+ u64 status, mask;
- chained_irq_enter(chip, desc);
- /*enable GPIO interrupt again*/
+ /* Read the wake status */
raw_spin_lock_irqsave(&gpio_dev->lock, flags);
- reg = readl(gpio_dev->base + WAKE_INT_STATUS_REG1);
- reg64 = reg;
- reg64 = reg64 << 32;
-
- reg = readl(gpio_dev->base + WAKE_INT_STATUS_REG0);
- reg64 |= reg;
+ status = readl(gpio_dev->base + WAKE_INT_STATUS_REG1);
+ status <<= 32;
+ status |= readl(gpio_dev->base + WAKE_INT_STATUS_REG0);
raw_spin_unlock_irqrestore(&gpio_dev->lock, flags);
- /*
- * first 46 bits indicates interrupt status.
- * one bit represents four interrupt sources.
- */
- for (off = 0; off < 46 ; off++) {
- if (reg64 & BIT(off)) {
- for (i = 0; i < 4; i++) {
- pin_reg = readl(gpio_dev->base +
- (off * 4 + i) * 4);
- if ((pin_reg & BIT(INTERRUPT_STS_OFF)) ||
- (pin_reg & BIT(WAKE_STS_OFF))) {
- irq = irq_find_mapping(gc->irqdomain,
- off * 4 + i);
- generic_handle_irq(irq);
- writel(pin_reg,
- gpio_dev->base
- + (off * 4 + i) * 4);
- handled++;
- }
- }
+ /* Bit 0-45 contain the relevant status bits */
+ status &= (1ULL << 46) - 1;
+ regs = gpio_dev->base;
+ for (mask = 1, irqnr = 0; status; mask <<= 1, regs += 4, irqnr += 4) {
+ if (!(status & mask))
+ continue;
+ status &= ~mask;
+
+ /* Each status bit covers four pins */
+ for (i = 0; i < 4; i++) {
+ regval = readl(regs + i);
+ if (!(regval & PIN_IRQ_PENDING))
+ continue;
+ irq = irq_find_mapping(gc->irqdomain, irqnr + i);
+ generic_handle_irq(irq);
+ /* Clear interrupt */
+ writel(regval, regs + i);
+ ret = IRQ_HANDLED;
}
}
- if (handled == 0)
- handle_bad_irq(desc);
-
+ /* Signal EOI to the GPIO unit */
raw_spin_lock_irqsave(&gpio_dev->lock, flags);
- reg = readl(gpio_dev->base + WAKE_INT_MASTER_REG);
- reg |= EOI_MASK;
- writel(reg, gpio_dev->base + WAKE_INT_MASTER_REG);
+ regval = readl(gpio_dev->base + WAKE_INT_MASTER_REG);
+ regval |= EOI_MASK;
+ writel(regval, gpio_dev->base + WAKE_INT_MASTER_REG);
raw_spin_unlock_irqrestore(&gpio_dev->lock, flags);
- chained_irq_exit(chip, desc);
+ return ret;
}
static int amd_get_groups_count(struct pinctrl_dev *pctldev)
@@ -821,10 +811,11 @@ static int amd_gpio_probe(struct platform_device *pdev)
goto out2;
}
- gpiochip_set_chained_irqchip(&gpio_dev->gc,
- &amd_gpio_irqchip,
- irq_base,
- amd_gpio_irq_handler);
+ ret = devm_request_irq(&pdev->dev, irq_base, amd_gpio_irq_handler, 0,
+ KBUILD_MODNAME, gpio_dev);
+ if (ret)
+ goto out2;
+
platform_set_drvdata(pdev, gpio_dev);
dev_dbg(&pdev->dev, "amd gpio driver loaded\n");
diff --git a/drivers/pinctrl/pinctrl-rockchip.c b/drivers/pinctrl/pinctrl-rockchip.c
index f141aa0430b1..9dd981ddbb17 100644
--- a/drivers/pinctrl/pinctrl-rockchip.c
+++ b/drivers/pinctrl/pinctrl-rockchip.c
@@ -143,9 +143,6 @@ struct rockchip_drv {
* @gpio_chip: gpiolib chip
* @grange: gpio range
* @slock: spinlock for the gpio bank
- * @irq_lock: bus lock for irq chip
- * @new_irqs: newly configured irqs which must be muxed as GPIOs in
- * irq_bus_sync_unlock()
*/
struct rockchip_pin_bank {
void __iomem *reg_base;
@@ -168,8 +165,6 @@ struct rockchip_pin_bank {
struct pinctrl_gpio_range grange;
raw_spinlock_t slock;
u32 toggle_edge_mode;
- struct mutex irq_lock;
- u32 new_irqs;
};
#define PIN_BANK(id, pins, label) \
@@ -2134,12 +2129,11 @@ static int rockchip_irq_set_type(struct irq_data *d, unsigned int type)
int ret;
/* make sure the pin is configured as gpio input */
- ret = rockchip_verify_mux(bank, d->hwirq, RK_FUNC_GPIO);
+ ret = rockchip_set_mux(bank, d->hwirq, RK_FUNC_GPIO);
if (ret < 0)
return ret;
- bank->new_irqs |= mask;
-
+ clk_enable(bank->clk);
raw_spin_lock_irqsave(&bank->slock, flags);
data = readl_relaxed(bank->reg_base + GPIO_SWPORT_DDR);
@@ -2197,6 +2191,7 @@ static int rockchip_irq_set_type(struct irq_data *d, unsigned int type)
default:
irq_gc_unlock(gc);
raw_spin_unlock_irqrestore(&bank->slock, flags);
+ clk_disable(bank->clk);
return -EINVAL;
}
@@ -2205,6 +2200,7 @@ static int rockchip_irq_set_type(struct irq_data *d, unsigned int type)
irq_gc_unlock(gc);
raw_spin_unlock_irqrestore(&bank->slock, flags);
+ clk_disable(bank->clk);
return 0;
}
@@ -2248,34 +2244,6 @@ static void rockchip_irq_disable(struct irq_data *d)
clk_disable(bank->clk);
}
-static void rockchip_irq_bus_lock(struct irq_data *d)
-{
- struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d);
- struct rockchip_pin_bank *bank = gc->private;
-
- clk_enable(bank->clk);
- mutex_lock(&bank->irq_lock);
-}
-
-static void rockchip_irq_bus_sync_unlock(struct irq_data *d)
-{
- struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d);
- struct rockchip_pin_bank *bank = gc->private;
-
- while (bank->new_irqs) {
- unsigned int irq = __ffs(bank->new_irqs);
- int ret;
-
- ret = rockchip_set_mux(bank, irq, RK_FUNC_GPIO);
- WARN_ON(ret < 0);
-
- bank->new_irqs &= ~BIT(irq);
- }
-
- mutex_unlock(&bank->irq_lock);
- clk_disable(bank->clk);
-}
-
static int rockchip_interrupts_register(struct platform_device *pdev,
struct rockchip_pinctrl *info)
{
@@ -2342,9 +2310,6 @@ static int rockchip_interrupts_register(struct platform_device *pdev,
gc->chip_types[0].chip.irq_suspend = rockchip_irq_suspend;
gc->chip_types[0].chip.irq_resume = rockchip_irq_resume;
gc->chip_types[0].chip.irq_set_type = rockchip_irq_set_type;
- gc->chip_types[0].chip.irq_bus_lock = rockchip_irq_bus_lock;
- gc->chip_types[0].chip.irq_bus_sync_unlock =
- rockchip_irq_bus_sync_unlock;
gc->wake_enabled = IRQ_MSK(bank->nr_pins);
irq_set_chained_handler_and_data(bank->irq,
@@ -2518,7 +2483,6 @@ static struct rockchip_pin_ctrl *rockchip_pinctrl_get_soc_data(
int bank_pins = 0;
raw_spin_lock_init(&bank->slock);
- mutex_init(&bank->irq_lock);
bank->drvdata = d;
bank->pin_base = ctrl->nr_pins;
ctrl->nr_pins += bank->nr_pins;
diff --git a/drivers/pinctrl/pinmux.c b/drivers/pinctrl/pinmux.c
index 9fd6d9087dc5..16b3ae5e4f44 100644
--- a/drivers/pinctrl/pinmux.c
+++ b/drivers/pinctrl/pinmux.c
@@ -826,30 +826,17 @@ EXPORT_SYMBOL_GPL(pinmux_generic_remove_function);
* pinmux_generic_free_functions() - removes all functions
* @pctldev: pin controller device
*
- * Note that the caller must take care of locking.
+ * Note that the caller must take care of locking. The pinctrl
+ * functions are allocated with devm_kzalloc() so no need to free
+ * them here.
*/
void pinmux_generic_free_functions(struct pinctrl_dev *pctldev)
{
struct radix_tree_iter iter;
- struct function_desc *function;
- unsigned long *indices;
void **slot;
- int i = 0;
-
- indices = devm_kzalloc(pctldev->dev, sizeof(*indices) *
- pctldev->num_functions, GFP_KERNEL);
- if (!indices)
- return;
radix_tree_for_each_slot(slot, &pctldev->pin_function_tree, &iter, 0)
- indices[i++] = iter.index;
-
- for (i = 0; i < pctldev->num_functions; i++) {
- function = radix_tree_lookup(&pctldev->pin_function_tree,
- indices[i]);
- radix_tree_delete(&pctldev->pin_function_tree, indices[i]);
- devm_kfree(pctldev->dev, function);
- }
+ radix_tree_delete(&pctldev->pin_function_tree, iter.index);
pctldev->num_functions = 0;
}
diff --git a/drivers/pinctrl/stm32/pinctrl-stm32.c b/drivers/pinctrl/stm32/pinctrl-stm32.c
index d3c5f5dfbbd7..222b6685b09f 100644
--- a/drivers/pinctrl/stm32/pinctrl-stm32.c
+++ b/drivers/pinctrl/stm32/pinctrl-stm32.c
@@ -798,7 +798,7 @@ static int stm32_pconf_parse_conf(struct pinctrl_dev *pctldev,
break;
case PIN_CONFIG_OUTPUT:
__stm32_gpio_set(bank, offset, arg);
- ret = stm32_pmx_gpio_set_direction(pctldev, NULL, pin, false);
+ ret = stm32_pmx_gpio_set_direction(pctldev, range, pin, false);
break;
default:
ret = -EINVAL;
diff --git a/drivers/pinctrl/sunxi/pinctrl-sun8i-a83t.c b/drivers/pinctrl/sunxi/pinctrl-sun8i-a83t.c
index 9aec1d2232dd..6624499eae72 100644
--- a/drivers/pinctrl/sunxi/pinctrl-sun8i-a83t.c
+++ b/drivers/pinctrl/sunxi/pinctrl-sun8i-a83t.c
@@ -394,7 +394,7 @@ static const struct sunxi_desc_pin sun8i_a83t_pins[] = {
SUNXI_PIN(SUNXI_PINCTRL_PIN(E, 18),
SUNXI_FUNCTION(0x0, "gpio_in"),
SUNXI_FUNCTION(0x1, "gpio_out"),
- SUNXI_FUNCTION(0x3, "owa")), /* DOUT */
+ SUNXI_FUNCTION(0x3, "spdif")), /* DOUT */
SUNXI_PIN(SUNXI_PINCTRL_PIN(E, 19),
SUNXI_FUNCTION(0x0, "gpio_in"),
SUNXI_FUNCTION(0x1, "gpio_out")),
diff --git a/drivers/platform/goldfish/goldfish_pipe.c b/drivers/platform/goldfish/goldfish_pipe.c
index 2de1e603bd2b..5f3672153b12 100644
--- a/drivers/platform/goldfish/goldfish_pipe.c
+++ b/drivers/platform/goldfish/goldfish_pipe.c
@@ -704,7 +704,7 @@ static int get_free_pipe_id_locked(struct goldfish_pipe_dev *dev)
/* Reallocate the array */
u32 new_capacity = 2 * dev->pipes_capacity;
struct goldfish_pipe **pipes =
- kcalloc(new_capacity, sizeof(*pipes), GFP_KERNEL);
+ kcalloc(new_capacity, sizeof(*pipes), GFP_ATOMIC);
if (!pipes)
return -ENOMEM;
memcpy(pipes, dev->pipes, sizeof(*pipes) * dev->pipes_capacity);
diff --git a/drivers/platform/x86/intel_telemetry_debugfs.c b/drivers/platform/x86/intel_telemetry_debugfs.c
index ef29f18b1951..4cc2f4ea0a25 100644
--- a/drivers/platform/x86/intel_telemetry_debugfs.c
+++ b/drivers/platform/x86/intel_telemetry_debugfs.c
@@ -97,11 +97,9 @@
} \
}
-#ifdef CONFIG_PM_SLEEP
static u8 suspend_prep_ok;
static u32 suspend_shlw_ctr_temp, suspend_deep_ctr_temp;
static u64 suspend_shlw_res_temp, suspend_deep_res_temp;
-#endif
struct telemetry_susp_stats {
u32 shlw_swake_ctr;
@@ -807,7 +805,6 @@ static const struct file_operations telem_ioss_trc_verb_ops = {
.release = single_release,
};
-#ifdef CONFIG_PM_SLEEP
static int pm_suspend_prep_cb(void)
{
struct telemetry_evtlog evtlog[TELEM_MAX_OS_ALLOCATED_EVENTS];
@@ -937,7 +934,6 @@ static int pm_notification(struct notifier_block *this,
static struct notifier_block pm_notifier = {
.notifier_call = pm_notification,
};
-#endif /* CONFIG_PM_SLEEP */
static int __init telemetry_debugfs_init(void)
{
@@ -960,14 +956,13 @@ static int __init telemetry_debugfs_init(void)
if (err < 0)
return -EINVAL;
-
-#ifdef CONFIG_PM_SLEEP
register_pm_notifier(&pm_notifier);
-#endif /* CONFIG_PM_SLEEP */
debugfs_conf->telemetry_dbg_dir = debugfs_create_dir("telemetry", NULL);
- if (!debugfs_conf->telemetry_dbg_dir)
- return -ENOMEM;
+ if (!debugfs_conf->telemetry_dbg_dir) {
+ err = -ENOMEM;
+ goto out_pm;
+ }
f = debugfs_create_file("pss_info", S_IFREG | S_IRUGO,
debugfs_conf->telemetry_dbg_dir, NULL,
@@ -1014,6 +1009,8 @@ static int __init telemetry_debugfs_init(void)
out:
debugfs_remove_recursive(debugfs_conf->telemetry_dbg_dir);
debugfs_conf->telemetry_dbg_dir = NULL;
+out_pm:
+ unregister_pm_notifier(&pm_notifier);
return err;
}
@@ -1022,6 +1019,7 @@ static void __exit telemetry_debugfs_exit(void)
{
debugfs_remove_recursive(debugfs_conf->telemetry_dbg_dir);
debugfs_conf->telemetry_dbg_dir = NULL;
+ unregister_pm_notifier(&pm_notifier);
}
late_initcall(telemetry_debugfs_init);
diff --git a/drivers/powercap/powercap_sys.c b/drivers/powercap/powercap_sys.c
index 14bde0db8c24..5b10b50f8686 100644
--- a/drivers/powercap/powercap_sys.c
+++ b/drivers/powercap/powercap_sys.c
@@ -538,6 +538,7 @@ struct powercap_zone *powercap_register_zone(
power_zone->id = result;
idr_init(&power_zone->idr);
+ result = -ENOMEM;
power_zone->name = kstrdup(name, GFP_KERNEL);
if (!power_zone->name)
goto err_name_alloc;
diff --git a/drivers/ras/cec.c b/drivers/ras/cec.c
index 6aab46d91d33..d0e5d6ee882c 100644
--- a/drivers/ras/cec.c
+++ b/drivers/ras/cec.c
@@ -481,7 +481,7 @@ static int __init create_debugfs_nodes(void)
count = debugfs_create_file("count_threshold", S_IRUSR | S_IWUSR, d,
&count_threshold, &count_threshold_ops);
- if (!decay) {
+ if (!count) {
pr_warn("Error creating count_threshold debugfs node!\n");
goto err;
}
diff --git a/drivers/ras/ras.c b/drivers/ras/ras.c
index 94f8038864b4..ed4c343d08c4 100644
--- a/drivers/ras/ras.c
+++ b/drivers/ras/ras.c
@@ -29,7 +29,7 @@ EXPORT_TRACEPOINT_SYMBOL_GPL(extlog_mem_event);
EXPORT_TRACEPOINT_SYMBOL_GPL(mc_event);
-int __init parse_ras_param(char *str)
+static int __init parse_ras_param(char *str)
{
#ifdef CONFIG_RAS_CEC
parse_cec_param(str);
diff --git a/drivers/reset/hisilicon/hi6220_reset.c b/drivers/reset/hisilicon/hi6220_reset.c
index 35ce53edabf9..d5e5229308f2 100644
--- a/drivers/reset/hisilicon/hi6220_reset.c
+++ b/drivers/reset/hisilicon/hi6220_reset.c
@@ -155,3 +155,5 @@ static int __init hi6220_reset_init(void)
}
postcore_initcall(hi6220_reset_init);
+
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/rtc/rtc-cmos.c b/drivers/rtc/rtc-cmos.c
index b3de973a6260..9dca53df3584 100644
--- a/drivers/rtc/rtc-cmos.c
+++ b/drivers/rtc/rtc-cmos.c
@@ -1088,7 +1088,7 @@ static u32 rtc_handler(void *context)
}
spin_unlock_irqrestore(&rtc_lock, flags);
- pm_wakeup_event(dev, 0);
+ pm_wakeup_hard_event(dev);
acpi_clear_event(ACPI_EVENT_RTC);
acpi_disable_event(ACPI_EVENT_RTC, 0);
return ACPI_INTERRUPT_HANDLED;
diff --git a/drivers/rtc/rtc-imxdi.c b/drivers/rtc/rtc-imxdi.c
index 6b54f6c24c5f..80931114c899 100644
--- a/drivers/rtc/rtc-imxdi.c
+++ b/drivers/rtc/rtc-imxdi.c
@@ -709,7 +709,7 @@ static irqreturn_t dryice_irq(int irq, void *dev_id)
/*If the write wait queue is empty then there is no pending
operations. It means the interrupt is for DryIce -Security.
IRQ must be returned as none.*/
- if (list_empty_careful(&imxdi->write_wait.task_list))
+ if (list_empty_careful(&imxdi->write_wait.head))
return rc;
/* DSR_WCF clears itself on DSR read */
diff --git a/drivers/s390/block/Kconfig b/drivers/s390/block/Kconfig
index 0acb8c2f9475..31f014b57bfc 100644
--- a/drivers/s390/block/Kconfig
+++ b/drivers/s390/block/Kconfig
@@ -82,10 +82,3 @@ config SCM_BLOCK
To compile this driver as a module, choose M here: the
module will be called scm_block.
-
-config SCM_BLOCK_CLUSTER_WRITE
- def_bool y
- prompt "SCM force cluster writes"
- depends on SCM_BLOCK
- help
- Force writes to Storage Class Memory (SCM) to be in done in clusters.
diff --git a/drivers/s390/block/Makefile b/drivers/s390/block/Makefile
index c2f4e673e031..b64e2b32c753 100644
--- a/drivers/s390/block/Makefile
+++ b/drivers/s390/block/Makefile
@@ -19,7 +19,4 @@ obj-$(CONFIG_BLK_DEV_XPRAM) += xpram.o
obj-$(CONFIG_DCSSBLK) += dcssblk.o
scm_block-objs := scm_drv.o scm_blk.o
-ifdef CONFIG_SCM_BLOCK_CLUSTER_WRITE
-scm_block-objs += scm_blk_cluster.o
-endif
obj-$(CONFIG_SCM_BLOCK) += scm_block.o
diff --git a/drivers/s390/block/dasd.c b/drivers/s390/block/dasd.c
index 6fb3fd5efc11..0f1fe4ff7f51 100644
--- a/drivers/s390/block/dasd.c
+++ b/drivers/s390/block/dasd.c
@@ -1965,8 +1965,12 @@ static int __dasd_device_is_unusable(struct dasd_device *device,
{
int mask = ~(DASD_STOPPED_DC_WAIT | DASD_UNRESUMED_PM);
- if (test_bit(DASD_FLAG_OFFLINE, &device->flags)) {
- /* dasd is being set offline. */
+ if (test_bit(DASD_FLAG_OFFLINE, &device->flags) &&
+ !test_bit(DASD_FLAG_SAFE_OFFLINE_RUNNING, &device->flags)) {
+ /*
+ * dasd is being set offline
+ * but it is no safe offline where we have to allow I/O
+ */
return 1;
}
if (device->stopped) {
@@ -2672,7 +2676,7 @@ static void __dasd_process_request_queue(struct dasd_block *block)
*/
if (basedev->state < DASD_STATE_READY) {
while ((req = blk_fetch_request(block->request_queue)))
- __blk_end_request_all(req, -EIO);
+ __blk_end_request_all(req, BLK_STS_IOERR);
return;
}
@@ -2692,7 +2696,7 @@ static void __dasd_process_request_queue(struct dasd_block *block)
"Rejecting write request %p",
req);
blk_start_request(req);
- __blk_end_request_all(req, -EIO);
+ __blk_end_request_all(req, BLK_STS_IOERR);
continue;
}
if (test_bit(DASD_FLAG_ABORTALL, &basedev->flags) &&
@@ -2702,7 +2706,7 @@ static void __dasd_process_request_queue(struct dasd_block *block)
"Rejecting failfast request %p",
req);
blk_start_request(req);
- __blk_end_request_all(req, -ETIMEDOUT);
+ __blk_end_request_all(req, BLK_STS_TIMEOUT);
continue;
}
cqr = basedev->discipline->build_cp(basedev, block, req);
@@ -2734,7 +2738,7 @@ static void __dasd_process_request_queue(struct dasd_block *block)
"on request %p",
PTR_ERR(cqr), req);
blk_start_request(req);
- __blk_end_request_all(req, -EIO);
+ __blk_end_request_all(req, BLK_STS_IOERR);
continue;
}
/*
@@ -2755,21 +2759,29 @@ static void __dasd_cleanup_cqr(struct dasd_ccw_req *cqr)
{
struct request *req;
int status;
- int error = 0;
+ blk_status_t error = BLK_STS_OK;
req = (struct request *) cqr->callback_data;
dasd_profile_end(cqr->block, cqr, req);
+
status = cqr->block->base->discipline->free_cp(cqr, req);
if (status < 0)
- error = status;
+ error = errno_to_blk_status(status);
else if (status == 0) {
- if (cqr->intrc == -EPERM)
- error = -EBADE;
- else if (cqr->intrc == -ENOLINK ||
- cqr->intrc == -ETIMEDOUT)
- error = cqr->intrc;
- else
- error = -EIO;
+ switch (cqr->intrc) {
+ case -EPERM:
+ error = BLK_STS_NEXUS;
+ break;
+ case -ENOLINK:
+ error = BLK_STS_TRANSPORT;
+ break;
+ case -ETIMEDOUT:
+ error = BLK_STS_TIMEOUT;
+ break;
+ default:
+ error = BLK_STS_IOERR;
+ break;
+ }
}
__blk_end_request_all(req, error);
}
@@ -3190,7 +3202,7 @@ static void dasd_flush_request_queue(struct dasd_block *block)
spin_lock_irq(&block->request_queue_lock);
while ((req = blk_fetch_request(block->request_queue)))
- __blk_end_request_all(req, -EIO);
+ __blk_end_request_all(req, BLK_STS_IOERR);
spin_unlock_irq(&block->request_queue_lock);
}
@@ -3562,57 +3574,69 @@ int dasd_generic_set_offline(struct ccw_device *cdev)
else
pr_warn("%s: The DASD cannot be set offline while it is in use\n",
dev_name(&cdev->dev));
- clear_bit(DASD_FLAG_OFFLINE, &device->flags);
- goto out_busy;
+ rc = -EBUSY;
+ goto out_err;
}
}
- if (test_bit(DASD_FLAG_SAFE_OFFLINE_RUNNING, &device->flags)) {
- /*
- * safe offline already running
- * could only be called by normal offline so safe_offline flag
- * needs to be removed to run normal offline and kill all I/O
- */
- if (test_and_set_bit(DASD_FLAG_OFFLINE, &device->flags))
- /* Already doing normal offline processing */
- goto out_busy;
- else
- clear_bit(DASD_FLAG_SAFE_OFFLINE, &device->flags);
- } else {
- if (test_bit(DASD_FLAG_OFFLINE, &device->flags))
- /* Already doing offline processing */
- goto out_busy;
+ /*
+ * Test if the offline processing is already running and exit if so.
+ * If a safe offline is being processed this could only be a normal
+ * offline that should be able to overtake the safe offline and
+ * cancel any I/O we do not want to wait for any longer
+ */
+ if (test_bit(DASD_FLAG_OFFLINE, &device->flags)) {
+ if (test_bit(DASD_FLAG_SAFE_OFFLINE_RUNNING, &device->flags)) {
+ clear_bit(DASD_FLAG_SAFE_OFFLINE_RUNNING,
+ &device->flags);
+ } else {
+ rc = -EBUSY;
+ goto out_err;
+ }
}
-
set_bit(DASD_FLAG_OFFLINE, &device->flags);
- spin_unlock_irqrestore(get_ccwdev_lock(cdev), flags);
/*
- * if safe_offline called set safe_offline_running flag and
+ * if safe_offline is called set safe_offline_running flag and
* clear safe_offline so that a call to normal offline
* can overrun safe_offline processing
*/
if (test_and_clear_bit(DASD_FLAG_SAFE_OFFLINE, &device->flags) &&
!test_and_set_bit(DASD_FLAG_SAFE_OFFLINE_RUNNING, &device->flags)) {
+ /* need to unlock here to wait for outstanding I/O */
+ spin_unlock_irqrestore(get_ccwdev_lock(cdev), flags);
/*
* If we want to set the device safe offline all IO operations
* should be finished before continuing the offline process
* so sync bdev first and then wait for our queues to become
* empty
*/
- /* sync blockdev and partitions */
if (device->block) {
rc = fsync_bdev(device->block->bdev);
if (rc != 0)
goto interrupted;
}
- /* schedule device tasklet and wait for completion */
dasd_schedule_device_bh(device);
rc = wait_event_interruptible(shutdown_waitq,
_wait_for_empty_queues(device));
if (rc != 0)
goto interrupted;
+
+ /*
+ * check if a normal offline process overtook the offline
+ * processing in this case simply do nothing beside returning
+ * that we got interrupted
+ * otherwise mark safe offline as not running any longer and
+ * continue with normal offline
+ */
+ spin_lock_irqsave(get_ccwdev_lock(cdev), flags);
+ if (!test_bit(DASD_FLAG_SAFE_OFFLINE_RUNNING, &device->flags)) {
+ rc = -ERESTARTSYS;
+ goto out_err;
+ }
+ clear_bit(DASD_FLAG_SAFE_OFFLINE_RUNNING, &device->flags);
}
+ spin_unlock_irqrestore(get_ccwdev_lock(cdev), flags);
dasd_set_target_state(device, DASD_STATE_NEW);
/* dasd_delete_device destroys the device reference. */
@@ -3624,22 +3648,18 @@ int dasd_generic_set_offline(struct ccw_device *cdev)
*/
if (block)
dasd_free_block(block);
+
return 0;
interrupted:
/* interrupted by signal */
- clear_bit(DASD_FLAG_SAFE_OFFLINE, &device->flags);
+ spin_lock_irqsave(get_ccwdev_lock(cdev), flags);
clear_bit(DASD_FLAG_SAFE_OFFLINE_RUNNING, &device->flags);
clear_bit(DASD_FLAG_OFFLINE, &device->flags);
- dasd_put_device(device);
-
- return rc;
-
-out_busy:
+out_err:
dasd_put_device(device);
spin_unlock_irqrestore(get_ccwdev_lock(cdev), flags);
-
- return -EBUSY;
+ return rc;
}
EXPORT_SYMBOL_GPL(dasd_generic_set_offline);
diff --git a/drivers/s390/block/dasd_devmap.c b/drivers/s390/block/dasd_devmap.c
index 1164b51d09f3..7c7351276d2e 100644
--- a/drivers/s390/block/dasd_devmap.c
+++ b/drivers/s390/block/dasd_devmap.c
@@ -315,45 +315,58 @@ static int __init dasd_parse_range(const char *range)
char *features_str = NULL;
char *from_str = NULL;
char *to_str = NULL;
- size_t len = strlen(range) + 1;
- char tmp[len];
+ int rc = 0;
+ char *tmp;
- strlcpy(tmp, range, len);
+ tmp = kstrdup(range, GFP_KERNEL);
+ if (!tmp)
+ return -ENOMEM;
- if (dasd_evaluate_range_param(tmp, &from_str, &to_str, &features_str))
- goto out_err;
+ if (dasd_evaluate_range_param(tmp, &from_str, &to_str, &features_str)) {
+ rc = -EINVAL;
+ goto out;
+ }
- if (dasd_busid(from_str, &from_id0, &from_id1, &from))
- goto out_err;
+ if (dasd_busid(from_str, &from_id0, &from_id1, &from)) {
+ rc = -EINVAL;
+ goto out;
+ }
to = from;
to_id0 = from_id0;
to_id1 = from_id1;
if (to_str) {
- if (dasd_busid(to_str, &to_id0, &to_id1, &to))
- goto out_err;
+ if (dasd_busid(to_str, &to_id0, &to_id1, &to)) {
+ rc = -EINVAL;
+ goto out;
+ }
if (from_id0 != to_id0 || from_id1 != to_id1 || from > to) {
pr_err("%s is not a valid device range\n", range);
- goto out_err;
+ rc = -EINVAL;
+ goto out;
}
}
features = dasd_feature_list(features_str);
- if (features < 0)
- goto out_err;
+ if (features < 0) {
+ rc = -EINVAL;
+ goto out;
+ }
/* each device in dasd= parameter should be set initially online */
features |= DASD_FEATURE_INITIAL_ONLINE;
while (from <= to) {
sprintf(bus_id, "%01x.%01x.%04x", from_id0, from_id1, from++);
devmap = dasd_add_busid(bus_id, features);
- if (IS_ERR(devmap))
- return PTR_ERR(devmap);
+ if (IS_ERR(devmap)) {
+ rc = PTR_ERR(devmap);
+ goto out;
+ }
}
- return 0;
+out:
+ kfree(tmp);
-out_err:
- return -EINVAL;
+ return rc;
}
/*
@@ -735,13 +748,22 @@ static ssize_t
dasd_ro_show(struct device *dev, struct device_attribute *attr, char *buf)
{
struct dasd_devmap *devmap;
- int ro_flag;
+ struct dasd_device *device;
+ int ro_flag = 0;
devmap = dasd_find_busid(dev_name(dev));
- if (!IS_ERR(devmap))
- ro_flag = (devmap->features & DASD_FEATURE_READONLY) != 0;
- else
- ro_flag = (DASD_FEATURE_DEFAULT & DASD_FEATURE_READONLY) != 0;
+ if (IS_ERR(devmap))
+ goto out;
+
+ ro_flag = !!(devmap->features & DASD_FEATURE_READONLY);
+
+ spin_lock(&dasd_devmap_lock);
+ device = devmap->device;
+ if (device)
+ ro_flag |= test_bit(DASD_FLAG_DEVICE_RO, &device->flags);
+ spin_unlock(&dasd_devmap_lock);
+
+out:
return snprintf(buf, PAGE_SIZE, ro_flag ? "1\n" : "0\n");
}
@@ -764,7 +786,7 @@ dasd_ro_store(struct device *dev, struct device_attribute *attr,
device = dasd_device_from_cdev(cdev);
if (IS_ERR(device))
- return PTR_ERR(device);
+ return count;
spin_lock_irqsave(get_ccwdev_lock(cdev), flags);
val = val || test_bit(DASD_FLAG_DEVICE_RO, &device->flags);
@@ -928,11 +950,14 @@ dasd_safe_offline_store(struct device *dev, struct device_attribute *attr,
{
struct ccw_device *cdev = to_ccwdev(dev);
struct dasd_device *device;
+ unsigned long flags;
int rc;
- device = dasd_device_from_cdev(cdev);
+ spin_lock_irqsave(get_ccwdev_lock(cdev), flags);
+ device = dasd_device_from_cdev_locked(cdev);
if (IS_ERR(device)) {
rc = PTR_ERR(device);
+ spin_unlock_irqrestore(get_ccwdev_lock(cdev), flags);
goto out;
}
@@ -940,12 +965,14 @@ dasd_safe_offline_store(struct device *dev, struct device_attribute *attr,
test_bit(DASD_FLAG_SAFE_OFFLINE_RUNNING, &device->flags)) {
/* Already doing offline processing */
dasd_put_device(device);
+ spin_unlock_irqrestore(get_ccwdev_lock(cdev), flags);
rc = -EBUSY;
goto out;
}
set_bit(DASD_FLAG_SAFE_OFFLINE, &device->flags);
dasd_put_device(device);
+ spin_unlock_irqrestore(get_ccwdev_lock(cdev), flags);
rc = ccw_device_set_offline(cdev);
diff --git a/drivers/s390/block/dcssblk.c b/drivers/s390/block/dcssblk.c
index 36e5280af3e4..06eb1de52d1c 100644
--- a/drivers/s390/block/dcssblk.c
+++ b/drivers/s390/block/dcssblk.c
@@ -845,7 +845,7 @@ dcssblk_make_request(struct request_queue *q, struct bio *bio)
unsigned long source_addr;
unsigned long bytes_done;
- blk_queue_split(q, &bio, q->bio_split);
+ blk_queue_split(q, &bio);
bytes_done = 0;
dev_info = bio->bi_bdev->bd_disk->private_data;
diff --git a/drivers/s390/block/scm_blk.c b/drivers/s390/block/scm_blk.c
index 152de6817875..42018a20f2b7 100644
--- a/drivers/s390/block/scm_blk.c
+++ b/drivers/s390/block/scm_blk.c
@@ -13,6 +13,7 @@
#include <linux/mempool.h>
#include <linux/module.h>
#include <linux/blkdev.h>
+#include <linux/blk-mq.h>
#include <linux/genhd.h>
#include <linux/slab.h>
#include <linux/list.h>
@@ -42,7 +43,6 @@ static void __scm_free_rq(struct scm_request *scmrq)
struct aob_rq_header *aobrq = to_aobrq(scmrq);
free_page((unsigned long) scmrq->aob);
- __scm_free_rq_cluster(scmrq);
kfree(scmrq->request);
kfree(aobrq);
}
@@ -82,9 +82,6 @@ static int __scm_alloc_rq(void)
if (!scmrq->request)
goto free;
- if (__scm_alloc_rq_cluster(scmrq))
- goto free;
-
INIT_LIST_HEAD(&scmrq->list);
spin_lock_irq(&list_lock);
list_add(&scmrq->list, &inactive_requests);
@@ -114,13 +111,13 @@ static struct scm_request *scm_request_fetch(void)
{
struct scm_request *scmrq = NULL;
- spin_lock(&list_lock);
+ spin_lock_irq(&list_lock);
if (list_empty(&inactive_requests))
goto out;
scmrq = list_first_entry(&inactive_requests, struct scm_request, list);
list_del(&scmrq->list);
out:
- spin_unlock(&list_lock);
+ spin_unlock_irq(&list_lock);
return scmrq;
}
@@ -231,140 +228,133 @@ static inline void scm_request_init(struct scm_blk_dev *bdev,
aob->request.data = (u64) aobrq;
scmrq->bdev = bdev;
scmrq->retries = 4;
- scmrq->error = 0;
+ scmrq->error = BLK_STS_OK;
/* We don't use all msbs - place aidaws at the end of the aob page. */
scmrq->next_aidaw = (void *) &aob->msb[nr_requests_per_io];
- scm_request_cluster_init(scmrq);
}
-static void scm_ensure_queue_restart(struct scm_blk_dev *bdev)
-{
- if (atomic_read(&bdev->queued_reqs)) {
- /* Queue restart is triggered by the next interrupt. */
- return;
- }
- blk_delay_queue(bdev->rq, SCM_QUEUE_DELAY);
-}
-
-void scm_request_requeue(struct scm_request *scmrq)
+static void scm_request_requeue(struct scm_request *scmrq)
{
struct scm_blk_dev *bdev = scmrq->bdev;
int i;
- scm_release_cluster(scmrq);
for (i = 0; i < nr_requests_per_io && scmrq->request[i]; i++)
- blk_requeue_request(bdev->rq, scmrq->request[i]);
+ blk_mq_requeue_request(scmrq->request[i], false);
atomic_dec(&bdev->queued_reqs);
scm_request_done(scmrq);
- scm_ensure_queue_restart(bdev);
+ blk_mq_kick_requeue_list(bdev->rq);
}
-void scm_request_finish(struct scm_request *scmrq)
+static void scm_request_finish(struct scm_request *scmrq)
{
struct scm_blk_dev *bdev = scmrq->bdev;
int i;
- scm_release_cluster(scmrq);
- for (i = 0; i < nr_requests_per_io && scmrq->request[i]; i++)
- blk_end_request_all(scmrq->request[i], scmrq->error);
+ for (i = 0; i < nr_requests_per_io && scmrq->request[i]; i++) {
+ if (scmrq->error)
+ blk_mq_end_request(scmrq->request[i], scmrq->error);
+ else
+ blk_mq_complete_request(scmrq->request[i]);
+ }
atomic_dec(&bdev->queued_reqs);
scm_request_done(scmrq);
}
-static int scm_request_start(struct scm_request *scmrq)
+static void scm_request_start(struct scm_request *scmrq)
{
struct scm_blk_dev *bdev = scmrq->bdev;
- int ret;
atomic_inc(&bdev->queued_reqs);
- if (!scmrq->aob->request.msb_count) {
- scm_request_requeue(scmrq);
- return -EINVAL;
- }
-
- ret = eadm_start_aob(scmrq->aob);
- if (ret) {
+ if (eadm_start_aob(scmrq->aob)) {
SCM_LOG(5, "no subchannel");
scm_request_requeue(scmrq);
}
- return ret;
}
-static void scm_blk_request(struct request_queue *rq)
+struct scm_queue {
+ struct scm_request *scmrq;
+ spinlock_t lock;
+};
+
+static int scm_blk_request(struct blk_mq_hw_ctx *hctx,
+ const struct blk_mq_queue_data *qd)
{
- struct scm_device *scmdev = rq->queuedata;
+ struct scm_device *scmdev = hctx->queue->queuedata;
struct scm_blk_dev *bdev = dev_get_drvdata(&scmdev->dev);
- struct scm_request *scmrq = NULL;
- struct request *req;
+ struct scm_queue *sq = hctx->driver_data;
+ struct request *req = qd->rq;
+ struct scm_request *scmrq;
- while ((req = blk_peek_request(rq))) {
- if (!scm_permit_request(bdev, req))
- goto out;
+ spin_lock(&sq->lock);
+ if (!scm_permit_request(bdev, req)) {
+ spin_unlock(&sq->lock);
+ return BLK_MQ_RQ_QUEUE_BUSY;
+ }
+ scmrq = sq->scmrq;
+ if (!scmrq) {
+ scmrq = scm_request_fetch();
if (!scmrq) {
- scmrq = scm_request_fetch();
- if (!scmrq) {
- SCM_LOG(5, "no request");
- goto out;
- }
- scm_request_init(bdev, scmrq);
+ SCM_LOG(5, "no request");
+ spin_unlock(&sq->lock);
+ return BLK_MQ_RQ_QUEUE_BUSY;
}
- scm_request_set(scmrq, req);
+ scm_request_init(bdev, scmrq);
+ sq->scmrq = scmrq;
+ }
+ scm_request_set(scmrq, req);
- if (!scm_reserve_cluster(scmrq)) {
- SCM_LOG(5, "cluster busy");
- scm_request_set(scmrq, NULL);
- if (scmrq->aob->request.msb_count)
- goto out;
+ if (scm_request_prepare(scmrq)) {
+ SCM_LOG(5, "aidaw alloc failed");
+ scm_request_set(scmrq, NULL);
- scm_request_done(scmrq);
- return;
- }
+ if (scmrq->aob->request.msb_count)
+ scm_request_start(scmrq);
- if (scm_need_cluster_request(scmrq)) {
- if (scmrq->aob->request.msb_count) {
- /* Start cluster requests separately. */
- scm_request_set(scmrq, NULL);
- if (scm_request_start(scmrq))
- return;
- } else {
- atomic_inc(&bdev->queued_reqs);
- blk_start_request(req);
- scm_initiate_cluster_request(scmrq);
- }
- scmrq = NULL;
- continue;
- }
+ sq->scmrq = NULL;
+ spin_unlock(&sq->lock);
+ return BLK_MQ_RQ_QUEUE_BUSY;
+ }
+ blk_mq_start_request(req);
- if (scm_request_prepare(scmrq)) {
- SCM_LOG(5, "aidaw alloc failed");
- scm_request_set(scmrq, NULL);
- goto out;
- }
- blk_start_request(req);
+ if (qd->last || scmrq->aob->request.msb_count == nr_requests_per_io) {
+ scm_request_start(scmrq);
+ sq->scmrq = NULL;
+ }
+ spin_unlock(&sq->lock);
+ return BLK_MQ_RQ_QUEUE_OK;
+}
- if (scmrq->aob->request.msb_count < nr_requests_per_io)
- continue;
+static int scm_blk_init_hctx(struct blk_mq_hw_ctx *hctx, void *data,
+ unsigned int idx)
+{
+ struct scm_queue *qd = kzalloc(sizeof(*qd), GFP_KERNEL);
- if (scm_request_start(scmrq))
- return;
+ if (!qd)
+ return -ENOMEM;
- scmrq = NULL;
- }
-out:
- if (scmrq)
- scm_request_start(scmrq);
- else
- scm_ensure_queue_restart(bdev);
+ spin_lock_init(&qd->lock);
+ hctx->driver_data = qd;
+
+ return 0;
+}
+
+static void scm_blk_exit_hctx(struct blk_mq_hw_ctx *hctx, unsigned int idx)
+{
+ struct scm_queue *qd = hctx->driver_data;
+
+ WARN_ON(qd->scmrq);
+ kfree(hctx->driver_data);
+ hctx->driver_data = NULL;
}
static void __scmrq_log_error(struct scm_request *scmrq)
{
struct aob *aob = scmrq->aob;
- if (scmrq->error == -ETIMEDOUT)
+ if (scmrq->error == BLK_STS_TIMEOUT)
SCM_LOG(1, "Request timeout");
else {
SCM_LOG(1, "Request error");
@@ -377,27 +367,12 @@ static void __scmrq_log_error(struct scm_request *scmrq)
scmrq->error);
}
-void scm_blk_irq(struct scm_device *scmdev, void *data, int error)
-{
- struct scm_request *scmrq = data;
- struct scm_blk_dev *bdev = scmrq->bdev;
-
- scmrq->error = error;
- if (error)
- __scmrq_log_error(scmrq);
-
- spin_lock(&bdev->lock);
- list_add_tail(&scmrq->list, &bdev->finished_requests);
- spin_unlock(&bdev->lock);
- tasklet_hi_schedule(&bdev->tasklet);
-}
-
static void scm_blk_handle_error(struct scm_request *scmrq)
{
struct scm_blk_dev *bdev = scmrq->bdev;
unsigned long flags;
- if (scmrq->error != -EIO)
+ if (scmrq->error != BLK_STS_IOERR)
goto restart;
/* For -EIO the response block is valid. */
@@ -419,54 +394,46 @@ restart:
return;
requeue:
- spin_lock_irqsave(&bdev->rq_lock, flags);
scm_request_requeue(scmrq);
- spin_unlock_irqrestore(&bdev->rq_lock, flags);
}
-static void scm_blk_tasklet(struct scm_blk_dev *bdev)
+void scm_blk_irq(struct scm_device *scmdev, void *data, blk_status_t error)
{
- struct scm_request *scmrq;
- unsigned long flags;
-
- spin_lock_irqsave(&bdev->lock, flags);
- while (!list_empty(&bdev->finished_requests)) {
- scmrq = list_first_entry(&bdev->finished_requests,
- struct scm_request, list);
- list_del(&scmrq->list);
- spin_unlock_irqrestore(&bdev->lock, flags);
+ struct scm_request *scmrq = data;
- if (scmrq->error && scmrq->retries-- > 0) {
+ scmrq->error = error;
+ if (error) {
+ __scmrq_log_error(scmrq);
+ if (scmrq->retries-- > 0) {
scm_blk_handle_error(scmrq);
-
- /* Request restarted or requeued, handle next. */
- spin_lock_irqsave(&bdev->lock, flags);
- continue;
+ return;
}
+ }
- if (scm_test_cluster_request(scmrq)) {
- scm_cluster_request_irq(scmrq);
- spin_lock_irqsave(&bdev->lock, flags);
- continue;
- }
+ scm_request_finish(scmrq);
+}
- scm_request_finish(scmrq);
- spin_lock_irqsave(&bdev->lock, flags);
- }
- spin_unlock_irqrestore(&bdev->lock, flags);
- /* Look out for more requests. */
- blk_run_queue(bdev->rq);
+static void scm_blk_request_done(struct request *req)
+{
+ blk_mq_end_request(req, 0);
}
static const struct block_device_operations scm_blk_devops = {
.owner = THIS_MODULE,
};
+static const struct blk_mq_ops scm_mq_ops = {
+ .queue_rq = scm_blk_request,
+ .complete = scm_blk_request_done,
+ .init_hctx = scm_blk_init_hctx,
+ .exit_hctx = scm_blk_exit_hctx,
+};
+
int scm_blk_dev_setup(struct scm_blk_dev *bdev, struct scm_device *scmdev)
{
- struct request_queue *rq;
- int len, ret = -ENOMEM;
unsigned int devindex, nr_max_blk;
+ struct request_queue *rq;
+ int len, ret;
devindex = atomic_inc_return(&nr_devices) - 1;
/* scma..scmz + scmaa..scmzz */
@@ -477,18 +444,23 @@ int scm_blk_dev_setup(struct scm_blk_dev *bdev, struct scm_device *scmdev)
bdev->scmdev = scmdev;
bdev->state = SCM_OPER;
- spin_lock_init(&bdev->rq_lock);
spin_lock_init(&bdev->lock);
- INIT_LIST_HEAD(&bdev->finished_requests);
atomic_set(&bdev->queued_reqs, 0);
- tasklet_init(&bdev->tasklet,
- (void (*)(unsigned long)) scm_blk_tasklet,
- (unsigned long) bdev);
- rq = blk_init_queue(scm_blk_request, &bdev->rq_lock);
- if (!rq)
+ bdev->tag_set.ops = &scm_mq_ops;
+ bdev->tag_set.nr_hw_queues = nr_requests;
+ bdev->tag_set.queue_depth = nr_requests_per_io * nr_requests;
+ bdev->tag_set.flags = BLK_MQ_F_SHOULD_MERGE;
+
+ ret = blk_mq_alloc_tag_set(&bdev->tag_set);
+ if (ret)
goto out;
+ rq = blk_mq_init_queue(&bdev->tag_set);
+ if (IS_ERR(rq)) {
+ ret = PTR_ERR(rq);
+ goto out_tag;
+ }
bdev->rq = rq;
nr_max_blk = min(scmdev->nr_max_block,
(unsigned int) (PAGE_SIZE / sizeof(struct aidaw)));
@@ -498,12 +470,12 @@ int scm_blk_dev_setup(struct scm_blk_dev *bdev, struct scm_device *scmdev)
blk_queue_max_segments(rq, nr_max_blk);
queue_flag_set_unlocked(QUEUE_FLAG_NONROT, rq);
queue_flag_clear_unlocked(QUEUE_FLAG_ADD_RANDOM, rq);
- scm_blk_dev_cluster_setup(bdev);
bdev->gendisk = alloc_disk(SCM_NR_PARTS);
- if (!bdev->gendisk)
+ if (!bdev->gendisk) {
+ ret = -ENOMEM;
goto out_queue;
-
+ }
rq->queuedata = scmdev;
bdev->gendisk->private_data = scmdev;
bdev->gendisk->fops = &scm_blk_devops;
@@ -528,6 +500,8 @@ int scm_blk_dev_setup(struct scm_blk_dev *bdev, struct scm_device *scmdev)
out_queue:
blk_cleanup_queue(rq);
+out_tag:
+ blk_mq_free_tag_set(&bdev->tag_set);
out:
atomic_dec(&nr_devices);
return ret;
@@ -535,9 +509,9 @@ out:
void scm_blk_dev_cleanup(struct scm_blk_dev *bdev)
{
- tasklet_kill(&bdev->tasklet);
del_gendisk(bdev->gendisk);
blk_cleanup_queue(bdev->gendisk->queue);
+ blk_mq_free_tag_set(&bdev->tag_set);
put_disk(bdev->gendisk);
}
@@ -558,7 +532,7 @@ static bool __init scm_blk_params_valid(void)
if (!nr_requests_per_io || nr_requests_per_io > 64)
return false;
- return scm_cluster_size_valid();
+ return true;
}
static int __init scm_blk_init(void)
diff --git a/drivers/s390/block/scm_blk.h b/drivers/s390/block/scm_blk.h
index 09218cdc5129..71288dd9dd7f 100644
--- a/drivers/s390/block/scm_blk.h
+++ b/drivers/s390/block/scm_blk.h
@@ -4,6 +4,7 @@
#include <linux/interrupt.h>
#include <linux/spinlock.h>
#include <linux/blkdev.h>
+#include <linux/blk-mq.h>
#include <linux/genhd.h>
#include <linux/list.h>
@@ -14,18 +15,14 @@
#define SCM_QUEUE_DELAY 5
struct scm_blk_dev {
- struct tasklet_struct tasklet;
struct request_queue *rq;
struct gendisk *gendisk;
+ struct blk_mq_tag_set tag_set;
struct scm_device *scmdev;
- spinlock_t rq_lock; /* guard the request queue */
- spinlock_t lock; /* guard the rest of the blockdev */
+ spinlock_t lock;
atomic_t queued_reqs;
enum {SCM_OPER, SCM_WR_PROHIBIT} state;
struct list_head finished_requests;
-#ifdef CONFIG_SCM_BLOCK_CLUSTER_WRITE
- struct list_head cluster_list;
-#endif
};
struct scm_request {
@@ -35,14 +32,7 @@ struct scm_request {
struct aob *aob;
struct list_head list;
u8 retries;
- int error;
-#ifdef CONFIG_SCM_BLOCK_CLUSTER_WRITE
- struct {
- enum {CLUSTER_NONE, CLUSTER_READ, CLUSTER_WRITE} state;
- struct list_head list;
- void **buf;
- } cluster;
-#endif
+ blk_status_t error;
};
#define to_aobrq(rq) container_of((void *) rq, struct aob_rq_header, data)
@@ -50,57 +40,13 @@ struct scm_request {
int scm_blk_dev_setup(struct scm_blk_dev *, struct scm_device *);
void scm_blk_dev_cleanup(struct scm_blk_dev *);
void scm_blk_set_available(struct scm_blk_dev *);
-void scm_blk_irq(struct scm_device *, void *, int);
-
-void scm_request_finish(struct scm_request *);
-void scm_request_requeue(struct scm_request *);
+void scm_blk_irq(struct scm_device *, void *, blk_status_t);
struct aidaw *scm_aidaw_fetch(struct scm_request *scmrq, unsigned int bytes);
int scm_drv_init(void);
void scm_drv_cleanup(void);
-#ifdef CONFIG_SCM_BLOCK_CLUSTER_WRITE
-void __scm_free_rq_cluster(struct scm_request *);
-int __scm_alloc_rq_cluster(struct scm_request *);
-void scm_request_cluster_init(struct scm_request *);
-bool scm_reserve_cluster(struct scm_request *);
-void scm_release_cluster(struct scm_request *);
-void scm_blk_dev_cluster_setup(struct scm_blk_dev *);
-bool scm_need_cluster_request(struct scm_request *);
-void scm_initiate_cluster_request(struct scm_request *);
-void scm_cluster_request_irq(struct scm_request *);
-bool scm_test_cluster_request(struct scm_request *);
-bool scm_cluster_size_valid(void);
-#else /* CONFIG_SCM_BLOCK_CLUSTER_WRITE */
-static inline void __scm_free_rq_cluster(struct scm_request *scmrq) {}
-static inline int __scm_alloc_rq_cluster(struct scm_request *scmrq)
-{
- return 0;
-}
-static inline void scm_request_cluster_init(struct scm_request *scmrq) {}
-static inline bool scm_reserve_cluster(struct scm_request *scmrq)
-{
- return true;
-}
-static inline void scm_release_cluster(struct scm_request *scmrq) {}
-static inline void scm_blk_dev_cluster_setup(struct scm_blk_dev *bdev) {}
-static inline bool scm_need_cluster_request(struct scm_request *scmrq)
-{
- return false;
-}
-static inline void scm_initiate_cluster_request(struct scm_request *scmrq) {}
-static inline void scm_cluster_request_irq(struct scm_request *scmrq) {}
-static inline bool scm_test_cluster_request(struct scm_request *scmrq)
-{
- return false;
-}
-static inline bool scm_cluster_size_valid(void)
-{
- return true;
-}
-#endif /* CONFIG_SCM_BLOCK_CLUSTER_WRITE */
-
extern debug_info_t *scm_debug;
#define SCM_LOG(imp, txt) do { \
diff --git a/drivers/s390/block/scm_blk_cluster.c b/drivers/s390/block/scm_blk_cluster.c
deleted file mode 100644
index 7497ddde2dd6..000000000000
--- a/drivers/s390/block/scm_blk_cluster.c
+++ /dev/null
@@ -1,255 +0,0 @@
-/*
- * Block driver for s390 storage class memory.
- *
- * Copyright IBM Corp. 2012
- * Author(s): Sebastian Ott <sebott@linux.vnet.ibm.com>
- */
-
-#include <linux/spinlock.h>
-#include <linux/module.h>
-#include <linux/blkdev.h>
-#include <linux/genhd.h>
-#include <linux/slab.h>
-#include <linux/list.h>
-#include <asm/eadm.h>
-#include "scm_blk.h"
-
-static unsigned int write_cluster_size = 64;
-module_param(write_cluster_size, uint, S_IRUGO);
-MODULE_PARM_DESC(write_cluster_size,
- "Number of pages used for contiguous writes.");
-
-#define CLUSTER_SIZE (write_cluster_size * PAGE_SIZE)
-
-void __scm_free_rq_cluster(struct scm_request *scmrq)
-{
- int i;
-
- if (!scmrq->cluster.buf)
- return;
-
- for (i = 0; i < 2 * write_cluster_size; i++)
- free_page((unsigned long) scmrq->cluster.buf[i]);
-
- kfree(scmrq->cluster.buf);
-}
-
-int __scm_alloc_rq_cluster(struct scm_request *scmrq)
-{
- int i;
-
- scmrq->cluster.buf = kzalloc(sizeof(void *) * 2 * write_cluster_size,
- GFP_KERNEL);
- if (!scmrq->cluster.buf)
- return -ENOMEM;
-
- for (i = 0; i < 2 * write_cluster_size; i++) {
- scmrq->cluster.buf[i] = (void *) get_zeroed_page(GFP_DMA);
- if (!scmrq->cluster.buf[i])
- return -ENOMEM;
- }
- INIT_LIST_HEAD(&scmrq->cluster.list);
- return 0;
-}
-
-void scm_request_cluster_init(struct scm_request *scmrq)
-{
- scmrq->cluster.state = CLUSTER_NONE;
-}
-
-static bool clusters_intersect(struct request *A, struct request *B)
-{
- unsigned long firstA, lastA, firstB, lastB;
-
- firstA = ((u64) blk_rq_pos(A) << 9) / CLUSTER_SIZE;
- lastA = (((u64) blk_rq_pos(A) << 9) +
- blk_rq_bytes(A) - 1) / CLUSTER_SIZE;
-
- firstB = ((u64) blk_rq_pos(B) << 9) / CLUSTER_SIZE;
- lastB = (((u64) blk_rq_pos(B) << 9) +
- blk_rq_bytes(B) - 1) / CLUSTER_SIZE;
-
- return (firstB <= lastA && firstA <= lastB);
-}
-
-bool scm_reserve_cluster(struct scm_request *scmrq)
-{
- struct request *req = scmrq->request[scmrq->aob->request.msb_count];
- struct scm_blk_dev *bdev = scmrq->bdev;
- struct scm_request *iter;
- int pos, add = 1;
-
- if (write_cluster_size == 0)
- return true;
-
- spin_lock(&bdev->lock);
- list_for_each_entry(iter, &bdev->cluster_list, cluster.list) {
- if (iter == scmrq) {
- /*
- * We don't have to use clusters_intersect here, since
- * cluster requests are always started separately.
- */
- add = 0;
- continue;
- }
- for (pos = 0; pos < iter->aob->request.msb_count; pos++) {
- if (clusters_intersect(req, iter->request[pos]) &&
- (rq_data_dir(req) == WRITE ||
- rq_data_dir(iter->request[pos]) == WRITE)) {
- spin_unlock(&bdev->lock);
- return false;
- }
- }
- }
- if (add)
- list_add(&scmrq->cluster.list, &bdev->cluster_list);
- spin_unlock(&bdev->lock);
-
- return true;
-}
-
-void scm_release_cluster(struct scm_request *scmrq)
-{
- struct scm_blk_dev *bdev = scmrq->bdev;
- unsigned long flags;
-
- if (write_cluster_size == 0)
- return;
-
- spin_lock_irqsave(&bdev->lock, flags);
- list_del(&scmrq->cluster.list);
- spin_unlock_irqrestore(&bdev->lock, flags);
-}
-
-void scm_blk_dev_cluster_setup(struct scm_blk_dev *bdev)
-{
- INIT_LIST_HEAD(&bdev->cluster_list);
- blk_queue_io_opt(bdev->rq, CLUSTER_SIZE);
-}
-
-static int scm_prepare_cluster_request(struct scm_request *scmrq)
-{
- struct scm_blk_dev *bdev = scmrq->bdev;
- struct scm_device *scmdev = bdev->gendisk->private_data;
- struct request *req = scmrq->request[0];
- struct msb *msb = &scmrq->aob->msb[0];
- struct req_iterator iter;
- struct aidaw *aidaw;
- struct bio_vec bv;
- int i = 0;
- u64 addr;
-
- switch (scmrq->cluster.state) {
- case CLUSTER_NONE:
- scmrq->cluster.state = CLUSTER_READ;
- /* fall through */
- case CLUSTER_READ:
- msb->bs = MSB_BS_4K;
- msb->oc = MSB_OC_READ;
- msb->flags = MSB_FLAG_IDA;
- msb->blk_count = write_cluster_size;
-
- addr = scmdev->address + ((u64) blk_rq_pos(req) << 9);
- msb->scm_addr = round_down(addr, CLUSTER_SIZE);
-
- if (msb->scm_addr !=
- round_down(addr + (u64) blk_rq_bytes(req) - 1,
- CLUSTER_SIZE))
- msb->blk_count = 2 * write_cluster_size;
-
- aidaw = scm_aidaw_fetch(scmrq, msb->blk_count * PAGE_SIZE);
- if (!aidaw)
- return -ENOMEM;
-
- scmrq->aob->request.msb_count = 1;
- msb->data_addr = (u64) aidaw;
- for (i = 0; i < msb->blk_count; i++) {
- aidaw->data_addr = (u64) scmrq->cluster.buf[i];
- aidaw++;
- }
-
- break;
- case CLUSTER_WRITE:
- aidaw = (void *) msb->data_addr;
- msb->oc = MSB_OC_WRITE;
-
- for (addr = msb->scm_addr;
- addr < scmdev->address + ((u64) blk_rq_pos(req) << 9);
- addr += PAGE_SIZE) {
- aidaw->data_addr = (u64) scmrq->cluster.buf[i];
- aidaw++;
- i++;
- }
- rq_for_each_segment(bv, req, iter) {
- aidaw->data_addr = (u64) page_address(bv.bv_page);
- aidaw++;
- i++;
- }
- for (; i < msb->blk_count; i++) {
- aidaw->data_addr = (u64) scmrq->cluster.buf[i];
- aidaw++;
- }
- break;
- }
- return 0;
-}
-
-bool scm_need_cluster_request(struct scm_request *scmrq)
-{
- int pos = scmrq->aob->request.msb_count;
-
- if (rq_data_dir(scmrq->request[pos]) == READ)
- return false;
-
- return blk_rq_bytes(scmrq->request[pos]) < CLUSTER_SIZE;
-}
-
-/* Called with queue lock held. */
-void scm_initiate_cluster_request(struct scm_request *scmrq)
-{
- if (scm_prepare_cluster_request(scmrq))
- goto requeue;
- if (eadm_start_aob(scmrq->aob))
- goto requeue;
- return;
-requeue:
- scm_request_requeue(scmrq);
-}
-
-bool scm_test_cluster_request(struct scm_request *scmrq)
-{
- return scmrq->cluster.state != CLUSTER_NONE;
-}
-
-void scm_cluster_request_irq(struct scm_request *scmrq)
-{
- struct scm_blk_dev *bdev = scmrq->bdev;
- unsigned long flags;
-
- switch (scmrq->cluster.state) {
- case CLUSTER_NONE:
- BUG();
- break;
- case CLUSTER_READ:
- if (scmrq->error) {
- scm_request_finish(scmrq);
- break;
- }
- scmrq->cluster.state = CLUSTER_WRITE;
- spin_lock_irqsave(&bdev->rq_lock, flags);
- scm_initiate_cluster_request(scmrq);
- spin_unlock_irqrestore(&bdev->rq_lock, flags);
- break;
- case CLUSTER_WRITE:
- scm_request_finish(scmrq);
- break;
- }
-}
-
-bool scm_cluster_size_valid(void)
-{
- if (write_cluster_size == 1 || write_cluster_size > 128)
- return false;
-
- return !(write_cluster_size & (write_cluster_size - 1));
-}
diff --git a/drivers/s390/block/xpram.c b/drivers/s390/block/xpram.c
index b9d7e755c8a3..a48f0d40c1d2 100644
--- a/drivers/s390/block/xpram.c
+++ b/drivers/s390/block/xpram.c
@@ -190,7 +190,7 @@ static blk_qc_t xpram_make_request(struct request_queue *q, struct bio *bio)
unsigned long page_addr;
unsigned long bytes;
- blk_queue_split(q, &bio, q->bio_split);
+ blk_queue_split(q, &bio);
if ((bio->bi_iter.bi_sector & 7) != 0 ||
(bio->bi_iter.bi_size & 4095) != 0)
diff --git a/drivers/s390/cio/css.c b/drivers/s390/cio/css.c
index e2aa944eb566..d3e504c3c362 100644
--- a/drivers/s390/cio/css.c
+++ b/drivers/s390/cio/css.c
@@ -296,6 +296,51 @@ static const struct attribute_group *default_subch_attr_groups[] = {
NULL,
};
+static ssize_t chpids_show(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ struct subchannel *sch = to_subchannel(dev);
+ struct chsc_ssd_info *ssd = &sch->ssd_info;
+ ssize_t ret = 0;
+ int mask;
+ int chp;
+
+ for (chp = 0; chp < 8; chp++) {
+ mask = 0x80 >> chp;
+ if (ssd->path_mask & mask)
+ ret += sprintf(buf + ret, "%02x ", ssd->chpid[chp].id);
+ else
+ ret += sprintf(buf + ret, "00 ");
+ }
+ ret += sprintf(buf + ret, "\n");
+ return ret;
+}
+static DEVICE_ATTR(chpids, 0444, chpids_show, NULL);
+
+static ssize_t pimpampom_show(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ struct subchannel *sch = to_subchannel(dev);
+ struct pmcw *pmcw = &sch->schib.pmcw;
+
+ return sprintf(buf, "%02x %02x %02x\n",
+ pmcw->pim, pmcw->pam, pmcw->pom);
+}
+static DEVICE_ATTR(pimpampom, 0444, pimpampom_show, NULL);
+
+static struct attribute *io_subchannel_type_attrs[] = {
+ &dev_attr_chpids.attr,
+ &dev_attr_pimpampom.attr,
+ NULL,
+};
+ATTRIBUTE_GROUPS(io_subchannel_type);
+
+static const struct device_type io_subchannel_type = {
+ .groups = io_subchannel_type_groups,
+};
+
int css_register_subchannel(struct subchannel *sch)
{
int ret;
@@ -304,6 +349,10 @@ int css_register_subchannel(struct subchannel *sch)
sch->dev.parent = &channel_subsystems[0]->device;
sch->dev.bus = &css_bus_type;
sch->dev.groups = default_subch_attr_groups;
+
+ if (sch->st == SUBCHANNEL_TYPE_IO)
+ sch->dev.type = &io_subchannel_type;
+
/*
* We don't want to generate uevents for I/O subchannels that don't
* have a working ccw device behind them since they will be
diff --git a/drivers/s390/cio/device.c b/drivers/s390/cio/device.c
index b8006ea9099c..7be01a58b44f 100644
--- a/drivers/s390/cio/device.c
+++ b/drivers/s390/cio/device.c
@@ -208,44 +208,6 @@ int __init io_subchannel_init(void)
/************************ device handling **************************/
-/*
- * A ccw_device has some interfaces in sysfs in addition to the
- * standard ones.
- * The following entries are designed to export the information which
- * resided in 2.4 in /proc/subchannels. Subchannel and device number
- * are obvious, so they don't have an entry :)
- * TODO: Split chpids and pimpampom up? Where is "in use" in the tree?
- */
-static ssize_t
-chpids_show (struct device * dev, struct device_attribute *attr, char * buf)
-{
- struct subchannel *sch = to_subchannel(dev);
- struct chsc_ssd_info *ssd = &sch->ssd_info;
- ssize_t ret = 0;
- int chp;
- int mask;
-
- for (chp = 0; chp < 8; chp++) {
- mask = 0x80 >> chp;
- if (ssd->path_mask & mask)
- ret += sprintf(buf + ret, "%02x ", ssd->chpid[chp].id);
- else
- ret += sprintf(buf + ret, "00 ");
- }
- ret += sprintf (buf+ret, "\n");
- return min((ssize_t)PAGE_SIZE, ret);
-}
-
-static ssize_t
-pimpampom_show (struct device * dev, struct device_attribute *attr, char * buf)
-{
- struct subchannel *sch = to_subchannel(dev);
- struct pmcw *pmcw = &sch->schib.pmcw;
-
- return sprintf (buf, "%02x %02x %02x\n",
- pmcw->pim, pmcw->pam, pmcw->pom);
-}
-
static ssize_t
devtype_show (struct device *dev, struct device_attribute *attr, char *buf)
{
@@ -636,8 +598,6 @@ static ssize_t vpm_show(struct device *dev, struct device_attribute *attr,
return sprintf(buf, "%02x\n", sch->vpm);
}
-static DEVICE_ATTR(chpids, 0444, chpids_show, NULL);
-static DEVICE_ATTR(pimpampom, 0444, pimpampom_show, NULL);
static DEVICE_ATTR(devtype, 0444, devtype_show, NULL);
static DEVICE_ATTR(cutype, 0444, cutype_show, NULL);
static DEVICE_ATTR(modalias, 0444, modalias_show, NULL);
@@ -647,8 +607,6 @@ static DEVICE_ATTR(logging, 0200, NULL, initiate_logging);
static DEVICE_ATTR(vpm, 0444, vpm_show, NULL);
static struct attribute *io_subchannel_attrs[] = {
- &dev_attr_chpids.attr,
- &dev_attr_pimpampom.attr,
&dev_attr_logging.attr,
&dev_attr_vpm.attr,
NULL,
diff --git a/drivers/s390/cio/eadm_sch.c b/drivers/s390/cio/eadm_sch.c
index b3f44bc7f644..0f11f3bcac82 100644
--- a/drivers/s390/cio/eadm_sch.c
+++ b/drivers/s390/cio/eadm_sch.c
@@ -135,7 +135,7 @@ static void eadm_subchannel_irq(struct subchannel *sch)
struct eadm_private *private = get_eadm_private(sch);
struct eadm_scsw *scsw = &sch->schib.scsw.eadm;
struct irb *irb = this_cpu_ptr(&cio_irb);
- int error = 0;
+ blk_status_t error = BLK_STS_OK;
EADM_LOG(6, "irq");
EADM_LOG_HEX(6, irb, sizeof(*irb));
@@ -144,10 +144,10 @@ static void eadm_subchannel_irq(struct subchannel *sch)
if ((scsw->stctl & (SCSW_STCTL_ALERT_STATUS | SCSW_STCTL_STATUS_PEND))
&& scsw->eswf == 1 && irb->esw.eadm.erw.r)
- error = -EIO;
+ error = BLK_STS_IOERR;
if (scsw->fctl & SCSW_FCTL_CLEAR_FUNC)
- error = -ETIMEDOUT;
+ error = BLK_STS_TIMEOUT;
eadm_subchannel_set_timeout(sch, 0);
diff --git a/drivers/s390/cio/scm.c b/drivers/s390/cio/scm.c
index 15268edc54ae..1fa53ecdc2aa 100644
--- a/drivers/s390/cio/scm.c
+++ b/drivers/s390/cio/scm.c
@@ -71,7 +71,7 @@ void scm_driver_unregister(struct scm_driver *scmdrv)
}
EXPORT_SYMBOL_GPL(scm_driver_unregister);
-void scm_irq_handler(struct aob *aob, int error)
+void scm_irq_handler(struct aob *aob, blk_status_t error)
{
struct aob_rq_header *aobrq = (void *) aob->request.data;
struct scm_device *scmdev = aobrq->scmdev;
diff --git a/drivers/s390/cio/vfio_ccw_drv.c b/drivers/s390/cio/vfio_ccw_drv.c
index e90dd43d2a55..a25367ebaa89 100644
--- a/drivers/s390/cio/vfio_ccw_drv.c
+++ b/drivers/s390/cio/vfio_ccw_drv.c
@@ -90,54 +90,6 @@ static void vfio_ccw_sch_io_todo(struct work_struct *work)
}
/*
- * Sysfs interfaces
- */
-static ssize_t chpids_show(struct device *dev,
- struct device_attribute *attr,
- char *buf)
-{
- struct subchannel *sch = to_subchannel(dev);
- struct chsc_ssd_info *ssd = &sch->ssd_info;
- ssize_t ret = 0;
- int chp;
- int mask;
-
- for (chp = 0; chp < 8; chp++) {
- mask = 0x80 >> chp;
- if (ssd->path_mask & mask)
- ret += sprintf(buf + ret, "%02x ", ssd->chpid[chp].id);
- else
- ret += sprintf(buf + ret, "00 ");
- }
- ret += sprintf(buf+ret, "\n");
- return ret;
-}
-
-static ssize_t pimpampom_show(struct device *dev,
- struct device_attribute *attr,
- char *buf)
-{
- struct subchannel *sch = to_subchannel(dev);
- struct pmcw *pmcw = &sch->schib.pmcw;
-
- return sprintf(buf, "%02x %02x %02x\n",
- pmcw->pim, pmcw->pam, pmcw->pom);
-}
-
-static DEVICE_ATTR(chpids, 0444, chpids_show, NULL);
-static DEVICE_ATTR(pimpampom, 0444, pimpampom_show, NULL);
-
-static struct attribute *vfio_subchannel_attrs[] = {
- &dev_attr_chpids.attr,
- &dev_attr_pimpampom.attr,
- NULL,
-};
-
-static struct attribute_group vfio_subchannel_attr_group = {
- .attrs = vfio_subchannel_attrs,
-};
-
-/*
* Css driver callbacks
*/
static void vfio_ccw_sch_irq(struct subchannel *sch)
@@ -174,13 +126,9 @@ static int vfio_ccw_sch_probe(struct subchannel *sch)
if (ret)
goto out_free;
- ret = sysfs_create_group(&sch->dev.kobj, &vfio_subchannel_attr_group);
- if (ret)
- goto out_disable;
-
ret = vfio_ccw_mdev_reg(sch);
if (ret)
- goto out_rm_group;
+ goto out_disable;
INIT_WORK(&private->io_work, vfio_ccw_sch_io_todo);
atomic_set(&private->avail, 1);
@@ -188,8 +136,6 @@ static int vfio_ccw_sch_probe(struct subchannel *sch)
return 0;
-out_rm_group:
- sysfs_remove_group(&sch->dev.kobj, &vfio_subchannel_attr_group);
out_disable:
cio_disable_subchannel(sch);
out_free:
@@ -206,8 +152,6 @@ static int vfio_ccw_sch_remove(struct subchannel *sch)
vfio_ccw_mdev_unreg(sch);
- sysfs_remove_group(&sch->dev.kobj, &vfio_subchannel_attr_group);
-
dev_set_drvdata(&sch->dev, NULL);
kfree(private);
diff --git a/drivers/s390/cio/vfio_ccw_ops.c b/drivers/s390/cio/vfio_ccw_ops.c
index e72abbc18ee3..a66a317f3e4f 100644
--- a/drivers/s390/cio/vfio_ccw_ops.c
+++ b/drivers/s390/cio/vfio_ccw_ops.c
@@ -70,14 +70,14 @@ static ssize_t name_show(struct kobject *kobj, struct device *dev, char *buf)
{
return sprintf(buf, "I/O subchannel (Non-QDIO)\n");
}
-MDEV_TYPE_ATTR_RO(name);
+static MDEV_TYPE_ATTR_RO(name);
static ssize_t device_api_show(struct kobject *kobj, struct device *dev,
char *buf)
{
return sprintf(buf, "%s\n", VFIO_DEVICE_API_CCW_STRING);
}
-MDEV_TYPE_ATTR_RO(device_api);
+static MDEV_TYPE_ATTR_RO(device_api);
static ssize_t available_instances_show(struct kobject *kobj,
struct device *dev, char *buf)
@@ -86,7 +86,7 @@ static ssize_t available_instances_show(struct kobject *kobj,
return sprintf(buf, "%d\n", atomic_read(&private->avail));
}
-MDEV_TYPE_ATTR_RO(available_instances);
+static MDEV_TYPE_ATTR_RO(available_instances);
static struct attribute *mdev_types_attrs[] = {
&mdev_type_attr_name.attr,
@@ -100,7 +100,7 @@ static struct attribute_group mdev_type_group = {
.attrs = mdev_types_attrs,
};
-struct attribute_group *mdev_type_groups[] = {
+static struct attribute_group *mdev_type_groups[] = {
&mdev_type_group,
NULL,
};
@@ -152,7 +152,7 @@ static int vfio_ccw_mdev_open(struct mdev_device *mdev)
&events, &private->nb);
}
-void vfio_ccw_mdev_release(struct mdev_device *mdev)
+static void vfio_ccw_mdev_release(struct mdev_device *mdev)
{
struct vfio_ccw_private *private =
dev_get_drvdata(mdev_parent_dev(mdev));
@@ -233,7 +233,7 @@ static int vfio_ccw_mdev_get_region_info(struct vfio_region_info *info,
}
}
-int vfio_ccw_mdev_get_irq_info(struct vfio_irq_info *info)
+static int vfio_ccw_mdev_get_irq_info(struct vfio_irq_info *info)
{
if (info->index != VFIO_CCW_IO_IRQ_INDEX)
return -EINVAL;
diff --git a/drivers/s390/crypto/ap_bus.c b/drivers/s390/crypto/ap_bus.c
index 9be4596d8a08..6dee598979e7 100644
--- a/drivers/s390/crypto/ap_bus.c
+++ b/drivers/s390/crypto/ap_bus.c
@@ -668,10 +668,28 @@ static int ap_device_probe(struct device *dev)
struct ap_driver *ap_drv = to_ap_drv(dev->driver);
int rc;
+ /* Add queue/card to list of active queues/cards */
+ spin_lock_bh(&ap_list_lock);
+ if (is_card_dev(dev))
+ list_add(&to_ap_card(dev)->list, &ap_card_list);
+ else
+ list_add(&to_ap_queue(dev)->list,
+ &to_ap_queue(dev)->card->queues);
+ spin_unlock_bh(&ap_list_lock);
+
ap_dev->drv = ap_drv;
rc = ap_drv->probe ? ap_drv->probe(ap_dev) : -ENODEV;
- if (rc)
+
+ if (rc) {
+ spin_lock_bh(&ap_list_lock);
+ if (is_card_dev(dev))
+ list_del_init(&to_ap_card(dev)->list);
+ else
+ list_del_init(&to_ap_queue(dev)->list);
+ spin_unlock_bh(&ap_list_lock);
ap_dev->drv = NULL;
+ }
+
return rc;
}
@@ -680,14 +698,17 @@ static int ap_device_remove(struct device *dev)
struct ap_device *ap_dev = to_ap_dev(dev);
struct ap_driver *ap_drv = ap_dev->drv;
+ if (ap_drv->remove)
+ ap_drv->remove(ap_dev);
+
+ /* Remove queue/card from list of active queues/cards */
spin_lock_bh(&ap_list_lock);
if (is_card_dev(dev))
list_del_init(&to_ap_card(dev)->list);
else
list_del_init(&to_ap_queue(dev)->list);
spin_unlock_bh(&ap_list_lock);
- if (ap_drv->remove)
- ap_drv->remove(ap_dev);
+
return 0;
}
@@ -745,7 +766,7 @@ static ssize_t ap_domain_store(struct bus_type *bus,
ap_domain_index = domain;
spin_unlock_bh(&ap_domain_lock);
- AP_DBF(DBF_DEBUG, "store new default domain=%d\n", domain);
+ AP_DBF(DBF_DEBUG, "stored new default domain=%d\n", domain);
return count;
}
@@ -931,6 +952,7 @@ static int ap_select_domain(void)
}
if (best_domain >= 0){
ap_domain_index = best_domain;
+ AP_DBF(DBF_DEBUG, "new ap_domain_index=%d\n", ap_domain_index);
spin_unlock_bh(&ap_domain_lock);
return 0;
}
@@ -967,7 +989,7 @@ static void ap_scan_bus(struct work_struct *unused)
ap_qid_t qid;
int depth = 0, type = 0;
unsigned int functions = 0;
- int rc, id, dom, borked, domains;
+ int rc, id, dom, borked, domains, defdomdevs = 0;
AP_DBF(DBF_DEBUG, "ap_scan_bus running\n");
@@ -1031,6 +1053,8 @@ static void ap_scan_bus(struct work_struct *unused)
put_device(dev);
if (!borked) {
domains++;
+ if (dom == ap_domain_index)
+ defdomdevs++;
continue;
}
}
@@ -1056,10 +1080,6 @@ static void ap_scan_bus(struct work_struct *unused)
}
/* get it and thus adjust reference counter */
get_device(&ac->ap_dev.device);
- /* Add card device to card list */
- spin_lock_bh(&ap_list_lock);
- list_add(&ac->list, &ap_card_list);
- spin_unlock_bh(&ap_list_lock);
}
/* now create the new queue device */
aq = ap_queue_create(qid, type);
@@ -1070,10 +1090,6 @@ static void ap_scan_bus(struct work_struct *unused)
aq->ap_dev.device.parent = &ac->ap_dev.device;
dev_set_name(&aq->ap_dev.device,
"%02x.%04x", id, dom);
- /* Add queue device to card queue list */
- spin_lock_bh(&ap_list_lock);
- list_add(&aq->list, &ac->queues);
- spin_unlock_bh(&ap_list_lock);
/* Start with a device reset */
spin_lock_bh(&aq->lock);
ap_wait(ap_sm_event(aq, AP_EVENT_POLL));
@@ -1081,13 +1097,12 @@ static void ap_scan_bus(struct work_struct *unused)
/* Register device */
rc = device_register(&aq->ap_dev.device);
if (rc) {
- spin_lock_bh(&ap_list_lock);
- list_del_init(&aq->list);
- spin_unlock_bh(&ap_list_lock);
put_device(&aq->ap_dev.device);
continue;
}
domains++;
+ if (dom == ap_domain_index)
+ defdomdevs++;
} /* end domain loop */
if (ac) {
/* remove card dev if there are no queue devices */
@@ -1096,6 +1111,11 @@ static void ap_scan_bus(struct work_struct *unused)
put_device(&ac->ap_dev.device);
}
} /* end device loop */
+
+ if (defdomdevs < 1)
+ AP_DBF(DBF_INFO, "no queue device with default domain %d available\n",
+ ap_domain_index);
+
out:
mod_timer(&ap_config_timer, jiffies + ap_config_time * HZ);
}
@@ -1164,14 +1184,14 @@ int __init ap_module_init(void)
ap_init_configuration();
if (ap_configuration)
- max_domain_id = ap_max_domain_id ? : (AP_DOMAINS - 1);
+ max_domain_id =
+ ap_max_domain_id ? ap_max_domain_id : AP_DOMAINS - 1;
else
max_domain_id = 15;
if (ap_domain_index < -1 || ap_domain_index > max_domain_id) {
pr_warn("%d is not a valid cryptographic domain\n",
ap_domain_index);
- rc = -EINVAL;
- goto out_free;
+ ap_domain_index = -1;
}
/* In resume callback we need to know if the user had set the domain.
* If so, we can not just reset it.
@@ -1244,7 +1264,6 @@ out:
unregister_reset_call(&ap_reset_call);
if (ap_using_interrupts())
unregister_adapter_interrupt(&ap_airq);
-out_free:
kfree(ap_configuration);
return rc;
}
diff --git a/drivers/s390/crypto/ap_card.c b/drivers/s390/crypto/ap_card.c
index cfa161ccc74e..836efac96813 100644
--- a/drivers/s390/crypto/ap_card.c
+++ b/drivers/s390/crypto/ap_card.c
@@ -160,7 +160,14 @@ static struct device_type ap_card_type = {
static void ap_card_device_release(struct device *dev)
{
- kfree(to_ap_card(dev));
+ struct ap_card *ac = to_ap_card(dev);
+
+ if (!list_empty(&ac->list)) {
+ spin_lock_bh(&ap_list_lock);
+ list_del_init(&ac->list);
+ spin_unlock_bh(&ap_list_lock);
+ }
+ kfree(ac);
}
struct ap_card *ap_card_create(int id, int queue_depth, int device_type,
diff --git a/drivers/s390/crypto/ap_queue.c b/drivers/s390/crypto/ap_queue.c
index 480c58a63769..0f1a5d02acb0 100644
--- a/drivers/s390/crypto/ap_queue.c
+++ b/drivers/s390/crypto/ap_queue.c
@@ -584,7 +584,14 @@ static struct device_type ap_queue_type = {
static void ap_queue_device_release(struct device *dev)
{
- kfree(to_ap_queue(dev));
+ struct ap_queue *aq = to_ap_queue(dev);
+
+ if (!list_empty(&aq->list)) {
+ spin_lock_bh(&ap_list_lock);
+ list_del_init(&aq->list);
+ spin_unlock_bh(&ap_list_lock);
+ }
+ kfree(aq);
}
struct ap_queue *ap_queue_create(ap_qid_t qid, int device_type)
diff --git a/drivers/s390/crypto/pkey_api.c b/drivers/s390/crypto/pkey_api.c
index ea86da8c75f9..f61fa47135a6 100644
--- a/drivers/s390/crypto/pkey_api.c
+++ b/drivers/s390/crypto/pkey_api.c
@@ -178,9 +178,9 @@ static inline void prep_xcrb(struct ica_xcRB *pxcrb,
pxcrb->user_defined = (cardnr == 0xFFFF ? AUTOSELECT : cardnr);
pxcrb->request_control_blk_length =
preqcblk->cprb_len + preqcblk->req_parml;
- pxcrb->request_control_blk_addr = (void *) preqcblk;
+ pxcrb->request_control_blk_addr = (void __user *) preqcblk;
pxcrb->reply_control_blk_length = preqcblk->rpl_msgbl;
- pxcrb->reply_control_blk_addr = (void *) prepcblk;
+ pxcrb->reply_control_blk_addr = (void __user *) prepcblk;
}
/*
@@ -1194,7 +1194,7 @@ static struct miscdevice pkey_dev = {
/*
* Module init
*/
-int __init pkey_init(void)
+static int __init pkey_init(void)
{
cpacf_mask_t pckmo_functions;
diff --git a/drivers/s390/crypto/zcrypt_api.c b/drivers/s390/crypto/zcrypt_api.c
index 93015f85d4a6..b1c27e28859b 100644
--- a/drivers/s390/crypto/zcrypt_api.c
+++ b/drivers/s390/crypto/zcrypt_api.c
@@ -821,8 +821,10 @@ static long zcrypt_unlocked_ioctl(struct file *filp, unsigned int cmd,
do {
rc = zcrypt_rsa_modexpo(&mex);
} while (rc == -EAGAIN);
- if (rc)
+ if (rc) {
+ ZCRYPT_DBF(DBF_DEBUG, "ioctl ICARSAMODEXPO rc=%d", rc);
return rc;
+ }
return put_user(mex.outputdatalength, &umex->outputdatalength);
}
case ICARSACRT: {
@@ -838,8 +840,10 @@ static long zcrypt_unlocked_ioctl(struct file *filp, unsigned int cmd,
do {
rc = zcrypt_rsa_crt(&crt);
} while (rc == -EAGAIN);
- if (rc)
+ if (rc) {
+ ZCRYPT_DBF(DBF_DEBUG, "ioctl ICARSACRT rc=%d", rc);
return rc;
+ }
return put_user(crt.outputdatalength, &ucrt->outputdatalength);
}
case ZSECSENDCPRB: {
@@ -855,6 +859,8 @@ static long zcrypt_unlocked_ioctl(struct file *filp, unsigned int cmd,
do {
rc = zcrypt_send_cprb(&xcRB);
} while (rc == -EAGAIN);
+ if (rc)
+ ZCRYPT_DBF(DBF_DEBUG, "ioctl ZSENDCPRB rc=%d", rc);
if (copy_to_user(uxcRB, &xcRB, sizeof(xcRB)))
return -EFAULT;
return rc;
@@ -872,6 +878,8 @@ static long zcrypt_unlocked_ioctl(struct file *filp, unsigned int cmd,
do {
rc = zcrypt_send_ep11_cprb(&xcrb);
} while (rc == -EAGAIN);
+ if (rc)
+ ZCRYPT_DBF(DBF_DEBUG, "ioctl ZSENDEP11CPRB rc=%d", rc);
if (copy_to_user(uxcrb, &xcrb, sizeof(xcrb)))
return -EFAULT;
return rc;
diff --git a/drivers/s390/crypto/zcrypt_cca_key.h b/drivers/s390/crypto/zcrypt_cca_key.h
index ca0cdbe46368..12cff6262566 100644
--- a/drivers/s390/crypto/zcrypt_cca_key.h
+++ b/drivers/s390/crypto/zcrypt_cca_key.h
@@ -48,26 +48,6 @@ struct cca_token_hdr {
#define CCA_TKN_HDR_ID_EXT 0x1E
-/**
- * mapping for the cca private ME section
- */
-struct cca_private_ext_ME_sec {
- unsigned char section_identifier;
- unsigned char version;
- unsigned short section_length;
- unsigned char private_key_hash[20];
- unsigned char reserved1[4];
- unsigned char key_format;
- unsigned char reserved2;
- unsigned char key_name_hash[20];
- unsigned char key_use_flags[4];
- unsigned char reserved3[6];
- unsigned char reserved4[24];
- unsigned char confounder[24];
- unsigned char exponent[128];
- unsigned char modulus[128];
-} __attribute__((packed));
-
#define CCA_PVT_USAGE_ALL 0x80
/**
@@ -124,77 +104,6 @@ struct cca_pvt_ext_CRT_sec {
#define CCA_PVT_EXT_CRT_SEC_FMT_CL 0x40
/**
- * Set up private key fields of a type6 MEX message.
- * Note that all numerics in the key token are big-endian,
- * while the entries in the key block header are little-endian.
- *
- * @mex: pointer to user input data
- * @p: pointer to memory area for the key
- *
- * Returns the size of the key area or -EFAULT
- */
-static inline int zcrypt_type6_mex_key_de(struct ica_rsa_modexpo *mex,
- void *p, int big_endian)
-{
- static struct cca_token_hdr static_pvt_me_hdr = {
- .token_identifier = 0x1E,
- .token_length = 0x0183,
- };
- static struct cca_private_ext_ME_sec static_pvt_me_sec = {
- .section_identifier = 0x02,
- .section_length = 0x016C,
- .key_use_flags = {0x80,0x00,0x00,0x00},
- };
- static struct cca_public_sec static_pub_me_sec = {
- .section_identifier = 0x04,
- .section_length = 0x000F,
- .exponent_len = 0x0003,
- };
- static char pk_exponent[3] = { 0x01, 0x00, 0x01 };
- struct {
- struct T6_keyBlock_hdr t6_hdr;
- struct cca_token_hdr pvtMeHdr;
- struct cca_private_ext_ME_sec pvtMeSec;
- struct cca_public_sec pubMeSec;
- char exponent[3];
- } __attribute__((packed)) *key = p;
- unsigned char *temp;
-
- memset(key, 0, sizeof(*key));
-
- if (big_endian) {
- key->t6_hdr.blen = cpu_to_be16(0x189);
- key->t6_hdr.ulen = cpu_to_be16(0x189 - 2);
- } else {
- key->t6_hdr.blen = cpu_to_le16(0x189);
- key->t6_hdr.ulen = cpu_to_le16(0x189 - 2);
- }
- key->pvtMeHdr = static_pvt_me_hdr;
- key->pvtMeSec = static_pvt_me_sec;
- key->pubMeSec = static_pub_me_sec;
- /*
- * In a private key, the modulus doesn't appear in the public
- * section. So, an arbitrary public exponent of 0x010001 will be
- * used.
- */
- memcpy(key->exponent, pk_exponent, 3);
-
- /* key parameter block */
- temp = key->pvtMeSec.exponent +
- sizeof(key->pvtMeSec.exponent) - mex->inputdatalength;
- if (copy_from_user(temp, mex->b_key, mex->inputdatalength))
- return -EFAULT;
-
- /* modulus */
- temp = key->pvtMeSec.modulus +
- sizeof(key->pvtMeSec.modulus) - mex->inputdatalength;
- if (copy_from_user(temp, mex->n_modulus, mex->inputdatalength))
- return -EFAULT;
- key->pubMeSec.modulus_bit_len = 8 * mex->inputdatalength;
- return sizeof(*key);
-}
-
-/**
* Set up private key fields of a type6 MEX message. The _pad variant
* strips leading zeroes from the b_key.
* Note that all numerics in the key token are big-endian,
@@ -205,8 +114,7 @@ static inline int zcrypt_type6_mex_key_de(struct ica_rsa_modexpo *mex,
*
* Returns the size of the key area or -EFAULT
*/
-static inline int zcrypt_type6_mex_key_en(struct ica_rsa_modexpo *mex,
- void *p, int big_endian)
+static inline int zcrypt_type6_mex_key_en(struct ica_rsa_modexpo *mex, void *p)
{
static struct cca_token_hdr static_pub_hdr = {
.token_identifier = 0x1E,
@@ -251,13 +159,8 @@ static inline int zcrypt_type6_mex_key_en(struct ica_rsa_modexpo *mex,
2*mex->inputdatalength - i;
key->pubHdr.token_length =
key->pubSec.section_length + sizeof(key->pubHdr);
- if (big_endian) {
- key->t6_hdr.ulen = cpu_to_be16(key->pubHdr.token_length + 4);
- key->t6_hdr.blen = cpu_to_be16(key->pubHdr.token_length + 6);
- } else {
- key->t6_hdr.ulen = cpu_to_le16(key->pubHdr.token_length + 4);
- key->t6_hdr.blen = cpu_to_le16(key->pubHdr.token_length + 6);
- }
+ key->t6_hdr.ulen = key->pubHdr.token_length + 4;
+ key->t6_hdr.blen = key->pubHdr.token_length + 6;
return sizeof(*key) + 2*mex->inputdatalength - i;
}
@@ -271,8 +174,7 @@ static inline int zcrypt_type6_mex_key_en(struct ica_rsa_modexpo *mex,
*
* Returns the size of the key area or -EFAULT
*/
-static inline int zcrypt_type6_crt_key(struct ica_rsa_modexpo_crt *crt,
- void *p, int big_endian)
+static inline int zcrypt_type6_crt_key(struct ica_rsa_modexpo_crt *crt, void *p)
{
static struct cca_public_sec static_cca_pub_sec = {
.section_identifier = 4,
@@ -298,13 +200,8 @@ static inline int zcrypt_type6_crt_key(struct ica_rsa_modexpo_crt *crt,
size = sizeof(*key) + key_len + sizeof(*pub) + 3;
/* parameter block.key block */
- if (big_endian) {
- key->t6_hdr.blen = cpu_to_be16(size);
- key->t6_hdr.ulen = cpu_to_be16(size - 2);
- } else {
- key->t6_hdr.blen = cpu_to_le16(size);
- key->t6_hdr.ulen = cpu_to_le16(size - 2);
- }
+ key->t6_hdr.blen = size;
+ key->t6_hdr.ulen = size - 2;
/* key token header */
key->token.token_identifier = CCA_TKN_HDR_ID_EXT;
diff --git a/drivers/s390/crypto/zcrypt_msgtype6.c b/drivers/s390/crypto/zcrypt_msgtype6.c
index e5563ffeb839..4fddb4319481 100644
--- a/drivers/s390/crypto/zcrypt_msgtype6.c
+++ b/drivers/s390/crypto/zcrypt_msgtype6.c
@@ -291,7 +291,7 @@ static int ICAMEX_msg_to_type6MEX_msgX(struct zcrypt_queue *zq,
return -EFAULT;
/* Set up key which is located after the variable length text. */
- size = zcrypt_type6_mex_key_en(mex, msg->text+mex->inputdatalength, 1);
+ size = zcrypt_type6_mex_key_en(mex, msg->text+mex->inputdatalength);
if (size < 0)
return size;
size += sizeof(*msg) + mex->inputdatalength;
@@ -353,7 +353,7 @@ static int ICACRT_msg_to_type6CRT_msgX(struct zcrypt_queue *zq,
return -EFAULT;
/* Set up key which is located after the variable length text. */
- size = zcrypt_type6_crt_key(crt, msg->text + crt->inputdatalength, 1);
+ size = zcrypt_type6_crt_key(crt, msg->text + crt->inputdatalength);
if (size < 0)
return size;
size += sizeof(*msg) + crt->inputdatalength; /* total size of msg */
diff --git a/drivers/s390/net/netiucv.c b/drivers/s390/net/netiucv.c
index fed9d6b56e5b..f1f6eb112531 100644
--- a/drivers/s390/net/netiucv.c
+++ b/drivers/s390/net/netiucv.c
@@ -1954,7 +1954,6 @@ static void netiucv_free_netdevice(struct net_device *dev)
privptr->conn = NULL; privptr->fsm = NULL;
/* privptr gets freed by free_netdev() */
}
- free_netdev(dev);
}
/**
@@ -1972,7 +1971,8 @@ static void netiucv_setup_netdevice(struct net_device *dev)
dev->mtu = NETIUCV_MTU_DEFAULT;
dev->min_mtu = 576;
dev->max_mtu = NETIUCV_MTU_MAX;
- dev->destructor = netiucv_free_netdevice;
+ dev->needs_free_netdev = true;
+ dev->priv_destructor = netiucv_free_netdevice;
dev->hard_header_len = NETIUCV_HDRLEN;
dev->addr_len = 0;
dev->type = ARPHRD_SLIP;
diff --git a/drivers/sbus/char/jsflash.c b/drivers/sbus/char/jsflash.c
index 62fed9dc893e..14f377ac1280 100644
--- a/drivers/sbus/char/jsflash.c
+++ b/drivers/sbus/char/jsflash.c
@@ -214,7 +214,7 @@ static void jsfd_request(void)
struct jsfd_part *jdp = req->rq_disk->private_data;
unsigned long offset = blk_rq_pos(req) << 9;
size_t len = blk_rq_cur_bytes(req);
- int err = -EIO;
+ blk_status_t err = BLK_STS_IOERR;
if ((offset + len) > jdp->dsize)
goto end;
@@ -230,7 +230,7 @@ static void jsfd_request(void)
}
jsfd_read(bio_data(req->bio), jdp->dbase + offset, len);
- err = 0;
+ err = BLK_STS_OK;
end:
if (!__blk_end_request_cur(req, err))
req = jsfd_next_request();
@@ -592,6 +592,7 @@ static int jsfd_init(void)
put_disk(disk);
goto out;
}
+ blk_queue_bounce_limit(disk->queue, BLK_BOUNCE_HIGH);
jsfd_disk[i] = disk;
}
diff --git a/drivers/scsi/bnx2fc/bnx2fc.h b/drivers/scsi/bnx2fc/bnx2fc.h
index 4fc8ed5fe067..1f424e40afdf 100644
--- a/drivers/scsi/bnx2fc/bnx2fc.h
+++ b/drivers/scsi/bnx2fc/bnx2fc.h
@@ -191,6 +191,7 @@ struct bnx2fc_hba {
struct bnx2fc_cmd_mgr *cmd_mgr;
spinlock_t hba_lock;
struct mutex hba_mutex;
+ struct mutex hba_stats_mutex;
unsigned long adapter_state;
#define ADAPTER_STATE_UP 0
#define ADAPTER_STATE_GOING_DOWN 1
diff --git a/drivers/scsi/bnx2fc/bnx2fc_fcoe.c b/drivers/scsi/bnx2fc/bnx2fc_fcoe.c
index 93b5a0012417..902722dc4ce3 100644
--- a/drivers/scsi/bnx2fc/bnx2fc_fcoe.c
+++ b/drivers/scsi/bnx2fc/bnx2fc_fcoe.c
@@ -663,15 +663,17 @@ static struct fc_host_statistics *bnx2fc_get_host_stats(struct Scsi_Host *shost)
if (!fw_stats)
return NULL;
+ mutex_lock(&hba->hba_stats_mutex);
+
bnx2fc_stats = fc_get_host_stats(shost);
init_completion(&hba->stat_req_done);
if (bnx2fc_send_stat_req(hba))
- return bnx2fc_stats;
+ goto unlock_stats_mutex;
rc = wait_for_completion_timeout(&hba->stat_req_done, (2 * HZ));
if (!rc) {
BNX2FC_HBA_DBG(lport, "FW stat req timed out\n");
- return bnx2fc_stats;
+ goto unlock_stats_mutex;
}
BNX2FC_STATS(hba, rx_stat2, fc_crc_cnt);
bnx2fc_stats->invalid_crc_count += hba->bfw_stats.fc_crc_cnt;
@@ -693,6 +695,9 @@ static struct fc_host_statistics *bnx2fc_get_host_stats(struct Scsi_Host *shost)
memcpy(&hba->prev_stats, hba->stats_buffer,
sizeof(struct fcoe_statistics_params));
+
+unlock_stats_mutex:
+ mutex_unlock(&hba->hba_stats_mutex);
return bnx2fc_stats;
}
@@ -1340,6 +1345,7 @@ static struct bnx2fc_hba *bnx2fc_hba_create(struct cnic_dev *cnic)
}
spin_lock_init(&hba->hba_lock);
mutex_init(&hba->hba_mutex);
+ mutex_init(&hba->hba_stats_mutex);
hba->cnic = cnic;
diff --git a/drivers/scsi/csiostor/csio_hw.c b/drivers/scsi/csiostor/csio_hw.c
index 622bdabc8894..dab195f04da7 100644
--- a/drivers/scsi/csiostor/csio_hw.c
+++ b/drivers/scsi/csiostor/csio_hw.c
@@ -1769,7 +1769,6 @@ csio_hw_use_fwconfig(struct csio_hw *hw, int reset, u32 *fw_cfg_param)
goto bye;
}
- mempool_free(mbp, hw->mb_mempool);
if (finicsum != cfcsum) {
csio_warn(hw,
"Config File checksum mismatch: csum=%#x, computed=%#x\n",
@@ -1780,6 +1779,10 @@ csio_hw_use_fwconfig(struct csio_hw *hw, int reset, u32 *fw_cfg_param)
rv = csio_hw_validate_caps(hw, mbp);
if (rv != 0)
goto bye;
+
+ mempool_free(mbp, hw->mb_mempool);
+ mbp = NULL;
+
/*
* Note that we're operating with parameters
* not supplied by the driver, rather than from hard-wired
diff --git a/drivers/scsi/cxgbi/cxgb4i/cxgb4i.c b/drivers/scsi/cxgbi/cxgb4i/cxgb4i.c
index 1076c1578322..0aae094ab91c 100644
--- a/drivers/scsi/cxgbi/cxgb4i/cxgb4i.c
+++ b/drivers/scsi/cxgbi/cxgb4i/cxgb4i.c
@@ -1595,7 +1595,6 @@ static void release_offload_resources(struct cxgbi_sock *csk)
cxgbi_sock_put(csk);
}
csk->dst = NULL;
- csk->cdev = NULL;
}
static int init_act_open(struct cxgbi_sock *csk)
diff --git a/drivers/scsi/cxgbi/libcxgbi.c b/drivers/scsi/cxgbi/libcxgbi.c
index bd7d39ecbd24..e4c83b7c96a8 100644
--- a/drivers/scsi/cxgbi/libcxgbi.c
+++ b/drivers/scsi/cxgbi/libcxgbi.c
@@ -867,7 +867,8 @@ static void need_active_close(struct cxgbi_sock *csk)
log_debug(1 << CXGBI_DBG_SOCK, "csk 0x%p,%u,0x%lx,%u.\n",
csk, (csk)->state, (csk)->flags, (csk)->tid);
spin_lock_bh(&csk->lock);
- dst_confirm(csk->dst);
+ if (csk->dst)
+ dst_confirm(csk->dst);
data_lost = skb_queue_len(&csk->receive_queue);
__skb_queue_purge(&csk->receive_queue);
@@ -882,7 +883,8 @@ static void need_active_close(struct cxgbi_sock *csk)
}
if (close_req) {
- if (data_lost)
+ if (!cxgbi_sock_flag(csk, CTPF_LOGOUT_RSP_RCVD) ||
+ data_lost)
csk->cdev->csk_send_abort_req(csk);
else
csk->cdev->csk_send_close_req(csk);
@@ -1186,9 +1188,10 @@ static int cxgbi_sock_send_pdus(struct cxgbi_sock *csk, struct sk_buff *skb)
cxgbi_ulp_extra_len(cxgbi_skcb_ulp_mode(skb));
skb = next;
}
-done:
+
if (likely(skb_queue_len(&csk->write_queue)))
cdev->csk_push_tx_frames(csk, 1);
+done:
spin_unlock_bh(&csk->lock);
return copied;
@@ -1568,9 +1571,12 @@ static inline int read_pdu_skb(struct iscsi_conn *conn,
}
}
-static int skb_read_pdu_bhs(struct iscsi_conn *conn, struct sk_buff *skb)
+static int
+skb_read_pdu_bhs(struct cxgbi_sock *csk, struct iscsi_conn *conn,
+ struct sk_buff *skb)
{
struct iscsi_tcp_conn *tcp_conn = conn->dd_data;
+ int err;
log_debug(1 << CXGBI_DBG_PDU_RX,
"conn 0x%p, skb 0x%p, len %u, flag 0x%lx.\n",
@@ -1608,7 +1614,16 @@ static int skb_read_pdu_bhs(struct iscsi_conn *conn, struct sk_buff *skb)
}
}
- return read_pdu_skb(conn, skb, 0, 0);
+ err = read_pdu_skb(conn, skb, 0, 0);
+ if (likely(err >= 0)) {
+ struct iscsi_hdr *hdr = (struct iscsi_hdr *)skb->data;
+ u8 opcode = hdr->opcode & ISCSI_OPCODE_MASK;
+
+ if (unlikely(opcode == ISCSI_OP_LOGOUT_RSP))
+ cxgbi_sock_set_flag(csk, CTPF_LOGOUT_RSP_RCVD);
+ }
+
+ return err;
}
static int skb_read_pdu_data(struct iscsi_conn *conn, struct sk_buff *lskb,
@@ -1713,7 +1728,7 @@ void cxgbi_conn_pdu_ready(struct cxgbi_sock *csk)
cxgbi_skcb_rx_pdulen(skb));
if (cxgbi_skcb_test_flag(skb, SKCBF_RX_COALESCED)) {
- err = skb_read_pdu_bhs(conn, skb);
+ err = skb_read_pdu_bhs(csk, conn, skb);
if (err < 0) {
pr_err("coalesced bhs, csk 0x%p, skb 0x%p,%u, "
"f 0x%lx, plen %u.\n",
@@ -1731,7 +1746,7 @@ void cxgbi_conn_pdu_ready(struct cxgbi_sock *csk)
cxgbi_skcb_flags(skb),
cxgbi_skcb_rx_pdulen(skb));
} else {
- err = skb_read_pdu_bhs(conn, skb);
+ err = skb_read_pdu_bhs(csk, conn, skb);
if (err < 0) {
pr_err("bhs, csk 0x%p, skb 0x%p,%u, "
"f 0x%lx, plen %u.\n",
@@ -1873,6 +1888,11 @@ int cxgbi_conn_alloc_pdu(struct iscsi_task *task, u8 opcode)
tcp_task->dd_data = tdata;
task->hdr = NULL;
+ if (tdata->skb) {
+ kfree_skb(tdata->skb);
+ tdata->skb = NULL;
+ }
+
if (SKB_MAX_HEAD(cdev->skb_tx_rsvd) > (512 * MAX_SKB_FRAGS) &&
(opcode == ISCSI_OP_SCSI_DATA_OUT ||
(opcode == ISCSI_OP_SCSI_CMD &&
@@ -1890,6 +1910,7 @@ int cxgbi_conn_alloc_pdu(struct iscsi_task *task, u8 opcode)
return -ENOMEM;
}
+ skb_get(tdata->skb);
skb_reserve(tdata->skb, cdev->skb_tx_rsvd);
task->hdr = (struct iscsi_hdr *)tdata->skb->data;
task->hdr_max = SKB_TX_ISCSI_PDU_HEADER_MAX; /* BHS + AHS */
@@ -2035,9 +2056,9 @@ int cxgbi_conn_xmit_pdu(struct iscsi_task *task)
unsigned int datalen;
int err;
- if (!skb) {
+ if (!skb || cxgbi_skcb_test_flag(skb, SKCBF_TX_DONE)) {
log_debug(1 << CXGBI_DBG_ISCSI | 1 << CXGBI_DBG_PDU_TX,
- "task 0x%p, skb NULL.\n", task);
+ "task 0x%p, skb 0x%p\n", task, skb);
return 0;
}
@@ -2050,7 +2071,6 @@ int cxgbi_conn_xmit_pdu(struct iscsi_task *task)
}
datalen = skb->data_len;
- tdata->skb = NULL;
/* write ppod first if using ofldq to write ppod */
if (ttinfo->flags & CXGBI_PPOD_INFO_FLAG_VALID) {
@@ -2078,6 +2098,7 @@ int cxgbi_conn_xmit_pdu(struct iscsi_task *task)
pdulen += ISCSI_DIGEST_SIZE;
task->conn->txdata_octets += pdulen;
+ cxgbi_skcb_set_flag(skb, SKCBF_TX_DONE);
return 0;
}
@@ -2086,7 +2107,6 @@ int cxgbi_conn_xmit_pdu(struct iscsi_task *task)
"task 0x%p, skb 0x%p, len %u/%u, %d EAGAIN.\n",
task, skb, skb->len, skb->data_len, err);
/* reset skb to send when we are called again */
- tdata->skb = skb;
return err;
}
@@ -2094,7 +2114,8 @@ int cxgbi_conn_xmit_pdu(struct iscsi_task *task)
"itt 0x%x, skb 0x%p, len %u/%u, xmit err %d.\n",
task->itt, skb, skb->len, skb->data_len, err);
- kfree_skb(skb);
+ __kfree_skb(tdata->skb);
+ tdata->skb = NULL;
iscsi_conn_printk(KERN_ERR, task->conn, "xmit err %d.\n", err);
iscsi_conn_failure(task->conn, ISCSI_ERR_XMIT_FAILED);
@@ -2113,8 +2134,10 @@ void cxgbi_cleanup_task(struct iscsi_task *task)
tcp_task->dd_data = NULL;
/* never reached the xmit task callout */
- if (tdata->skb)
- __kfree_skb(tdata->skb);
+ if (tdata->skb) {
+ kfree_skb(tdata->skb);
+ tdata->skb = NULL;
+ }
task_release_itt(task, task->hdr_itt);
memset(tdata, 0, sizeof(*tdata));
@@ -2714,6 +2737,9 @@ EXPORT_SYMBOL_GPL(cxgbi_attr_is_visible);
static int __init libcxgbi_init_module(void)
{
pr_info("%s", version);
+
+ BUILD_BUG_ON(FIELD_SIZEOF(struct sk_buff, cb) <
+ sizeof(struct cxgbi_skb_cb));
return 0;
}
diff --git a/drivers/scsi/cxgbi/libcxgbi.h b/drivers/scsi/cxgbi/libcxgbi.h
index 18e0ea83d361..37f07aaab1e4 100644
--- a/drivers/scsi/cxgbi/libcxgbi.h
+++ b/drivers/scsi/cxgbi/libcxgbi.h
@@ -187,6 +187,7 @@ enum cxgbi_sock_flags {
CTPF_HAS_ATID, /* reserved atid */
CTPF_HAS_TID, /* reserved hw tid */
CTPF_OFFLOAD_DOWN, /* offload function off */
+ CTPF_LOGOUT_RSP_RCVD, /* received logout response */
};
struct cxgbi_skb_rx_cb {
@@ -195,7 +196,8 @@ struct cxgbi_skb_rx_cb {
};
struct cxgbi_skb_tx_cb {
- void *l2t;
+ void *handle;
+ void *arp_err_handler;
struct sk_buff *wr_next;
};
@@ -203,6 +205,7 @@ enum cxgbi_skcb_flags {
SKCBF_TX_NEED_HDR, /* packet needs a header */
SKCBF_TX_MEM_WRITE, /* memory write */
SKCBF_TX_FLAG_COMPL, /* wr completion flag */
+ SKCBF_TX_DONE, /* skb tx done */
SKCBF_RX_COALESCED, /* received whole pdu */
SKCBF_RX_HDR, /* received pdu header */
SKCBF_RX_DATA, /* received pdu payload */
@@ -215,13 +218,13 @@ enum cxgbi_skcb_flags {
};
struct cxgbi_skb_cb {
- unsigned char ulp_mode;
- unsigned long flags;
- unsigned int seq;
union {
struct cxgbi_skb_rx_cb rx;
struct cxgbi_skb_tx_cb tx;
};
+ unsigned char ulp_mode;
+ unsigned long flags;
+ unsigned int seq;
};
#define CXGBI_SKB_CB(skb) ((struct cxgbi_skb_cb *)&((skb)->cb[0]))
@@ -374,11 +377,9 @@ static inline void cxgbi_sock_enqueue_wr(struct cxgbi_sock *csk,
cxgbi_skcb_tx_wr_next(skb) = NULL;
/*
* We want to take an extra reference since both us and the driver
- * need to free the packet before it's really freed. We know there's
- * just one user currently so we use atomic_set rather than skb_get
- * to avoid the atomic op.
+ * need to free the packet before it's really freed.
*/
- atomic_set(&skb->users, 2);
+ skb_get(skb);
if (!csk->wr_pending_head)
csk->wr_pending_head = skb;
diff --git a/drivers/scsi/device_handler/scsi_dh_rdac.c b/drivers/scsi/device_handler/scsi_dh_rdac.c
index 3cbab8710e58..2ceff585f189 100644
--- a/drivers/scsi/device_handler/scsi_dh_rdac.c
+++ b/drivers/scsi/device_handler/scsi_dh_rdac.c
@@ -265,18 +265,16 @@ static unsigned int rdac_failover_get(struct rdac_controller *ctlr,
struct list_head *list,
unsigned char *cdb)
{
- struct scsi_device *sdev = ctlr->ms_sdev;
- struct rdac_dh_data *h = sdev->handler_data;
struct rdac_mode_common *common;
unsigned data_size;
struct rdac_queue_data *qdata;
u8 *lun_table;
- if (h->ctlr->use_ms10) {
+ if (ctlr->use_ms10) {
struct rdac_pg_expanded *rdac_pg;
data_size = sizeof(struct rdac_pg_expanded);
- rdac_pg = &h->ctlr->mode_select.expanded;
+ rdac_pg = &ctlr->mode_select.expanded;
memset(rdac_pg, 0, data_size);
common = &rdac_pg->common;
rdac_pg->page_code = RDAC_PAGE_CODE_REDUNDANT_CONTROLLER + 0x40;
@@ -288,7 +286,7 @@ static unsigned int rdac_failover_get(struct rdac_controller *ctlr,
struct rdac_pg_legacy *rdac_pg;
data_size = sizeof(struct rdac_pg_legacy);
- rdac_pg = &h->ctlr->mode_select.legacy;
+ rdac_pg = &ctlr->mode_select.legacy;
memset(rdac_pg, 0, data_size);
common = &rdac_pg->common;
rdac_pg->page_code = RDAC_PAGE_CODE_REDUNDANT_CONTROLLER;
@@ -304,7 +302,7 @@ static unsigned int rdac_failover_get(struct rdac_controller *ctlr,
}
/* Prepare the command. */
- if (h->ctlr->use_ms10) {
+ if (ctlr->use_ms10) {
cdb[0] = MODE_SELECT_10;
cdb[7] = data_size >> 8;
cdb[8] = data_size & 0xff;
diff --git a/drivers/scsi/dpt/dpti_i2o.h b/drivers/scsi/dpt/dpti_i2o.h
index bd9e31e16249..16fc380b5512 100644
--- a/drivers/scsi/dpt/dpti_i2o.h
+++ b/drivers/scsi/dpt/dpti_i2o.h
@@ -48,7 +48,7 @@
#include <linux/wait.h>
typedef wait_queue_head_t adpt_wait_queue_head_t;
#define ADPT_DECLARE_WAIT_QUEUE_HEAD(wait) DECLARE_WAIT_QUEUE_HEAD_ONSTACK(wait)
-typedef wait_queue_t adpt_wait_queue_t;
+typedef wait_queue_entry_t adpt_wait_queue_entry_t;
/*
* message structures
diff --git a/drivers/scsi/ibmvscsi_tgt/ibmvscsi_tgt.c b/drivers/scsi/ibmvscsi_tgt/ibmvscsi_tgt.c
index b480878e3258..659ab483d716 100644
--- a/drivers/scsi/ibmvscsi_tgt/ibmvscsi_tgt.c
+++ b/drivers/scsi/ibmvscsi_tgt/ibmvscsi_tgt.c
@@ -1170,6 +1170,8 @@ static struct ibmvscsis_cmd *ibmvscsis_get_free_cmd(struct scsi_info *vscsi)
cmd = list_first_entry_or_null(&vscsi->free_cmd,
struct ibmvscsis_cmd, list);
if (cmd) {
+ if (cmd->abort_cmd)
+ cmd->abort_cmd = NULL;
cmd->flags &= ~(DELAY_SEND);
list_del(&cmd->list);
cmd->iue = iue;
@@ -1774,6 +1776,7 @@ static void ibmvscsis_send_messages(struct scsi_info *vscsi)
if (cmd->abort_cmd) {
retry = true;
cmd->abort_cmd->flags &= ~(DELAY_SEND);
+ cmd->abort_cmd = NULL;
}
/*
@@ -1788,6 +1791,25 @@ static void ibmvscsis_send_messages(struct scsi_info *vscsi)
list_del(&cmd->list);
ibmvscsis_free_cmd_resources(vscsi,
cmd);
+ /*
+ * With a successfully aborted op
+ * through LIO we want to increment the
+ * the vscsi credit so that when we dont
+ * send a rsp to the original scsi abort
+ * op (h_send_crq), but the tm rsp to
+ * the abort is sent, the credit is
+ * correctly sent with the abort tm rsp.
+ * We would need 1 for the abort tm rsp
+ * and 1 credit for the aborted scsi op.
+ * Thus we need to increment here.
+ * Also we want to increment the credit
+ * here because we want to make sure
+ * cmd is actually released first
+ * otherwise the client will think it
+ * it can send a new cmd, and we could
+ * find ourselves short of cmd elements.
+ */
+ vscsi->credit += 1;
} else {
iue = cmd->iue;
@@ -2962,10 +2984,7 @@ static long srp_build_response(struct scsi_info *vscsi,
rsp->opcode = SRP_RSP;
- if (vscsi->credit > 0 && vscsi->state == SRP_PROCESSING)
- rsp->req_lim_delta = cpu_to_be32(vscsi->credit);
- else
- rsp->req_lim_delta = cpu_to_be32(1 + vscsi->credit);
+ rsp->req_lim_delta = cpu_to_be32(1 + vscsi->credit);
rsp->tag = cmd->rsp.tag;
rsp->flags = 0;
diff --git a/drivers/scsi/ips.c b/drivers/scsi/ips.c
index 3419e1bcdff6..67621308eb9c 100644
--- a/drivers/scsi/ips.c
+++ b/drivers/scsi/ips.c
@@ -301,13 +301,13 @@ static uint32_t ips_statupd_copperhead_memio(ips_ha_t *);
static uint32_t ips_statupd_morpheus(ips_ha_t *);
static ips_scb_t *ips_getscb(ips_ha_t *);
static void ips_putq_scb_head(ips_scb_queue_t *, ips_scb_t *);
-static void ips_putq_wait_tail(ips_wait_queue_t *, struct scsi_cmnd *);
+static void ips_putq_wait_tail(ips_wait_queue_entry_t *, struct scsi_cmnd *);
static void ips_putq_copp_tail(ips_copp_queue_t *,
ips_copp_wait_item_t *);
static ips_scb_t *ips_removeq_scb_head(ips_scb_queue_t *);
static ips_scb_t *ips_removeq_scb(ips_scb_queue_t *, ips_scb_t *);
-static struct scsi_cmnd *ips_removeq_wait_head(ips_wait_queue_t *);
-static struct scsi_cmnd *ips_removeq_wait(ips_wait_queue_t *,
+static struct scsi_cmnd *ips_removeq_wait_head(ips_wait_queue_entry_t *);
+static struct scsi_cmnd *ips_removeq_wait(ips_wait_queue_entry_t *,
struct scsi_cmnd *);
static ips_copp_wait_item_t *ips_removeq_copp(ips_copp_queue_t *,
ips_copp_wait_item_t *);
@@ -2871,7 +2871,7 @@ ips_removeq_scb(ips_scb_queue_t * queue, ips_scb_t * item)
/* ASSUMED to be called from within the HA lock */
/* */
/****************************************************************************/
-static void ips_putq_wait_tail(ips_wait_queue_t *queue, struct scsi_cmnd *item)
+static void ips_putq_wait_tail(ips_wait_queue_entry_t *queue, struct scsi_cmnd *item)
{
METHOD_TRACE("ips_putq_wait_tail", 1);
@@ -2902,7 +2902,7 @@ static void ips_putq_wait_tail(ips_wait_queue_t *queue, struct scsi_cmnd *item)
/* ASSUMED to be called from within the HA lock */
/* */
/****************************************************************************/
-static struct scsi_cmnd *ips_removeq_wait_head(ips_wait_queue_t *queue)
+static struct scsi_cmnd *ips_removeq_wait_head(ips_wait_queue_entry_t *queue)
{
struct scsi_cmnd *item;
@@ -2936,7 +2936,7 @@ static struct scsi_cmnd *ips_removeq_wait_head(ips_wait_queue_t *queue)
/* ASSUMED to be called from within the HA lock */
/* */
/****************************************************************************/
-static struct scsi_cmnd *ips_removeq_wait(ips_wait_queue_t *queue,
+static struct scsi_cmnd *ips_removeq_wait(ips_wait_queue_entry_t *queue,
struct scsi_cmnd *item)
{
struct scsi_cmnd *p;
diff --git a/drivers/scsi/ips.h b/drivers/scsi/ips.h
index b782bb60baf0..366be3b2f9b4 100644
--- a/drivers/scsi/ips.h
+++ b/drivers/scsi/ips.h
@@ -989,7 +989,7 @@ typedef struct ips_wait_queue {
struct scsi_cmnd *head;
struct scsi_cmnd *tail;
int count;
-} ips_wait_queue_t;
+} ips_wait_queue_entry_t;
typedef struct ips_copp_wait_item {
struct scsi_cmnd *scsi_cmd;
@@ -1035,7 +1035,7 @@ typedef struct ips_ha {
ips_stat_t sp; /* Status packer pointer */
struct ips_scb *scbs; /* Array of all CCBS */
struct ips_scb *scb_freelist; /* SCB free list */
- ips_wait_queue_t scb_waitlist; /* Pending SCB list */
+ ips_wait_queue_entry_t scb_waitlist; /* Pending SCB list */
ips_copp_queue_t copp_waitlist; /* Pending PT list */
ips_scb_queue_t scb_activelist; /* Active SCB list */
IPS_IO_CMD *dummy; /* dummy command */
diff --git a/drivers/scsi/libfc/fc_rport.c b/drivers/scsi/libfc/fc_rport.c
index b44c3136eb51..520325867e2b 100644
--- a/drivers/scsi/libfc/fc_rport.c
+++ b/drivers/scsi/libfc/fc_rport.c
@@ -1422,7 +1422,7 @@ static void fc_rport_recv_rtv_req(struct fc_rport_priv *rdata,
fp = fc_frame_alloc(lport, sizeof(*rtv));
if (!fp) {
rjt_data.reason = ELS_RJT_UNAB;
- rjt_data.reason = ELS_EXPL_INSUF_RES;
+ rjt_data.explan = ELS_EXPL_INSUF_RES;
fc_seq_els_rsp_send(in_fp, ELS_LS_RJT, &rjt_data);
goto drop;
}
diff --git a/drivers/scsi/lpfc/lpfc.h b/drivers/scsi/lpfc/lpfc.h
index 6d7840b096e6..f2c0ba6ced78 100644
--- a/drivers/scsi/lpfc/lpfc.h
+++ b/drivers/scsi/lpfc/lpfc.h
@@ -141,6 +141,13 @@ struct lpfc_dmabuf {
uint32_t buffer_tag; /* used for tagged queue ring */
};
+struct lpfc_nvmet_ctxbuf {
+ struct list_head list;
+ struct lpfc_nvmet_rcv_ctx *context;
+ struct lpfc_iocbq *iocbq;
+ struct lpfc_sglq *sglq;
+};
+
struct lpfc_dma_pool {
struct lpfc_dmabuf *elements;
uint32_t max_count;
@@ -163,9 +170,7 @@ struct rqb_dmabuf {
struct lpfc_dmabuf dbuf;
uint16_t total_size;
uint16_t bytes_recv;
- void *context;
- struct lpfc_iocbq *iocbq;
- struct lpfc_sglq *sglq;
+ uint16_t idx;
struct lpfc_queue *hrq; /* ptr to associated Header RQ */
struct lpfc_queue *drq; /* ptr to associated Data RQ */
};
@@ -670,6 +675,8 @@ struct lpfc_hba {
/* INIT_LINK mailbox command */
#define LS_NPIV_FAB_SUPPORTED 0x2 /* Fabric supports NPIV */
#define LS_IGNORE_ERATT 0x4 /* intr handler should ignore ERATT */
+#define LS_MDS_LINK_DOWN 0x8 /* MDS Diagnostics Link Down */
+#define LS_MDS_LOOPBACK 0x16 /* MDS Diagnostics Link Up (Loopback) */
uint32_t hba_flag; /* hba generic flags */
#define HBA_ERATT_HANDLED 0x1 /* This flag is set when eratt handled */
@@ -777,7 +784,6 @@ struct lpfc_hba {
uint32_t cfg_nvme_oas;
uint32_t cfg_nvme_io_channel;
uint32_t cfg_nvmet_mrq;
- uint32_t cfg_nvmet_mrq_post;
uint32_t cfg_enable_nvmet;
uint32_t cfg_nvme_enable_fb;
uint32_t cfg_nvmet_fb_size;
@@ -943,6 +949,7 @@ struct lpfc_hba {
struct pci_pool *lpfc_mbuf_pool;
struct pci_pool *lpfc_hrb_pool; /* header receive buffer pool */
struct pci_pool *lpfc_drb_pool; /* data receive buffer pool */
+ struct pci_pool *lpfc_nvmet_drb_pool; /* data receive buffer pool */
struct pci_pool *lpfc_hbq_pool; /* SLI3 hbq buffer pool */
struct pci_pool *txrdy_payload_pool;
struct lpfc_dma_pool lpfc_mbuf_safety_pool;
@@ -1228,7 +1235,11 @@ lpfc_sli_read_hs(struct lpfc_hba *phba)
static inline struct lpfc_sli_ring *
lpfc_phba_elsring(struct lpfc_hba *phba)
{
- if (phba->sli_rev == LPFC_SLI_REV4)
- return phba->sli4_hba.els_wq->pring;
+ if (phba->sli_rev == LPFC_SLI_REV4) {
+ if (phba->sli4_hba.els_wq)
+ return phba->sli4_hba.els_wq->pring;
+ else
+ return NULL;
+ }
return &phba->sli.sli3_ring[LPFC_ELS_RING];
}
diff --git a/drivers/scsi/lpfc/lpfc_attr.c b/drivers/scsi/lpfc/lpfc_attr.c
index 4830370bfab1..bb2d9e238225 100644
--- a/drivers/scsi/lpfc/lpfc_attr.c
+++ b/drivers/scsi/lpfc/lpfc_attr.c
@@ -60,9 +60,9 @@
#define LPFC_MIN_DEVLOSS_TMO 1
#define LPFC_MAX_DEVLOSS_TMO 255
-#define LPFC_DEF_MRQ_POST 256
-#define LPFC_MIN_MRQ_POST 32
-#define LPFC_MAX_MRQ_POST 512
+#define LPFC_DEF_MRQ_POST 512
+#define LPFC_MIN_MRQ_POST 512
+#define LPFC_MAX_MRQ_POST 2048
/*
* Write key size should be multiple of 4. If write key is changed
@@ -205,8 +205,9 @@ lpfc_nvme_info_show(struct device *dev, struct device_attribute *attr,
atomic_read(&tgtp->xmt_ls_rsp_error));
len += snprintf(buf+len, PAGE_SIZE-len,
- "FCP: Rcv %08x Drop %08x\n",
+ "FCP: Rcv %08x Release %08x Drop %08x\n",
atomic_read(&tgtp->rcv_fcp_cmd_in),
+ atomic_read(&tgtp->xmt_fcp_release),
atomic_read(&tgtp->rcv_fcp_cmd_drop));
if (atomic_read(&tgtp->rcv_fcp_cmd_in) !=
@@ -218,15 +219,12 @@ lpfc_nvme_info_show(struct device *dev, struct device_attribute *attr,
}
len += snprintf(buf+len, PAGE_SIZE-len,
- "FCP Rsp: RD %08x rsp %08x WR %08x rsp %08x\n",
+ "FCP Rsp: RD %08x rsp %08x WR %08x rsp %08x "
+ "drop %08x\n",
atomic_read(&tgtp->xmt_fcp_read),
atomic_read(&tgtp->xmt_fcp_read_rsp),
atomic_read(&tgtp->xmt_fcp_write),
- atomic_read(&tgtp->xmt_fcp_rsp));
-
- len += snprintf(buf+len, PAGE_SIZE-len,
- "FCP Rsp: abort %08x drop %08x\n",
- atomic_read(&tgtp->xmt_fcp_abort),
+ atomic_read(&tgtp->xmt_fcp_rsp),
atomic_read(&tgtp->xmt_fcp_drop));
len += snprintf(buf+len, PAGE_SIZE-len,
@@ -236,10 +234,22 @@ lpfc_nvme_info_show(struct device *dev, struct device_attribute *attr,
atomic_read(&tgtp->xmt_fcp_rsp_drop));
len += snprintf(buf+len, PAGE_SIZE-len,
- "ABORT: Xmt %08x Err %08x Cmpl %08x",
+ "ABORT: Xmt %08x Cmpl %08x\n",
+ atomic_read(&tgtp->xmt_fcp_abort),
+ atomic_read(&tgtp->xmt_fcp_abort_cmpl));
+
+ len += snprintf(buf + len, PAGE_SIZE - len,
+ "ABORT: Sol %08x Usol %08x Err %08x Cmpl %08x",
+ atomic_read(&tgtp->xmt_abort_sol),
+ atomic_read(&tgtp->xmt_abort_unsol),
atomic_read(&tgtp->xmt_abort_rsp),
- atomic_read(&tgtp->xmt_abort_rsp_error),
- atomic_read(&tgtp->xmt_abort_cmpl));
+ atomic_read(&tgtp->xmt_abort_rsp_error));
+
+ len += snprintf(buf + len, PAGE_SIZE - len,
+ "IO_CTX: %08x outstanding %08x total %x",
+ phba->sli4_hba.nvmet_ctx_cnt,
+ phba->sli4_hba.nvmet_io_wait_cnt,
+ phba->sli4_hba.nvmet_io_wait_total);
len += snprintf(buf+len, PAGE_SIZE-len, "\n");
return len;
@@ -3312,14 +3322,6 @@ LPFC_ATTR_R(nvmet_mrq,
"Specify number of RQ pairs for processing NVMET cmds");
/*
- * lpfc_nvmet_mrq_post: Specify number buffers to post on every MRQ
- *
- */
-LPFC_ATTR_R(nvmet_mrq_post, LPFC_DEF_MRQ_POST,
- LPFC_MIN_MRQ_POST, LPFC_MAX_MRQ_POST,
- "Specify number of buffers to post on every MRQ");
-
-/*
* lpfc_enable_fc4_type: Defines what FC4 types are supported.
* Supported Values: 1 - register just FCP
* 3 - register both FCP and NVME
@@ -5154,7 +5156,6 @@ struct device_attribute *lpfc_hba_attrs[] = {
&dev_attr_lpfc_suppress_rsp,
&dev_attr_lpfc_nvme_io_channel,
&dev_attr_lpfc_nvmet_mrq,
- &dev_attr_lpfc_nvmet_mrq_post,
&dev_attr_lpfc_nvme_enable_fb,
&dev_attr_lpfc_nvmet_fb_size,
&dev_attr_lpfc_enable_bg,
@@ -6194,7 +6195,6 @@ lpfc_get_cfgparam(struct lpfc_hba *phba)
lpfc_enable_fc4_type_init(phba, lpfc_enable_fc4_type);
lpfc_nvmet_mrq_init(phba, lpfc_nvmet_mrq);
- lpfc_nvmet_mrq_post_init(phba, lpfc_nvmet_mrq_post);
/* Initialize first burst. Target vs Initiator are different. */
lpfc_nvme_enable_fb_init(phba, lpfc_nvme_enable_fb);
@@ -6291,7 +6291,6 @@ lpfc_nvme_mod_param_dep(struct lpfc_hba *phba)
/* Not NVME Target mode. Turn off Target parameters. */
phba->nvmet_support = 0;
phba->cfg_nvmet_mrq = 0;
- phba->cfg_nvmet_mrq_post = 0;
phba->cfg_nvmet_fb_size = 0;
}
diff --git a/drivers/scsi/lpfc/lpfc_crtn.h b/drivers/scsi/lpfc/lpfc_crtn.h
index 1c55408ac718..da669dce12fe 100644
--- a/drivers/scsi/lpfc/lpfc_crtn.h
+++ b/drivers/scsi/lpfc/lpfc_crtn.h
@@ -75,6 +75,10 @@ void lpfc_init_vpi_cmpl(struct lpfc_hba *, LPFC_MBOXQ_t *);
void lpfc_cancel_all_vport_retry_delay_timer(struct lpfc_hba *);
void lpfc_retry_pport_discovery(struct lpfc_hba *);
void lpfc_release_rpi(struct lpfc_hba *, struct lpfc_vport *, uint16_t);
+int lpfc_init_iocb_list(struct lpfc_hba *phba, int cnt);
+void lpfc_free_iocb_list(struct lpfc_hba *phba);
+int lpfc_post_rq_buffer(struct lpfc_hba *phba, struct lpfc_queue *hrq,
+ struct lpfc_queue *drq, int count, int idx);
void lpfc_mbx_cmpl_local_config_link(struct lpfc_hba *, LPFC_MBOXQ_t *);
void lpfc_mbx_cmpl_reg_login(struct lpfc_hba *, LPFC_MBOXQ_t *);
@@ -123,7 +127,7 @@ int lpfc_disc_state_machine(struct lpfc_vport *, struct lpfc_nodelist *, void *,
void lpfc_do_scr_ns_plogi(struct lpfc_hba *, struct lpfc_vport *);
int lpfc_check_sparm(struct lpfc_vport *, struct lpfc_nodelist *,
struct serv_parm *, uint32_t, int);
-int lpfc_els_abort(struct lpfc_hba *, struct lpfc_nodelist *);
+void lpfc_els_abort(struct lpfc_hba *, struct lpfc_nodelist *);
void lpfc_more_plogi(struct lpfc_vport *);
void lpfc_more_adisc(struct lpfc_vport *);
void lpfc_end_rscn(struct lpfc_vport *);
@@ -246,16 +250,14 @@ struct hbq_dmabuf *lpfc_sli4_rb_alloc(struct lpfc_hba *);
void lpfc_sli4_rb_free(struct lpfc_hba *, struct hbq_dmabuf *);
struct rqb_dmabuf *lpfc_sli4_nvmet_alloc(struct lpfc_hba *phba);
void lpfc_sli4_nvmet_free(struct lpfc_hba *phba, struct rqb_dmabuf *dmab);
-void lpfc_nvmet_rq_post(struct lpfc_hba *phba, struct lpfc_nvmet_rcv_ctx *ctxp,
- struct lpfc_dmabuf *mp);
+void lpfc_nvmet_ctxbuf_post(struct lpfc_hba *phba,
+ struct lpfc_nvmet_ctxbuf *ctxp);
int lpfc_nvmet_rcv_unsol_abort(struct lpfc_vport *vport,
struct fc_frame_header *fc_hdr);
void lpfc_sli4_build_dflt_fcf_record(struct lpfc_hba *, struct fcf_record *,
uint16_t);
int lpfc_sli4_rq_put(struct lpfc_queue *hq, struct lpfc_queue *dq,
struct lpfc_rqe *hrqe, struct lpfc_rqe *drqe);
-int lpfc_post_rq_buffer(struct lpfc_hba *phba, struct lpfc_queue *hq,
- struct lpfc_queue *dq, int count);
int lpfc_free_rq_buffer(struct lpfc_hba *phba, struct lpfc_queue *hq);
void lpfc_unregister_fcf(struct lpfc_hba *);
void lpfc_unregister_fcf_rescan(struct lpfc_hba *);
@@ -271,6 +273,7 @@ int lpfc_sli4_fcf_rr_next_proc(struct lpfc_vport *, uint16_t);
void lpfc_sli4_clear_fcf_rr_bmask(struct lpfc_hba *);
int lpfc_mem_alloc(struct lpfc_hba *, int align);
+int lpfc_nvmet_mem_alloc(struct lpfc_hba *phba);
int lpfc_mem_alloc_active_rrq_pool_s4(struct lpfc_hba *);
void lpfc_mem_free(struct lpfc_hba *);
void lpfc_mem_free_all(struct lpfc_hba *);
diff --git a/drivers/scsi/lpfc/lpfc_ct.c b/drivers/scsi/lpfc/lpfc_ct.c
index c7962dae4dab..24ce96dcc94d 100644
--- a/drivers/scsi/lpfc/lpfc_ct.c
+++ b/drivers/scsi/lpfc/lpfc_ct.c
@@ -978,9 +978,10 @@ lpfc_cmpl_ct_cmd_gft_id(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
ndlp, did, ndlp->nlp_fc4_type,
FC_TYPE_FCP, FC_TYPE_NVME);
ndlp->nlp_prev_state = NLP_STE_REG_LOGIN_ISSUE;
+
+ lpfc_nlp_set_state(vport, ndlp, NLP_STE_PRLI_ISSUE);
+ lpfc_issue_els_prli(vport, ndlp, 0);
}
- lpfc_nlp_set_state(vport, ndlp, NLP_STE_PRLI_ISSUE);
- lpfc_issue_els_prli(vport, ndlp, 0);
} else
lpfc_printf_vlog(vport, KERN_ERR, LOG_DISCOVERY,
"3065 GFT_ID failed x%08x\n", irsp->ulpStatus);
@@ -2092,6 +2093,7 @@ lpfc_fdmi_port_attr_fc4type(struct lpfc_vport *vport,
ae->un.AttrTypes[3] = 0x02; /* Type 1 - ELS */
ae->un.AttrTypes[2] = 0x01; /* Type 8 - FCP */
+ ae->un.AttrTypes[6] = 0x01; /* Type 40 - NVME */
ae->un.AttrTypes[7] = 0x01; /* Type 32 - CT */
size = FOURBYTES + 32;
ad->AttrLen = cpu_to_be16(size);
diff --git a/drivers/scsi/lpfc/lpfc_debugfs.c b/drivers/scsi/lpfc/lpfc_debugfs.c
index fce549a91911..4bcb92c844ca 100644
--- a/drivers/scsi/lpfc/lpfc_debugfs.c
+++ b/drivers/scsi/lpfc/lpfc_debugfs.c
@@ -798,21 +798,22 @@ lpfc_debugfs_nvmestat_data(struct lpfc_vport *vport, char *buf, int size)
atomic_read(&tgtp->xmt_fcp_rsp));
len += snprintf(buf + len, size - len,
- "FCP Rsp: abort %08x drop %08x\n",
- atomic_read(&tgtp->xmt_fcp_abort),
- atomic_read(&tgtp->xmt_fcp_drop));
-
- len += snprintf(buf + len, size - len,
"FCP Rsp Cmpl: %08x err %08x drop %08x\n",
atomic_read(&tgtp->xmt_fcp_rsp_cmpl),
atomic_read(&tgtp->xmt_fcp_rsp_error),
atomic_read(&tgtp->xmt_fcp_rsp_drop));
len += snprintf(buf + len, size - len,
- "ABORT: Xmt %08x Err %08x Cmpl %08x",
+ "ABORT: Xmt %08x Cmpl %08x\n",
+ atomic_read(&tgtp->xmt_fcp_abort),
+ atomic_read(&tgtp->xmt_fcp_abort_cmpl));
+
+ len += snprintf(buf + len, size - len,
+ "ABORT: Sol %08x Usol %08x Err %08x Cmpl %08x",
+ atomic_read(&tgtp->xmt_abort_sol),
+ atomic_read(&tgtp->xmt_abort_unsol),
atomic_read(&tgtp->xmt_abort_rsp),
- atomic_read(&tgtp->xmt_abort_rsp_error),
- atomic_read(&tgtp->xmt_abort_cmpl));
+ atomic_read(&tgtp->xmt_abort_rsp_error));
len += snprintf(buf + len, size - len, "\n");
@@ -841,6 +842,12 @@ lpfc_debugfs_nvmestat_data(struct lpfc_vport *vport, char *buf, int size)
}
spin_unlock(&phba->sli4_hba.abts_nvme_buf_list_lock);
}
+
+ len += snprintf(buf + len, size - len,
+ "IO_CTX: %08x outstanding %08x total %08x\n",
+ phba->sli4_hba.nvmet_ctx_cnt,
+ phba->sli4_hba.nvmet_io_wait_cnt,
+ phba->sli4_hba.nvmet_io_wait_total);
} else {
if (!(phba->cfg_enable_fc4_type & LPFC_ENABLE_NVME))
return len;
@@ -1959,6 +1966,7 @@ lpfc_debugfs_nvmestat_write(struct file *file, const char __user *buf,
atomic_set(&tgtp->rcv_ls_req_out, 0);
atomic_set(&tgtp->rcv_ls_req_drop, 0);
atomic_set(&tgtp->xmt_ls_abort, 0);
+ atomic_set(&tgtp->xmt_ls_abort_cmpl, 0);
atomic_set(&tgtp->xmt_ls_rsp, 0);
atomic_set(&tgtp->xmt_ls_drop, 0);
atomic_set(&tgtp->xmt_ls_rsp_error, 0);
@@ -1967,19 +1975,22 @@ lpfc_debugfs_nvmestat_write(struct file *file, const char __user *buf,
atomic_set(&tgtp->rcv_fcp_cmd_in, 0);
atomic_set(&tgtp->rcv_fcp_cmd_out, 0);
atomic_set(&tgtp->rcv_fcp_cmd_drop, 0);
- atomic_set(&tgtp->xmt_fcp_abort, 0);
atomic_set(&tgtp->xmt_fcp_drop, 0);
atomic_set(&tgtp->xmt_fcp_read_rsp, 0);
atomic_set(&tgtp->xmt_fcp_read, 0);
atomic_set(&tgtp->xmt_fcp_write, 0);
atomic_set(&tgtp->xmt_fcp_rsp, 0);
+ atomic_set(&tgtp->xmt_fcp_release, 0);
atomic_set(&tgtp->xmt_fcp_rsp_cmpl, 0);
atomic_set(&tgtp->xmt_fcp_rsp_error, 0);
atomic_set(&tgtp->xmt_fcp_rsp_drop, 0);
+ atomic_set(&tgtp->xmt_fcp_abort, 0);
+ atomic_set(&tgtp->xmt_fcp_abort_cmpl, 0);
+ atomic_set(&tgtp->xmt_abort_sol, 0);
+ atomic_set(&tgtp->xmt_abort_unsol, 0);
atomic_set(&tgtp->xmt_abort_rsp, 0);
atomic_set(&tgtp->xmt_abort_rsp_error, 0);
- atomic_set(&tgtp->xmt_abort_cmpl, 0);
}
return nbytes;
}
@@ -3070,11 +3081,11 @@ __lpfc_idiag_print_wq(struct lpfc_queue *qp, char *wqtype,
qp->assoc_qid, qp->q_cnt_1,
(unsigned long long)qp->q_cnt_4);
len += snprintf(pbuffer + len, LPFC_QUE_INFO_GET_BUF_SIZE - len,
- "\t\tWQID[%02d], QE-CNT[%04d], QE-SIZE[%04d], "
- "HOST-IDX[%04d], PORT-IDX[%04d]",
+ "\t\tWQID[%02d], QE-CNT[%04d], QE-SZ[%04d], "
+ "HST-IDX[%04d], PRT-IDX[%04d], PST[%03d]",
qp->queue_id, qp->entry_count,
qp->entry_size, qp->host_index,
- qp->hba_index);
+ qp->hba_index, qp->entry_repost);
len += snprintf(pbuffer + len,
LPFC_QUE_INFO_GET_BUF_SIZE - len, "\n");
return len;
@@ -3121,11 +3132,11 @@ __lpfc_idiag_print_cq(struct lpfc_queue *qp, char *cqtype,
qp->assoc_qid, qp->q_cnt_1, qp->q_cnt_2,
qp->q_cnt_3, (unsigned long long)qp->q_cnt_4);
len += snprintf(pbuffer + len, LPFC_QUE_INFO_GET_BUF_SIZE - len,
- "\tCQID[%02d], QE-CNT[%04d], QE-SIZE[%04d], "
- "HOST-IDX[%04d], PORT-IDX[%04d]",
+ "\tCQID[%02d], QE-CNT[%04d], QE-SZ[%04d], "
+ "HST-IDX[%04d], PRT-IDX[%04d], PST[%03d]",
qp->queue_id, qp->entry_count,
qp->entry_size, qp->host_index,
- qp->hba_index);
+ qp->hba_index, qp->entry_repost);
len += snprintf(pbuffer + len, LPFC_QUE_INFO_GET_BUF_SIZE - len, "\n");
@@ -3143,20 +3154,20 @@ __lpfc_idiag_print_rqpair(struct lpfc_queue *qp, struct lpfc_queue *datqp,
"\t\t%s RQ info: ", rqtype);
len += snprintf(pbuffer + len, LPFC_QUE_INFO_GET_BUF_SIZE - len,
"AssocCQID[%02d]: RQ-STAT[nopost:x%x nobuf:x%x "
- "trunc:x%x rcv:x%llx]\n",
+ "posted:x%x rcv:x%llx]\n",
qp->assoc_qid, qp->q_cnt_1, qp->q_cnt_2,
qp->q_cnt_3, (unsigned long long)qp->q_cnt_4);
len += snprintf(pbuffer + len, LPFC_QUE_INFO_GET_BUF_SIZE - len,
- "\t\tHQID[%02d], QE-CNT[%04d], QE-SIZE[%04d], "
- "HOST-IDX[%04d], PORT-IDX[%04d]\n",
+ "\t\tHQID[%02d], QE-CNT[%04d], QE-SZ[%04d], "
+ "HST-IDX[%04d], PRT-IDX[%04d], PST[%03d]\n",
qp->queue_id, qp->entry_count, qp->entry_size,
- qp->host_index, qp->hba_index);
+ qp->host_index, qp->hba_index, qp->entry_repost);
len += snprintf(pbuffer + len, LPFC_QUE_INFO_GET_BUF_SIZE - len,
- "\t\tDQID[%02d], QE-CNT[%04d], QE-SIZE[%04d], "
- "HOST-IDX[%04d], PORT-IDX[%04d]\n",
+ "\t\tDQID[%02d], QE-CNT[%04d], QE-SZ[%04d], "
+ "HST-IDX[%04d], PRT-IDX[%04d], PST[%03d]\n",
datqp->queue_id, datqp->entry_count,
datqp->entry_size, datqp->host_index,
- datqp->hba_index);
+ datqp->hba_index, datqp->entry_repost);
return len;
}
@@ -3242,10 +3253,10 @@ __lpfc_idiag_print_eq(struct lpfc_queue *qp, char *eqtype,
eqtype, qp->q_cnt_1, qp->q_cnt_2, qp->q_cnt_3,
(unsigned long long)qp->q_cnt_4);
len += snprintf(pbuffer + len, LPFC_QUE_INFO_GET_BUF_SIZE - len,
- "EQID[%02d], QE-CNT[%04d], QE-SIZE[%04d], "
- "HOST-IDX[%04d], PORT-IDX[%04d]",
+ "EQID[%02d], QE-CNT[%04d], QE-SZ[%04d], "
+ "HST-IDX[%04d], PRT-IDX[%04d], PST[%03d]",
qp->queue_id, qp->entry_count, qp->entry_size,
- qp->host_index, qp->hba_index);
+ qp->host_index, qp->hba_index, qp->entry_repost);
len += snprintf(pbuffer + len, LPFC_QUE_INFO_GET_BUF_SIZE - len, "\n");
return len;
@@ -5855,8 +5866,10 @@ lpfc_debugfs_terminate(struct lpfc_vport *vport)
atomic_dec(&lpfc_debugfs_hba_count);
}
- debugfs_remove(lpfc_debugfs_root); /* lpfc */
- lpfc_debugfs_root = NULL;
+ if (atomic_read(&lpfc_debugfs_hba_count) == 0) {
+ debugfs_remove(lpfc_debugfs_root); /* lpfc */
+ lpfc_debugfs_root = NULL;
+ }
}
#endif
return;
diff --git a/drivers/scsi/lpfc/lpfc_disc.h b/drivers/scsi/lpfc/lpfc_disc.h
index 9d5a379f4b15..094c97b9e5f7 100644
--- a/drivers/scsi/lpfc/lpfc_disc.h
+++ b/drivers/scsi/lpfc/lpfc_disc.h
@@ -90,6 +90,7 @@ struct lpfc_nodelist {
#define NLP_FCP_INITIATOR 0x10 /* entry is an FCP Initiator */
#define NLP_NVME_TARGET 0x20 /* entry is a NVME Target */
#define NLP_NVME_INITIATOR 0x40 /* entry is a NVME Initiator */
+#define NLP_NVME_DISCOVERY 0x80 /* entry has NVME disc srvc */
uint16_t nlp_fc4_type; /* FC types node supports. */
/* Assigned from GID_FF, only
diff --git a/drivers/scsi/lpfc/lpfc_els.c b/drivers/scsi/lpfc/lpfc_els.c
index 67827e397431..8e532b39ae93 100644
--- a/drivers/scsi/lpfc/lpfc_els.c
+++ b/drivers/scsi/lpfc/lpfc_els.c
@@ -1047,6 +1047,13 @@ stop_rr_fcf_flogi:
irsp->ulpStatus, irsp->un.ulpWord[4],
irsp->ulpTimeout);
+
+ /* If this is not a loop open failure, bail out */
+ if (!(irsp->ulpStatus == IOSTAT_LOCAL_REJECT &&
+ ((irsp->un.ulpWord[4] & IOERR_PARAM_MASK) ==
+ IOERR_LOOP_OPEN_FAILURE)))
+ goto flogifail;
+
/* FLOGI failed, so there is no fabric */
spin_lock_irq(shost->host_lock);
vport->fc_flag &= ~(FC_FABRIC | FC_PUBLIC_LOOP);
@@ -2077,16 +2084,19 @@ lpfc_cmpl_els_prli(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
if (irsp->ulpStatus) {
/* Check for retry */
+ ndlp->fc4_prli_sent--;
if (lpfc_els_retry(phba, cmdiocb, rspiocb)) {
/* ELS command is being retried */
- ndlp->fc4_prli_sent--;
goto out;
}
+
/* PRLI failed */
lpfc_printf_vlog(vport, KERN_ERR, LOG_ELS,
- "2754 PRLI failure DID:%06X Status:x%x/x%x\n",
+ "2754 PRLI failure DID:%06X Status:x%x/x%x, "
+ "data: x%x\n",
ndlp->nlp_DID, irsp->ulpStatus,
- irsp->un.ulpWord[4]);
+ irsp->un.ulpWord[4], ndlp->fc4_prli_sent);
+
/* Do not call DSM for lpfc_els_abort'ed ELS cmds */
if (lpfc_error_lost_link(irsp))
goto out;
@@ -7441,6 +7451,13 @@ lpfc_els_flush_cmd(struct lpfc_vport *vport)
*/
spin_lock_irq(&phba->hbalock);
pring = lpfc_phba_elsring(phba);
+
+ /* Bail out if we've no ELS wq, like in PCI error recovery case. */
+ if (unlikely(!pring)) {
+ spin_unlock_irq(&phba->hbalock);
+ return;
+ }
+
if (phba->sli_rev == LPFC_SLI_REV4)
spin_lock(&pring->ring_lock);
@@ -8667,7 +8684,8 @@ lpfc_cmpl_els_fdisc(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
lpfc_do_scr_ns_plogi(phba, vport);
goto out;
fdisc_failed:
- if (vport->fc_vport->vport_state != FC_VPORT_NO_FABRIC_RSCS)
+ if (vport->fc_vport &&
+ (vport->fc_vport->vport_state != FC_VPORT_NO_FABRIC_RSCS))
lpfc_vport_set_state(vport, FC_VPORT_FAILED);
/* Cancel discovery timer */
lpfc_can_disctmo(vport);
diff --git a/drivers/scsi/lpfc/lpfc_hbadisc.c b/drivers/scsi/lpfc/lpfc_hbadisc.c
index 0482c5580331..3ffcd9215ca8 100644
--- a/drivers/scsi/lpfc/lpfc_hbadisc.c
+++ b/drivers/scsi/lpfc/lpfc_hbadisc.c
@@ -693,15 +693,16 @@ lpfc_work_done(struct lpfc_hba *phba)
pring = lpfc_phba_elsring(phba);
status = (ha_copy & (HA_RXMASK << (4*LPFC_ELS_RING)));
status >>= (4*LPFC_ELS_RING);
- if ((status & HA_RXMASK) ||
- (pring->flag & LPFC_DEFERRED_RING_EVENT) ||
- (phba->hba_flag & HBA_SP_QUEUE_EVT)) {
+ if (pring && (status & HA_RXMASK ||
+ pring->flag & LPFC_DEFERRED_RING_EVENT ||
+ phba->hba_flag & HBA_SP_QUEUE_EVT)) {
if (pring->flag & LPFC_STOP_IOCB_EVENT) {
pring->flag |= LPFC_DEFERRED_RING_EVENT;
/* Set the lpfc data pending flag */
set_bit(LPFC_DATA_READY, &phba->data_flags);
} else {
- if (phba->link_state >= LPFC_LINK_UP) {
+ if (phba->link_state >= LPFC_LINK_UP ||
+ phba->link_flag & LS_MDS_LOOPBACK) {
pring->flag &= ~LPFC_DEFERRED_RING_EVENT;
lpfc_sli_handle_slow_ring_event(phba, pring,
(status &
diff --git a/drivers/scsi/lpfc/lpfc_hw4.h b/drivers/scsi/lpfc/lpfc_hw4.h
index 1d12f2be36bc..e0a5fce416ae 100644
--- a/drivers/scsi/lpfc/lpfc_hw4.h
+++ b/drivers/scsi/lpfc/lpfc_hw4.h
@@ -1356,6 +1356,7 @@ struct lpfc_mbx_wq_destroy {
#define LPFC_HDR_BUF_SIZE 128
#define LPFC_DATA_BUF_SIZE 2048
+#define LPFC_NVMET_DATA_BUF_SIZE 128
struct rq_context {
uint32_t word0;
#define lpfc_rq_context_rqe_count_SHIFT 16 /* Version 0 Only */
@@ -4420,6 +4421,19 @@ struct fcp_treceive64_wqe {
};
#define TXRDY_PAYLOAD_LEN 12
+#define CMD_SEND_FRAME 0xE1
+
+struct send_frame_wqe {
+ struct ulp_bde64 bde; /* words 0-2 */
+ uint32_t frame_len; /* word 3 */
+ uint32_t fc_hdr_wd0; /* word 4 */
+ uint32_t fc_hdr_wd1; /* word 5 */
+ struct wqe_common wqe_com; /* words 6-11 */
+ uint32_t fc_hdr_wd2; /* word 12 */
+ uint32_t fc_hdr_wd3; /* word 13 */
+ uint32_t fc_hdr_wd4; /* word 14 */
+ uint32_t fc_hdr_wd5; /* word 15 */
+};
union lpfc_wqe {
uint32_t words[16];
@@ -4438,7 +4452,7 @@ union lpfc_wqe {
struct fcp_trsp64_wqe fcp_trsp;
struct fcp_tsend64_wqe fcp_tsend;
struct fcp_treceive64_wqe fcp_treceive;
-
+ struct send_frame_wqe send_frame;
};
union lpfc_wqe128 {
diff --git a/drivers/scsi/lpfc/lpfc_init.c b/drivers/scsi/lpfc/lpfc_init.c
index 4b1eb98c228d..9add9473cae5 100644
--- a/drivers/scsi/lpfc/lpfc_init.c
+++ b/drivers/scsi/lpfc/lpfc_init.c
@@ -1099,7 +1099,7 @@ lpfc_hba_down_post_s4(struct lpfc_hba *phba)
list_for_each_entry_safe(ctxp, ctxp_next, &nvmet_aborts, list) {
ctxp->flag &= ~(LPFC_NVMET_XBUSY | LPFC_NVMET_ABORT_OP);
- lpfc_nvmet_rq_post(phba, ctxp, &ctxp->rqb_buffer->hbuf);
+ lpfc_nvmet_ctxbuf_post(phba, ctxp->ctxbuf);
}
}
@@ -3381,7 +3381,7 @@ lpfc_sli4_nvmet_sgl_update(struct lpfc_hba *phba)
{
struct lpfc_sglq *sglq_entry = NULL, *sglq_entry_next = NULL;
uint16_t i, lxri, xri_cnt, els_xri_cnt;
- uint16_t nvmet_xri_cnt, tot_cnt;
+ uint16_t nvmet_xri_cnt;
LIST_HEAD(nvmet_sgl_list);
int rc;
@@ -3389,15 +3389,9 @@ lpfc_sli4_nvmet_sgl_update(struct lpfc_hba *phba)
* update on pci function's nvmet xri-sgl list
*/
els_xri_cnt = lpfc_sli4_get_els_iocb_cnt(phba);
- nvmet_xri_cnt = phba->cfg_nvmet_mrq * phba->cfg_nvmet_mrq_post;
- tot_cnt = phba->sli4_hba.max_cfg_param.max_xri - els_xri_cnt;
- if (nvmet_xri_cnt > tot_cnt) {
- phba->cfg_nvmet_mrq_post = tot_cnt / phba->cfg_nvmet_mrq;
- nvmet_xri_cnt = phba->cfg_nvmet_mrq * phba->cfg_nvmet_mrq_post;
- lpfc_printf_log(phba, KERN_INFO, LOG_SLI,
- "6301 NVMET post-sgl count changed to %d\n",
- phba->cfg_nvmet_mrq_post);
- }
+
+ /* For NVMET, ALL remaining XRIs are dedicated for IO processing */
+ nvmet_xri_cnt = phba->sli4_hba.max_cfg_param.max_xri - els_xri_cnt;
if (nvmet_xri_cnt > phba->sli4_hba.nvmet_xri_cnt) {
/* els xri-sgl expanded */
@@ -4546,6 +4540,19 @@ lpfc_sli4_async_fc_evt(struct lpfc_hba *phba, struct lpfc_acqe_fc_la *acqe_fc)
pmb->vport = phba->pport;
if (phba->sli4_hba.link_state.status != LPFC_FC_LA_TYPE_LINK_UP) {
+ phba->link_flag &= ~(LS_MDS_LINK_DOWN | LS_MDS_LOOPBACK);
+
+ switch (phba->sli4_hba.link_state.status) {
+ case LPFC_FC_LA_TYPE_MDS_LINK_DOWN:
+ phba->link_flag |= LS_MDS_LINK_DOWN;
+ break;
+ case LPFC_FC_LA_TYPE_MDS_LOOPBACK:
+ phba->link_flag |= LS_MDS_LOOPBACK;
+ break;
+ default:
+ break;
+ }
+
/* Parse and translate status field */
mb = &pmb->u.mb;
mb->mbxStatus = lpfc_sli4_parse_latt_fault(phba,
@@ -5830,6 +5837,9 @@ lpfc_sli4_driver_resource_setup(struct lpfc_hba *phba)
spin_lock_init(&phba->sli4_hba.abts_nvme_buf_list_lock);
INIT_LIST_HEAD(&phba->sli4_hba.lpfc_abts_nvme_buf_list);
INIT_LIST_HEAD(&phba->sli4_hba.lpfc_abts_nvmet_ctx_list);
+ INIT_LIST_HEAD(&phba->sli4_hba.lpfc_nvmet_ctx_list);
+ INIT_LIST_HEAD(&phba->sli4_hba.lpfc_nvmet_io_wait_list);
+
/* Fast-path XRI aborted CQ Event work queue list */
INIT_LIST_HEAD(&phba->sli4_hba.sp_nvme_xri_aborted_work_queue);
}
@@ -5837,6 +5847,7 @@ lpfc_sli4_driver_resource_setup(struct lpfc_hba *phba)
/* This abort list used by worker thread */
spin_lock_init(&phba->sli4_hba.sgl_list_lock);
spin_lock_init(&phba->sli4_hba.nvmet_io_lock);
+ spin_lock_init(&phba->sli4_hba.nvmet_io_wait_lock);
/*
* Initialize driver internal slow-path work queues
@@ -5951,16 +5962,21 @@ lpfc_sli4_driver_resource_setup(struct lpfc_hba *phba)
for (i = 0; i < lpfc_enable_nvmet_cnt; i++) {
if (wwn == lpfc_enable_nvmet[i]) {
#if (IS_ENABLED(CONFIG_NVME_TARGET_FC))
+ if (lpfc_nvmet_mem_alloc(phba))
+ break;
+
+ phba->nvmet_support = 1; /* a match */
+
lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
"6017 NVME Target %016llx\n",
wwn);
- phba->nvmet_support = 1; /* a match */
#else
lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
"6021 Can't enable NVME Target."
" NVME_TARGET_FC infrastructure"
" is not in kernel\n");
#endif
+ break;
}
}
}
@@ -6269,7 +6285,7 @@ lpfc_unset_driver_resource_phase2(struct lpfc_hba *phba)
*
* This routine is invoked to free the driver's IOCB list and memory.
**/
-static void
+void
lpfc_free_iocb_list(struct lpfc_hba *phba)
{
struct lpfc_iocbq *iocbq_entry = NULL, *iocbq_next = NULL;
@@ -6297,7 +6313,7 @@ lpfc_free_iocb_list(struct lpfc_hba *phba)
* 0 - successful
* other values - error
**/
-static int
+int
lpfc_init_iocb_list(struct lpfc_hba *phba, int iocb_count)
{
struct lpfc_iocbq *iocbq_entry = NULL;
@@ -6525,7 +6541,6 @@ lpfc_sli4_create_rpi_hdr(struct lpfc_hba *phba)
uint16_t rpi_limit, curr_rpi_range;
struct lpfc_dmabuf *dmabuf;
struct lpfc_rpi_hdr *rpi_hdr;
- uint32_t rpi_count;
/*
* If the SLI4 port supports extents, posting the rpi header isn't
@@ -6538,8 +6553,7 @@ lpfc_sli4_create_rpi_hdr(struct lpfc_hba *phba)
return NULL;
/* The limit on the logical index is just the max_rpi count. */
- rpi_limit = phba->sli4_hba.max_cfg_param.rpi_base +
- phba->sli4_hba.max_cfg_param.max_rpi - 1;
+ rpi_limit = phba->sli4_hba.max_cfg_param.max_rpi;
spin_lock_irq(&phba->hbalock);
/*
@@ -6550,18 +6564,10 @@ lpfc_sli4_create_rpi_hdr(struct lpfc_hba *phba)
curr_rpi_range = phba->sli4_hba.next_rpi;
spin_unlock_irq(&phba->hbalock);
- /*
- * The port has a limited number of rpis. The increment here
- * is LPFC_RPI_HDR_COUNT - 1 to account for the starting value
- * and to allow the full max_rpi range per port.
- */
- if ((curr_rpi_range + (LPFC_RPI_HDR_COUNT - 1)) > rpi_limit)
- rpi_count = rpi_limit - curr_rpi_range;
- else
- rpi_count = LPFC_RPI_HDR_COUNT;
-
- if (!rpi_count)
+ /* Reached full RPI range */
+ if (curr_rpi_range == rpi_limit)
return NULL;
+
/*
* First allocate the protocol header region for the port. The
* port expects a 4KB DMA-mapped memory region that is 4K aligned.
@@ -6595,13 +6601,9 @@ lpfc_sli4_create_rpi_hdr(struct lpfc_hba *phba)
/* The rpi_hdr stores the logical index only. */
rpi_hdr->start_rpi = curr_rpi_range;
+ rpi_hdr->next_rpi = phba->sli4_hba.next_rpi + LPFC_RPI_HDR_COUNT;
list_add_tail(&rpi_hdr->list, &phba->sli4_hba.lpfc_rpi_hdr_list);
- /*
- * The next_rpi stores the next logical module-64 rpi value used
- * to post physical rpis in subsequent rpi postings.
- */
- phba->sli4_hba.next_rpi += rpi_count;
spin_unlock_irq(&phba->hbalock);
return rpi_hdr;
@@ -8172,7 +8174,7 @@ lpfc_sli4_queue_create(struct lpfc_hba *phba)
/* Create NVMET Receive Queue for header */
qdesc = lpfc_sli4_queue_alloc(phba,
phba->sli4_hba.rq_esize,
- phba->sli4_hba.rq_ecount);
+ LPFC_NVMET_RQE_DEF_COUNT);
if (!qdesc) {
lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
"3146 Failed allocate "
@@ -8194,7 +8196,7 @@ lpfc_sli4_queue_create(struct lpfc_hba *phba)
/* Create NVMET Receive Queue for data */
qdesc = lpfc_sli4_queue_alloc(phba,
phba->sli4_hba.rq_esize,
- phba->sli4_hba.rq_ecount);
+ LPFC_NVMET_RQE_DEF_COUNT);
if (!qdesc) {
lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
"3156 Failed allocate "
@@ -8326,46 +8328,6 @@ lpfc_sli4_queue_destroy(struct lpfc_hba *phba)
}
int
-lpfc_post_rq_buffer(struct lpfc_hba *phba, struct lpfc_queue *hrq,
- struct lpfc_queue *drq, int count)
-{
- int rc, i;
- struct lpfc_rqe hrqe;
- struct lpfc_rqe drqe;
- struct lpfc_rqb *rqbp;
- struct rqb_dmabuf *rqb_buffer;
- LIST_HEAD(rqb_buf_list);
-
- rqbp = hrq->rqbp;
- for (i = 0; i < count; i++) {
- rqb_buffer = (rqbp->rqb_alloc_buffer)(phba);
- if (!rqb_buffer)
- break;
- rqb_buffer->hrq = hrq;
- rqb_buffer->drq = drq;
- list_add_tail(&rqb_buffer->hbuf.list, &rqb_buf_list);
- }
- while (!list_empty(&rqb_buf_list)) {
- list_remove_head(&rqb_buf_list, rqb_buffer, struct rqb_dmabuf,
- hbuf.list);
-
- hrqe.address_lo = putPaddrLow(rqb_buffer->hbuf.phys);
- hrqe.address_hi = putPaddrHigh(rqb_buffer->hbuf.phys);
- drqe.address_lo = putPaddrLow(rqb_buffer->dbuf.phys);
- drqe.address_hi = putPaddrHigh(rqb_buffer->dbuf.phys);
- rc = lpfc_sli4_rq_put(hrq, drq, &hrqe, &drqe);
- if (rc < 0) {
- (rqbp->rqb_free_buffer)(phba, rqb_buffer);
- } else {
- list_add_tail(&rqb_buffer->hbuf.list,
- &rqbp->rqb_buffer_list);
- rqbp->buffer_count++;
- }
- }
- return 1;
-}
-
-int
lpfc_free_rq_buffer(struct lpfc_hba *phba, struct lpfc_queue *rq)
{
struct lpfc_rqb *rqbp;
@@ -8784,9 +8746,6 @@ lpfc_sli4_queue_setup(struct lpfc_hba *phba)
goto out_destroy;
}
- lpfc_rq_adjust_repost(phba, phba->sli4_hba.hdr_rq, LPFC_ELS_HBQ);
- lpfc_rq_adjust_repost(phba, phba->sli4_hba.dat_rq, LPFC_ELS_HBQ);
-
rc = lpfc_rq_create(phba, phba->sli4_hba.hdr_rq, phba->sli4_hba.dat_rq,
phba->sli4_hba.els_cq, LPFC_USOL);
if (rc) {
@@ -11110,7 +11069,7 @@ lpfc_pci_probe_one_s4(struct pci_dev *pdev, const struct pci_device_id *pid)
struct lpfc_hba *phba;
struct lpfc_vport *vport = NULL;
struct Scsi_Host *shost = NULL;
- int error, cnt;
+ int error;
uint32_t cfg_mode, intr_mode;
/* Allocate memory for HBA structure */
@@ -11144,22 +11103,6 @@ lpfc_pci_probe_one_s4(struct pci_dev *pdev, const struct pci_device_id *pid)
goto out_unset_pci_mem_s4;
}
- cnt = phba->cfg_iocb_cnt * 1024;
- if (phba->nvmet_support)
- cnt += phba->cfg_nvmet_mrq_post * phba->cfg_nvmet_mrq;
-
- /* Initialize and populate the iocb list per host */
- lpfc_printf_log(phba, KERN_INFO, LOG_INIT,
- "2821 initialize iocb list %d total %d\n",
- phba->cfg_iocb_cnt, cnt);
- error = lpfc_init_iocb_list(phba, cnt);
-
- if (error) {
- lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
- "1413 Failed to initialize iocb list.\n");
- goto out_unset_driver_resource_s4;
- }
-
INIT_LIST_HEAD(&phba->active_rrq_list);
INIT_LIST_HEAD(&phba->fcf.fcf_pri_list);
@@ -11168,7 +11111,7 @@ lpfc_pci_probe_one_s4(struct pci_dev *pdev, const struct pci_device_id *pid)
if (error) {
lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
"1414 Failed to set up driver resource.\n");
- goto out_free_iocb_list;
+ goto out_unset_driver_resource_s4;
}
/* Get the default values for Model Name and Description */
@@ -11268,8 +11211,6 @@ out_destroy_shost:
lpfc_destroy_shost(phba);
out_unset_driver_resource:
lpfc_unset_driver_resource_phase2(phba);
-out_free_iocb_list:
- lpfc_free_iocb_list(phba);
out_unset_driver_resource_s4:
lpfc_sli4_driver_resource_unset(phba);
out_unset_pci_mem_s4:
diff --git a/drivers/scsi/lpfc/lpfc_mem.c b/drivers/scsi/lpfc/lpfc_mem.c
index 5986c7957199..fcc05a1517c2 100644
--- a/drivers/scsi/lpfc/lpfc_mem.c
+++ b/drivers/scsi/lpfc/lpfc_mem.c
@@ -214,6 +214,21 @@ fail_free_drb_pool:
return -ENOMEM;
}
+int
+lpfc_nvmet_mem_alloc(struct lpfc_hba *phba)
+{
+ phba->lpfc_nvmet_drb_pool =
+ pci_pool_create("lpfc_nvmet_drb_pool",
+ phba->pcidev, LPFC_NVMET_DATA_BUF_SIZE,
+ SGL_ALIGN_SZ, 0);
+ if (!phba->lpfc_nvmet_drb_pool) {
+ lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
+ "6024 Can't enable NVME Target - no memory\n");
+ return -ENOMEM;
+ }
+ return 0;
+}
+
/**
* lpfc_mem_free - Frees memory allocated by lpfc_mem_alloc
* @phba: HBA to free memory for
@@ -232,6 +247,9 @@ lpfc_mem_free(struct lpfc_hba *phba)
/* Free HBQ pools */
lpfc_sli_hbqbuf_free_all(phba);
+ if (phba->lpfc_nvmet_drb_pool)
+ pci_pool_destroy(phba->lpfc_nvmet_drb_pool);
+ phba->lpfc_nvmet_drb_pool = NULL;
if (phba->lpfc_drb_pool)
pci_pool_destroy(phba->lpfc_drb_pool);
phba->lpfc_drb_pool = NULL;
@@ -611,8 +629,6 @@ struct rqb_dmabuf *
lpfc_sli4_nvmet_alloc(struct lpfc_hba *phba)
{
struct rqb_dmabuf *dma_buf;
- struct lpfc_iocbq *nvmewqe;
- union lpfc_wqe128 *wqe;
dma_buf = kzalloc(sizeof(struct rqb_dmabuf), GFP_KERNEL);
if (!dma_buf)
@@ -624,69 +640,15 @@ lpfc_sli4_nvmet_alloc(struct lpfc_hba *phba)
kfree(dma_buf);
return NULL;
}
- dma_buf->dbuf.virt = pci_pool_alloc(phba->lpfc_drb_pool, GFP_KERNEL,
- &dma_buf->dbuf.phys);
+ dma_buf->dbuf.virt = pci_pool_alloc(phba->lpfc_nvmet_drb_pool,
+ GFP_KERNEL, &dma_buf->dbuf.phys);
if (!dma_buf->dbuf.virt) {
pci_pool_free(phba->lpfc_hrb_pool, dma_buf->hbuf.virt,
dma_buf->hbuf.phys);
kfree(dma_buf);
return NULL;
}
- dma_buf->total_size = LPFC_DATA_BUF_SIZE;
-
- dma_buf->context = kzalloc(sizeof(struct lpfc_nvmet_rcv_ctx),
- GFP_KERNEL);
- if (!dma_buf->context) {
- pci_pool_free(phba->lpfc_drb_pool, dma_buf->dbuf.virt,
- dma_buf->dbuf.phys);
- pci_pool_free(phba->lpfc_hrb_pool, dma_buf->hbuf.virt,
- dma_buf->hbuf.phys);
- kfree(dma_buf);
- return NULL;
- }
-
- dma_buf->iocbq = lpfc_sli_get_iocbq(phba);
- if (!dma_buf->iocbq) {
- kfree(dma_buf->context);
- pci_pool_free(phba->lpfc_drb_pool, dma_buf->dbuf.virt,
- dma_buf->dbuf.phys);
- pci_pool_free(phba->lpfc_hrb_pool, dma_buf->hbuf.virt,
- dma_buf->hbuf.phys);
- kfree(dma_buf);
- lpfc_printf_log(phba, KERN_ERR, LOG_NVME,
- "2621 Ran out of nvmet iocb/WQEs\n");
- return NULL;
- }
- dma_buf->iocbq->iocb_flag = LPFC_IO_NVMET;
- nvmewqe = dma_buf->iocbq;
- wqe = (union lpfc_wqe128 *)&nvmewqe->wqe;
- /* Initialize WQE */
- memset(wqe, 0, sizeof(union lpfc_wqe));
- /* Word 7 */
- bf_set(wqe_ct, &wqe->generic.wqe_com, SLI4_CT_RPI);
- bf_set(wqe_class, &wqe->generic.wqe_com, CLASS3);
- bf_set(wqe_pu, &wqe->generic.wqe_com, 1);
- /* Word 10 */
- bf_set(wqe_nvme, &wqe->fcp_tsend.wqe_com, 1);
- bf_set(wqe_ebde_cnt, &wqe->generic.wqe_com, 0);
- bf_set(wqe_qosd, &wqe->generic.wqe_com, 0);
-
- dma_buf->iocbq->context1 = NULL;
- spin_lock(&phba->sli4_hba.sgl_list_lock);
- dma_buf->sglq = __lpfc_sli_get_nvmet_sglq(phba, dma_buf->iocbq);
- spin_unlock(&phba->sli4_hba.sgl_list_lock);
- if (!dma_buf->sglq) {
- lpfc_sli_release_iocbq(phba, dma_buf->iocbq);
- kfree(dma_buf->context);
- pci_pool_free(phba->lpfc_drb_pool, dma_buf->dbuf.virt,
- dma_buf->dbuf.phys);
- pci_pool_free(phba->lpfc_hrb_pool, dma_buf->hbuf.virt,
- dma_buf->hbuf.phys);
- kfree(dma_buf);
- lpfc_printf_log(phba, KERN_ERR, LOG_NVME,
- "6132 Ran out of nvmet XRIs\n");
- return NULL;
- }
+ dma_buf->total_size = LPFC_NVMET_DATA_BUF_SIZE;
return dma_buf;
}
@@ -705,20 +667,9 @@ lpfc_sli4_nvmet_alloc(struct lpfc_hba *phba)
void
lpfc_sli4_nvmet_free(struct lpfc_hba *phba, struct rqb_dmabuf *dmab)
{
- unsigned long flags;
-
- __lpfc_clear_active_sglq(phba, dmab->sglq->sli4_lxritag);
- dmab->sglq->state = SGL_FREED;
- dmab->sglq->ndlp = NULL;
-
- spin_lock_irqsave(&phba->sli4_hba.sgl_list_lock, flags);
- list_add_tail(&dmab->sglq->list, &phba->sli4_hba.lpfc_nvmet_sgl_list);
- spin_unlock_irqrestore(&phba->sli4_hba.sgl_list_lock, flags);
-
- lpfc_sli_release_iocbq(phba, dmab->iocbq);
- kfree(dmab->context);
pci_pool_free(phba->lpfc_hrb_pool, dmab->hbuf.virt, dmab->hbuf.phys);
- pci_pool_free(phba->lpfc_drb_pool, dmab->dbuf.virt, dmab->dbuf.phys);
+ pci_pool_free(phba->lpfc_nvmet_drb_pool,
+ dmab->dbuf.virt, dmab->dbuf.phys);
kfree(dmab);
}
@@ -803,6 +754,11 @@ lpfc_rq_buf_free(struct lpfc_hba *phba, struct lpfc_dmabuf *mp)
rc = lpfc_sli4_rq_put(rqb_entry->hrq, rqb_entry->drq, &hrqe, &drqe);
if (rc < 0) {
(rqbp->rqb_free_buffer)(phba, rqb_entry);
+ lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
+ "6409 Cannot post to RQ %d: %x %x\n",
+ rqb_entry->hrq->queue_id,
+ rqb_entry->hrq->host_index,
+ rqb_entry->hrq->hba_index);
} else {
list_add_tail(&rqb_entry->hbuf.list, &rqbp->rqb_buffer_list);
rqbp->buffer_count++;
diff --git a/drivers/scsi/lpfc/lpfc_nportdisc.c b/drivers/scsi/lpfc/lpfc_nportdisc.c
index 8777c2d5f50d..f74cb0142fd4 100644
--- a/drivers/scsi/lpfc/lpfc_nportdisc.c
+++ b/drivers/scsi/lpfc/lpfc_nportdisc.c
@@ -206,7 +206,7 @@ lpfc_check_elscmpl_iocb(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
* associated with a LPFC_NODELIST entry. This
* routine effectively results in a "software abort".
*/
-int
+void
lpfc_els_abort(struct lpfc_hba *phba, struct lpfc_nodelist *ndlp)
{
LIST_HEAD(abort_list);
@@ -215,6 +215,10 @@ lpfc_els_abort(struct lpfc_hba *phba, struct lpfc_nodelist *ndlp)
pring = lpfc_phba_elsring(phba);
+ /* In case of error recovery path, we might have a NULL pring here */
+ if (!pring)
+ return;
+
/* Abort outstanding I/O on NPort <nlp_DID> */
lpfc_printf_vlog(ndlp->vport, KERN_INFO, LOG_DISCOVERY,
"2819 Abort outstanding I/O on NPort x%x "
@@ -273,7 +277,6 @@ lpfc_els_abort(struct lpfc_hba *phba, struct lpfc_nodelist *ndlp)
IOSTAT_LOCAL_REJECT, IOERR_SLI_ABORTED);
lpfc_cancel_retry_delay_tmo(phba->pport, ndlp);
- return 0;
}
static int
@@ -1944,7 +1947,13 @@ lpfc_cmpl_prli_prli_issue(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
/* Target driver cannot solicit NVME FB. */
if (bf_get_be32(prli_tgt, nvpr)) {
+ /* Complete the nvme target roles. The transport
+ * needs to know if the rport is capable of
+ * discovery in addition to its role.
+ */
ndlp->nlp_type |= NLP_NVME_TARGET;
+ if (bf_get_be32(prli_disc, nvpr))
+ ndlp->nlp_type |= NLP_NVME_DISCOVERY;
if ((bf_get_be32(prli_fba, nvpr) == 1) &&
(bf_get_be32(prli_fb_sz, nvpr) > 0) &&
(phba->cfg_nvme_enable_fb) &&
diff --git a/drivers/scsi/lpfc/lpfc_nvmet.c b/drivers/scsi/lpfc/lpfc_nvmet.c
index 0488580eea12..518b15e6f222 100644
--- a/drivers/scsi/lpfc/lpfc_nvmet.c
+++ b/drivers/scsi/lpfc/lpfc_nvmet.c
@@ -142,7 +142,7 @@ out:
}
/**
- * lpfc_nvmet_rq_post - Repost a NVMET RQ DMA buffer and clean up context
+ * lpfc_nvmet_ctxbuf_post - Repost a NVMET RQ DMA buffer and clean up context
* @phba: HBA buffer is associated with
* @ctxp: context to clean up
* @mp: Buffer to free
@@ -155,24 +155,113 @@ out:
* Returns: None
**/
void
-lpfc_nvmet_rq_post(struct lpfc_hba *phba, struct lpfc_nvmet_rcv_ctx *ctxp,
- struct lpfc_dmabuf *mp)
+lpfc_nvmet_ctxbuf_post(struct lpfc_hba *phba, struct lpfc_nvmet_ctxbuf *ctx_buf)
{
- if (ctxp) {
- if (ctxp->flag)
- lpfc_printf_log(phba, KERN_INFO, LOG_NVME_ABTS,
- "6314 rq_post ctx xri x%x flag x%x\n",
- ctxp->oxid, ctxp->flag);
-
- if (ctxp->txrdy) {
- pci_pool_free(phba->txrdy_payload_pool, ctxp->txrdy,
- ctxp->txrdy_phys);
- ctxp->txrdy = NULL;
- ctxp->txrdy_phys = 0;
+#if (IS_ENABLED(CONFIG_NVME_TARGET_FC))
+ struct lpfc_nvmet_rcv_ctx *ctxp = ctx_buf->context;
+ struct lpfc_nvmet_tgtport *tgtp;
+ struct fc_frame_header *fc_hdr;
+ struct rqb_dmabuf *nvmebuf;
+ struct lpfc_dmabuf *hbufp;
+ uint32_t *payload;
+ uint32_t size, oxid, sid, rc;
+ unsigned long iflag;
+
+ if (ctxp->txrdy) {
+ pci_pool_free(phba->txrdy_payload_pool, ctxp->txrdy,
+ ctxp->txrdy_phys);
+ ctxp->txrdy = NULL;
+ ctxp->txrdy_phys = 0;
+ }
+ ctxp->state = LPFC_NVMET_STE_FREE;
+
+ spin_lock_irqsave(&phba->sli4_hba.nvmet_io_wait_lock, iflag);
+ if (phba->sli4_hba.nvmet_io_wait_cnt) {
+ hbufp = &nvmebuf->hbuf;
+ list_remove_head(&phba->sli4_hba.lpfc_nvmet_io_wait_list,
+ nvmebuf, struct rqb_dmabuf,
+ hbuf.list);
+ phba->sli4_hba.nvmet_io_wait_cnt--;
+ spin_unlock_irqrestore(&phba->sli4_hba.nvmet_io_wait_lock,
+ iflag);
+
+ fc_hdr = (struct fc_frame_header *)(nvmebuf->hbuf.virt);
+ oxid = be16_to_cpu(fc_hdr->fh_ox_id);
+ tgtp = (struct lpfc_nvmet_tgtport *)phba->targetport->private;
+ payload = (uint32_t *)(nvmebuf->dbuf.virt);
+ size = nvmebuf->bytes_recv;
+ sid = sli4_sid_from_fc_hdr(fc_hdr);
+
+ ctxp = (struct lpfc_nvmet_rcv_ctx *)ctx_buf->context;
+ memset(ctxp, 0, sizeof(ctxp->ctx));
+ ctxp->wqeq = NULL;
+ ctxp->txrdy = NULL;
+ ctxp->offset = 0;
+ ctxp->phba = phba;
+ ctxp->size = size;
+ ctxp->oxid = oxid;
+ ctxp->sid = sid;
+ ctxp->state = LPFC_NVMET_STE_RCV;
+ ctxp->entry_cnt = 1;
+ ctxp->flag = 0;
+ ctxp->ctxbuf = ctx_buf;
+ spin_lock_init(&ctxp->ctxlock);
+
+#ifdef CONFIG_SCSI_LPFC_DEBUG_FS
+ if (phba->ktime_on) {
+ ctxp->ts_cmd_nvme = ktime_get_ns();
+ ctxp->ts_isr_cmd = ctxp->ts_cmd_nvme;
+ ctxp->ts_nvme_data = 0;
+ ctxp->ts_data_wqput = 0;
+ ctxp->ts_isr_data = 0;
+ ctxp->ts_data_nvme = 0;
+ ctxp->ts_nvme_status = 0;
+ ctxp->ts_status_wqput = 0;
+ ctxp->ts_isr_status = 0;
+ ctxp->ts_status_nvme = 0;
}
- ctxp->state = LPFC_NVMET_STE_FREE;
+#endif
+ atomic_inc(&tgtp->rcv_fcp_cmd_in);
+ /*
+ * The calling sequence should be:
+ * nvmet_fc_rcv_fcp_req->lpfc_nvmet_xmt_fcp_op/cmp- req->done
+ * lpfc_nvmet_xmt_fcp_op_cmp should free the allocated ctxp.
+ * When we return from nvmet_fc_rcv_fcp_req, all relevant info
+ * the NVME command / FC header is stored.
+ * A buffer has already been reposted for this IO, so just free
+ * the nvmebuf.
+ */
+ rc = nvmet_fc_rcv_fcp_req(phba->targetport, &ctxp->ctx.fcp_req,
+ payload, size);
+
+ /* Process FCP command */
+ if (rc == 0) {
+ atomic_inc(&tgtp->rcv_fcp_cmd_out);
+ nvmebuf->hrq->rqbp->rqb_free_buffer(phba, nvmebuf);
+ return;
+ }
+
+ atomic_inc(&tgtp->rcv_fcp_cmd_drop);
+ lpfc_printf_log(phba, KERN_ERR, LOG_NVME_IOERR,
+ "2582 FCP Drop IO x%x: err x%x: x%x x%x x%x\n",
+ ctxp->oxid, rc,
+ atomic_read(&tgtp->rcv_fcp_cmd_in),
+ atomic_read(&tgtp->rcv_fcp_cmd_out),
+ atomic_read(&tgtp->xmt_fcp_release));
+
+ lpfc_nvmet_defer_release(phba, ctxp);
+ lpfc_nvmet_unsol_fcp_issue_abort(phba, ctxp, sid, oxid);
+ nvmebuf->hrq->rqbp->rqb_free_buffer(phba, nvmebuf);
+ return;
}
- lpfc_rq_buf_free(phba, mp);
+ spin_unlock_irqrestore(&phba->sli4_hba.nvmet_io_wait_lock, iflag);
+
+ spin_lock_irqsave(&phba->sli4_hba.nvmet_io_lock, iflag);
+ list_add_tail(&ctx_buf->list,
+ &phba->sli4_hba.lpfc_nvmet_ctx_list);
+ phba->sli4_hba.nvmet_ctx_cnt++;
+ spin_unlock_irqrestore(&phba->sli4_hba.nvmet_io_lock, iflag);
+#endif
}
#ifdef CONFIG_SCSI_LPFC_DEBUG_FS
@@ -502,6 +591,7 @@ lpfc_nvmet_xmt_ls_rsp(struct nvmet_fc_target_port *tgtport,
"6150 LS Drop IO x%x: Prep\n",
ctxp->oxid);
lpfc_in_buf_free(phba, &nvmebuf->dbuf);
+ atomic_inc(&nvmep->xmt_ls_abort);
lpfc_nvmet_unsol_ls_issue_abort(phba, ctxp,
ctxp->sid, ctxp->oxid);
return -ENOMEM;
@@ -545,6 +635,7 @@ lpfc_nvmet_xmt_ls_rsp(struct nvmet_fc_target_port *tgtport,
lpfc_nlp_put(nvmewqeq->context1);
lpfc_in_buf_free(phba, &nvmebuf->dbuf);
+ atomic_inc(&nvmep->xmt_ls_abort);
lpfc_nvmet_unsol_ls_issue_abort(phba, ctxp, ctxp->sid, ctxp->oxid);
return -ENXIO;
}
@@ -612,9 +703,9 @@ lpfc_nvmet_xmt_fcp_op(struct nvmet_fc_target_port *tgtport,
lpfc_nvmeio_data(phba, "NVMET FCP CMND: xri x%x op x%x len x%x\n",
ctxp->oxid, rsp->op, rsp->rsplen);
+ ctxp->flag |= LPFC_NVMET_IO_INP;
rc = lpfc_sli4_issue_wqe(phba, LPFC_FCP_RING, nvmewqeq);
if (rc == WQE_SUCCESS) {
- ctxp->flag |= LPFC_NVMET_IO_INP;
#ifdef CONFIG_SCSI_LPFC_DEBUG_FS
if (!phba->ktime_on)
return 0;
@@ -692,6 +783,7 @@ static void
lpfc_nvmet_xmt_fcp_release(struct nvmet_fc_target_port *tgtport,
struct nvmefc_tgt_fcp_req *rsp)
{
+ struct lpfc_nvmet_tgtport *lpfc_nvmep = tgtport->private;
struct lpfc_nvmet_rcv_ctx *ctxp =
container_of(rsp, struct lpfc_nvmet_rcv_ctx, ctx.fcp_req);
struct lpfc_hba *phba = ctxp->phba;
@@ -707,13 +799,15 @@ lpfc_nvmet_xmt_fcp_release(struct nvmet_fc_target_port *tgtport,
}
spin_unlock_irqrestore(&ctxp->ctxlock, flags);
- lpfc_nvmeio_data(phba, "NVMET FCP FREE: xri x%x ste %d\n", ctxp->oxid,
- ctxp->state, 0);
+ lpfc_nvmeio_data(phba, "NVMET FCP FREE: xri x%x ste %d abt %d\n", ctxp->oxid,
+ ctxp->state, aborting);
+
+ atomic_inc(&lpfc_nvmep->xmt_fcp_release);
if (aborting)
return;
- lpfc_nvmet_rq_post(phba, ctxp, &ctxp->rqb_buffer->hbuf);
+ lpfc_nvmet_ctxbuf_post(phba, ctxp->ctxbuf);
}
static struct nvmet_fc_target_template lpfc_tgttemplate = {
@@ -734,17 +828,128 @@ static struct nvmet_fc_target_template lpfc_tgttemplate = {
.target_priv_sz = sizeof(struct lpfc_nvmet_tgtport),
};
+void
+lpfc_nvmet_cleanup_io_context(struct lpfc_hba *phba)
+{
+ struct lpfc_nvmet_ctxbuf *ctx_buf, *next_ctx_buf;
+ unsigned long flags;
+
+ list_for_each_entry_safe(
+ ctx_buf, next_ctx_buf,
+ &phba->sli4_hba.lpfc_nvmet_ctx_list, list) {
+ spin_lock_irqsave(
+ &phba->sli4_hba.abts_nvme_buf_list_lock, flags);
+ list_del_init(&ctx_buf->list);
+ spin_unlock_irqrestore(
+ &phba->sli4_hba.abts_nvme_buf_list_lock, flags);
+ __lpfc_clear_active_sglq(phba,
+ ctx_buf->sglq->sli4_lxritag);
+ ctx_buf->sglq->state = SGL_FREED;
+ ctx_buf->sglq->ndlp = NULL;
+
+ spin_lock_irqsave(&phba->sli4_hba.sgl_list_lock, flags);
+ list_add_tail(&ctx_buf->sglq->list,
+ &phba->sli4_hba.lpfc_nvmet_sgl_list);
+ spin_unlock_irqrestore(&phba->sli4_hba.sgl_list_lock,
+ flags);
+
+ lpfc_sli_release_iocbq(phba, ctx_buf->iocbq);
+ kfree(ctx_buf->context);
+ }
+}
+
+int
+lpfc_nvmet_setup_io_context(struct lpfc_hba *phba)
+{
+ struct lpfc_nvmet_ctxbuf *ctx_buf;
+ struct lpfc_iocbq *nvmewqe;
+ union lpfc_wqe128 *wqe;
+ int i;
+
+ lpfc_printf_log(phba, KERN_INFO, LOG_NVME,
+ "6403 Allocate NVMET resources for %d XRIs\n",
+ phba->sli4_hba.nvmet_xri_cnt);
+
+ /* For all nvmet xris, allocate resources needed to process a
+ * received command on a per xri basis.
+ */
+ for (i = 0; i < phba->sli4_hba.nvmet_xri_cnt; i++) {
+ ctx_buf = kzalloc(sizeof(*ctx_buf), GFP_KERNEL);
+ if (!ctx_buf) {
+ lpfc_printf_log(phba, KERN_ERR, LOG_NVME,
+ "6404 Ran out of memory for NVMET\n");
+ return -ENOMEM;
+ }
+
+ ctx_buf->context = kzalloc(sizeof(*ctx_buf->context),
+ GFP_KERNEL);
+ if (!ctx_buf->context) {
+ kfree(ctx_buf);
+ lpfc_printf_log(phba, KERN_ERR, LOG_NVME,
+ "6405 Ran out of NVMET "
+ "context memory\n");
+ return -ENOMEM;
+ }
+ ctx_buf->context->ctxbuf = ctx_buf;
+
+ ctx_buf->iocbq = lpfc_sli_get_iocbq(phba);
+ if (!ctx_buf->iocbq) {
+ kfree(ctx_buf->context);
+ kfree(ctx_buf);
+ lpfc_printf_log(phba, KERN_ERR, LOG_NVME,
+ "6406 Ran out of NVMET iocb/WQEs\n");
+ return -ENOMEM;
+ }
+ ctx_buf->iocbq->iocb_flag = LPFC_IO_NVMET;
+ nvmewqe = ctx_buf->iocbq;
+ wqe = (union lpfc_wqe128 *)&nvmewqe->wqe;
+ /* Initialize WQE */
+ memset(wqe, 0, sizeof(union lpfc_wqe));
+ /* Word 7 */
+ bf_set(wqe_ct, &wqe->generic.wqe_com, SLI4_CT_RPI);
+ bf_set(wqe_class, &wqe->generic.wqe_com, CLASS3);
+ bf_set(wqe_pu, &wqe->generic.wqe_com, 1);
+ /* Word 10 */
+ bf_set(wqe_nvme, &wqe->fcp_tsend.wqe_com, 1);
+ bf_set(wqe_ebde_cnt, &wqe->generic.wqe_com, 0);
+ bf_set(wqe_qosd, &wqe->generic.wqe_com, 0);
+
+ ctx_buf->iocbq->context1 = NULL;
+ spin_lock(&phba->sli4_hba.sgl_list_lock);
+ ctx_buf->sglq = __lpfc_sli_get_nvmet_sglq(phba, ctx_buf->iocbq);
+ spin_unlock(&phba->sli4_hba.sgl_list_lock);
+ if (!ctx_buf->sglq) {
+ lpfc_sli_release_iocbq(phba, ctx_buf->iocbq);
+ kfree(ctx_buf->context);
+ kfree(ctx_buf);
+ lpfc_printf_log(phba, KERN_ERR, LOG_NVME,
+ "6407 Ran out of NVMET XRIs\n");
+ return -ENOMEM;
+ }
+ spin_lock(&phba->sli4_hba.nvmet_io_lock);
+ list_add_tail(&ctx_buf->list,
+ &phba->sli4_hba.lpfc_nvmet_ctx_list);
+ spin_unlock(&phba->sli4_hba.nvmet_io_lock);
+ }
+ phba->sli4_hba.nvmet_ctx_cnt = phba->sli4_hba.nvmet_xri_cnt;
+ return 0;
+}
+
int
lpfc_nvmet_create_targetport(struct lpfc_hba *phba)
{
struct lpfc_vport *vport = phba->pport;
struct lpfc_nvmet_tgtport *tgtp;
struct nvmet_fc_port_info pinfo;
- int error = 0;
+ int error;
if (phba->targetport)
return 0;
+ error = lpfc_nvmet_setup_io_context(phba);
+ if (error)
+ return error;
+
memset(&pinfo, 0, sizeof(struct nvmet_fc_port_info));
pinfo.node_name = wwn_to_u64(vport->fc_nodename.u.wwn);
pinfo.port_name = wwn_to_u64(vport->fc_portname.u.wwn);
@@ -772,13 +977,16 @@ lpfc_nvmet_create_targetport(struct lpfc_hba *phba)
&phba->pcidev->dev,
&phba->targetport);
#else
- error = -ENOMEM;
+ error = -ENOENT;
#endif
if (error) {
lpfc_printf_log(phba, KERN_ERR, LOG_NVME_DISC,
"6025 Cannot register NVME targetport "
"x%x\n", error);
phba->targetport = NULL;
+
+ lpfc_nvmet_cleanup_io_context(phba);
+
} else {
tgtp = (struct lpfc_nvmet_tgtport *)
phba->targetport->private;
@@ -795,6 +1003,7 @@ lpfc_nvmet_create_targetport(struct lpfc_hba *phba)
atomic_set(&tgtp->rcv_ls_req_out, 0);
atomic_set(&tgtp->rcv_ls_req_drop, 0);
atomic_set(&tgtp->xmt_ls_abort, 0);
+ atomic_set(&tgtp->xmt_ls_abort_cmpl, 0);
atomic_set(&tgtp->xmt_ls_rsp, 0);
atomic_set(&tgtp->xmt_ls_drop, 0);
atomic_set(&tgtp->xmt_ls_rsp_error, 0);
@@ -802,18 +1011,21 @@ lpfc_nvmet_create_targetport(struct lpfc_hba *phba)
atomic_set(&tgtp->rcv_fcp_cmd_in, 0);
atomic_set(&tgtp->rcv_fcp_cmd_out, 0);
atomic_set(&tgtp->rcv_fcp_cmd_drop, 0);
- atomic_set(&tgtp->xmt_fcp_abort, 0);
atomic_set(&tgtp->xmt_fcp_drop, 0);
atomic_set(&tgtp->xmt_fcp_read_rsp, 0);
atomic_set(&tgtp->xmt_fcp_read, 0);
atomic_set(&tgtp->xmt_fcp_write, 0);
atomic_set(&tgtp->xmt_fcp_rsp, 0);
+ atomic_set(&tgtp->xmt_fcp_release, 0);
atomic_set(&tgtp->xmt_fcp_rsp_cmpl, 0);
atomic_set(&tgtp->xmt_fcp_rsp_error, 0);
atomic_set(&tgtp->xmt_fcp_rsp_drop, 0);
+ atomic_set(&tgtp->xmt_fcp_abort, 0);
+ atomic_set(&tgtp->xmt_fcp_abort_cmpl, 0);
+ atomic_set(&tgtp->xmt_abort_unsol, 0);
+ atomic_set(&tgtp->xmt_abort_sol, 0);
atomic_set(&tgtp->xmt_abort_rsp, 0);
atomic_set(&tgtp->xmt_abort_rsp_error, 0);
- atomic_set(&tgtp->xmt_abort_cmpl, 0);
}
return error;
}
@@ -864,7 +1076,7 @@ lpfc_sli4_nvmet_xri_aborted(struct lpfc_hba *phba,
list_for_each_entry_safe(ctxp, next_ctxp,
&phba->sli4_hba.lpfc_abts_nvmet_ctx_list,
list) {
- if (ctxp->rqb_buffer->sglq->sli4_xritag != xri)
+ if (ctxp->ctxbuf->sglq->sli4_xritag != xri)
continue;
/* Check if we already received a free context call
@@ -885,7 +1097,7 @@ lpfc_sli4_nvmet_xri_aborted(struct lpfc_hba *phba,
(ndlp->nlp_state == NLP_STE_UNMAPPED_NODE ||
ndlp->nlp_state == NLP_STE_MAPPED_NODE)) {
lpfc_set_rrq_active(phba, ndlp,
- ctxp->rqb_buffer->sglq->sli4_lxritag,
+ ctxp->ctxbuf->sglq->sli4_lxritag,
rxid, 1);
lpfc_sli4_abts_err_handler(phba, ndlp, axri);
}
@@ -894,8 +1106,8 @@ lpfc_sli4_nvmet_xri_aborted(struct lpfc_hba *phba,
"6318 XB aborted %x flg x%x (%x)\n",
ctxp->oxid, ctxp->flag, released);
if (released)
- lpfc_nvmet_rq_post(phba, ctxp,
- &ctxp->rqb_buffer->hbuf);
+ lpfc_nvmet_ctxbuf_post(phba, ctxp->ctxbuf);
+
if (rrq_empty)
lpfc_worker_wake_up(phba);
return;
@@ -923,7 +1135,7 @@ lpfc_nvmet_rcv_unsol_abort(struct lpfc_vport *vport,
list_for_each_entry_safe(ctxp, next_ctxp,
&phba->sli4_hba.lpfc_abts_nvmet_ctx_list,
list) {
- if (ctxp->rqb_buffer->sglq->sli4_xritag != xri)
+ if (ctxp->ctxbuf->sglq->sli4_xritag != xri)
continue;
spin_unlock(&phba->sli4_hba.abts_nvme_buf_list_lock);
@@ -975,6 +1187,7 @@ lpfc_nvmet_destroy_targetport(struct lpfc_hba *phba)
init_completion(&tgtp->tport_unreg_done);
nvmet_fc_unregister_targetport(phba->targetport);
wait_for_completion_timeout(&tgtp->tport_unreg_done, 5);
+ lpfc_nvmet_cleanup_io_context(phba);
}
phba->targetport = NULL;
#endif
@@ -1010,6 +1223,7 @@ lpfc_nvmet_unsol_ls_buffer(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
oxid = 0;
size = 0;
sid = 0;
+ ctxp = NULL;
goto dropit;
}
@@ -1104,39 +1318,71 @@ lpfc_nvmet_unsol_fcp_buffer(struct lpfc_hba *phba,
struct lpfc_nvmet_rcv_ctx *ctxp;
struct lpfc_nvmet_tgtport *tgtp;
struct fc_frame_header *fc_hdr;
+ struct lpfc_nvmet_ctxbuf *ctx_buf;
uint32_t *payload;
- uint32_t size, oxid, sid, rc;
+ uint32_t size, oxid, sid, rc, qno;
+ unsigned long iflag;
#ifdef CONFIG_SCSI_LPFC_DEBUG_FS
uint32_t id;
#endif
+ ctx_buf = NULL;
if (!nvmebuf || !phba->targetport) {
lpfc_printf_log(phba, KERN_ERR, LOG_NVME_IOERR,
- "6157 FCP Drop IO\n");
+ "6157 NVMET FCP Drop IO\n");
oxid = 0;
size = 0;
sid = 0;
+ ctxp = NULL;
goto dropit;
}
+ spin_lock_irqsave(&phba->sli4_hba.nvmet_io_lock, iflag);
+ if (phba->sli4_hba.nvmet_ctx_cnt) {
+ list_remove_head(&phba->sli4_hba.lpfc_nvmet_ctx_list,
+ ctx_buf, struct lpfc_nvmet_ctxbuf, list);
+ phba->sli4_hba.nvmet_ctx_cnt--;
+ }
+ spin_unlock_irqrestore(&phba->sli4_hba.nvmet_io_lock, iflag);
- tgtp = (struct lpfc_nvmet_tgtport *)phba->targetport->private;
- payload = (uint32_t *)(nvmebuf->dbuf.virt);
fc_hdr = (struct fc_frame_header *)(nvmebuf->hbuf.virt);
- size = nvmebuf->bytes_recv;
oxid = be16_to_cpu(fc_hdr->fh_ox_id);
- sid = sli4_sid_from_fc_hdr(fc_hdr);
+ size = nvmebuf->bytes_recv;
- ctxp = (struct lpfc_nvmet_rcv_ctx *)nvmebuf->context;
- if (ctxp == NULL) {
- atomic_inc(&tgtp->rcv_fcp_cmd_drop);
- lpfc_printf_log(phba, KERN_ERR, LOG_NVME_IOERR,
- "6158 FCP Drop IO x%x: Alloc\n",
- oxid);
- lpfc_nvmet_rq_post(phba, NULL, &nvmebuf->hbuf);
- /* Cannot send ABTS without context */
+#ifdef CONFIG_SCSI_LPFC_DEBUG_FS
+ if (phba->cpucheck_on & LPFC_CHECK_NVMET_RCV) {
+ id = smp_processor_id();
+ if (id < LPFC_CHECK_CPU_CNT)
+ phba->cpucheck_rcv_io[id]++;
+ }
+#endif
+
+ lpfc_nvmeio_data(phba, "NVMET FCP RCV: xri x%x sz %d CPU %02x\n",
+ oxid, size, smp_processor_id());
+
+ if (!ctx_buf) {
+ /* Queue this NVME IO to process later */
+ spin_lock_irqsave(&phba->sli4_hba.nvmet_io_wait_lock, iflag);
+ list_add_tail(&nvmebuf->hbuf.list,
+ &phba->sli4_hba.lpfc_nvmet_io_wait_list);
+ phba->sli4_hba.nvmet_io_wait_cnt++;
+ phba->sli4_hba.nvmet_io_wait_total++;
+ spin_unlock_irqrestore(&phba->sli4_hba.nvmet_io_wait_lock,
+ iflag);
+
+ /* Post a brand new DMA buffer to RQ */
+ qno = nvmebuf->idx;
+ lpfc_post_rq_buffer(
+ phba, phba->sli4_hba.nvmet_mrq_hdr[qno],
+ phba->sli4_hba.nvmet_mrq_data[qno], 1, qno);
return;
}
+
+ tgtp = (struct lpfc_nvmet_tgtport *)phba->targetport->private;
+ payload = (uint32_t *)(nvmebuf->dbuf.virt);
+ sid = sli4_sid_from_fc_hdr(fc_hdr);
+
+ ctxp = (struct lpfc_nvmet_rcv_ctx *)ctx_buf->context;
memset(ctxp, 0, sizeof(ctxp->ctx));
ctxp->wqeq = NULL;
ctxp->txrdy = NULL;
@@ -1146,9 +1392,9 @@ lpfc_nvmet_unsol_fcp_buffer(struct lpfc_hba *phba,
ctxp->oxid = oxid;
ctxp->sid = sid;
ctxp->state = LPFC_NVMET_STE_RCV;
- ctxp->rqb_buffer = nvmebuf;
ctxp->entry_cnt = 1;
ctxp->flag = 0;
+ ctxp->ctxbuf = ctx_buf;
spin_lock_init(&ctxp->ctxlock);
#ifdef CONFIG_SCSI_LPFC_DEBUG_FS
@@ -1164,22 +1410,16 @@ lpfc_nvmet_unsol_fcp_buffer(struct lpfc_hba *phba,
ctxp->ts_isr_status = 0;
ctxp->ts_status_nvme = 0;
}
-
- if (phba->cpucheck_on & LPFC_CHECK_NVMET_RCV) {
- id = smp_processor_id();
- if (id < LPFC_CHECK_CPU_CNT)
- phba->cpucheck_rcv_io[id]++;
- }
#endif
- lpfc_nvmeio_data(phba, "NVMET FCP RCV: xri x%x sz %d CPU %02x\n",
- oxid, size, smp_processor_id());
-
atomic_inc(&tgtp->rcv_fcp_cmd_in);
/*
* The calling sequence should be:
* nvmet_fc_rcv_fcp_req -> lpfc_nvmet_xmt_fcp_op/cmp -> req->done
* lpfc_nvmet_xmt_fcp_op_cmp should free the allocated ctxp.
+ * When we return from nvmet_fc_rcv_fcp_req, all relevant info in
+ * the NVME command / FC header is stored, so we are free to repost
+ * the buffer.
*/
rc = nvmet_fc_rcv_fcp_req(phba->targetport, &ctxp->ctx.fcp_req,
payload, size);
@@ -1187,26 +1427,32 @@ lpfc_nvmet_unsol_fcp_buffer(struct lpfc_hba *phba,
/* Process FCP command */
if (rc == 0) {
atomic_inc(&tgtp->rcv_fcp_cmd_out);
+ lpfc_rq_buf_free(phba, &nvmebuf->hbuf); /* repost */
return;
}
atomic_inc(&tgtp->rcv_fcp_cmd_drop);
lpfc_printf_log(phba, KERN_ERR, LOG_NVME_IOERR,
- "6159 FCP Drop IO x%x: err x%x\n",
- ctxp->oxid, rc);
+ "6159 FCP Drop IO x%x: err x%x: x%x x%x x%x\n",
+ ctxp->oxid, rc,
+ atomic_read(&tgtp->rcv_fcp_cmd_in),
+ atomic_read(&tgtp->rcv_fcp_cmd_out),
+ atomic_read(&tgtp->xmt_fcp_release));
dropit:
lpfc_nvmeio_data(phba, "NVMET FCP DROP: xri x%x sz %d from %06x\n",
oxid, size, sid);
if (oxid) {
+ lpfc_nvmet_defer_release(phba, ctxp);
lpfc_nvmet_unsol_fcp_issue_abort(phba, ctxp, sid, oxid);
+ lpfc_rq_buf_free(phba, &nvmebuf->hbuf); /* repost */
return;
}
- if (nvmebuf) {
- nvmebuf->iocbq->hba_wqidx = 0;
- /* We assume a rcv'ed cmd ALWAYs fits into 1 buffer */
- lpfc_nvmet_rq_post(phba, NULL, &nvmebuf->hbuf);
- }
+ if (ctx_buf)
+ lpfc_nvmet_ctxbuf_post(phba, ctx_buf);
+
+ if (nvmebuf)
+ lpfc_rq_buf_free(phba, &nvmebuf->hbuf); /* repost */
#endif
}
@@ -1258,7 +1504,7 @@ lpfc_nvmet_unsol_fcp_event(struct lpfc_hba *phba,
uint64_t isr_timestamp)
{
if (phba->nvmet_support == 0) {
- lpfc_nvmet_rq_post(phba, NULL, &nvmebuf->hbuf);
+ lpfc_rq_buf_free(phba, &nvmebuf->hbuf);
return;
}
lpfc_nvmet_unsol_fcp_buffer(phba, pring, nvmebuf,
@@ -1459,7 +1705,7 @@ lpfc_nvmet_prep_fcp_wqe(struct lpfc_hba *phba,
nvmewqe = ctxp->wqeq;
if (nvmewqe == NULL) {
/* Allocate buffer for command wqe */
- nvmewqe = ctxp->rqb_buffer->iocbq;
+ nvmewqe = ctxp->ctxbuf->iocbq;
if (nvmewqe == NULL) {
lpfc_printf_log(phba, KERN_ERR, LOG_NVME_IOERR,
"6110 lpfc_nvmet_prep_fcp_wqe: No "
@@ -1486,7 +1732,7 @@ lpfc_nvmet_prep_fcp_wqe(struct lpfc_hba *phba,
return NULL;
}
- sgl = (struct sli4_sge *)ctxp->rqb_buffer->sglq->sgl;
+ sgl = (struct sli4_sge *)ctxp->ctxbuf->sglq->sgl;
switch (rsp->op) {
case NVMET_FCOP_READDATA:
case NVMET_FCOP_READDATA_RSP:
@@ -1811,7 +2057,8 @@ lpfc_nvmet_sol_fcp_abort_cmp(struct lpfc_hba *phba, struct lpfc_iocbq *cmdwqe,
result = wcqe->parameter;
tgtp = (struct lpfc_nvmet_tgtport *)phba->targetport->private;
- atomic_inc(&tgtp->xmt_abort_cmpl);
+ if (ctxp->flag & LPFC_NVMET_ABORT_OP)
+ atomic_inc(&tgtp->xmt_fcp_abort_cmpl);
ctxp->state = LPFC_NVMET_STE_DONE;
@@ -1826,6 +2073,7 @@ lpfc_nvmet_sol_fcp_abort_cmp(struct lpfc_hba *phba, struct lpfc_iocbq *cmdwqe,
}
ctxp->flag &= ~LPFC_NVMET_ABORT_OP;
spin_unlock_irqrestore(&ctxp->ctxlock, flags);
+ atomic_inc(&tgtp->xmt_abort_rsp);
lpfc_printf_log(phba, KERN_ERR, LOG_NVME_ABTS,
"6165 ABORT cmpl: xri x%x flg x%x (%d) "
@@ -1834,15 +2082,16 @@ lpfc_nvmet_sol_fcp_abort_cmp(struct lpfc_hba *phba, struct lpfc_iocbq *cmdwqe,
wcqe->word0, wcqe->total_data_placed,
result, wcqe->word3);
+ cmdwqe->context2 = NULL;
+ cmdwqe->context3 = NULL;
/*
* if transport has released ctx, then can reuse it. Otherwise,
* will be recycled by transport release call.
*/
if (released)
- lpfc_nvmet_rq_post(phba, ctxp, &ctxp->rqb_buffer->hbuf);
+ lpfc_nvmet_ctxbuf_post(phba, ctxp->ctxbuf);
- cmdwqe->context2 = NULL;
- cmdwqe->context3 = NULL;
+ /* This is the iocbq for the abort, not the command */
lpfc_sli_release_iocbq(phba, cmdwqe);
/* Since iaab/iaar are NOT set, there is no work left.
@@ -1876,7 +2125,8 @@ lpfc_nvmet_unsol_fcp_abort_cmp(struct lpfc_hba *phba, struct lpfc_iocbq *cmdwqe,
result = wcqe->parameter;
tgtp = (struct lpfc_nvmet_tgtport *)phba->targetport->private;
- atomic_inc(&tgtp->xmt_abort_cmpl);
+ if (ctxp->flag & LPFC_NVMET_ABORT_OP)
+ atomic_inc(&tgtp->xmt_fcp_abort_cmpl);
if (!ctxp) {
/* if context is clear, related io alrady complete */
@@ -1906,6 +2156,7 @@ lpfc_nvmet_unsol_fcp_abort_cmp(struct lpfc_hba *phba, struct lpfc_iocbq *cmdwqe,
}
ctxp->flag &= ~LPFC_NVMET_ABORT_OP;
spin_unlock_irqrestore(&ctxp->ctxlock, flags);
+ atomic_inc(&tgtp->xmt_abort_rsp);
lpfc_printf_log(phba, KERN_INFO, LOG_NVME_ABTS,
"6316 ABTS cmpl xri x%x flg x%x (%x) "
@@ -1913,15 +2164,15 @@ lpfc_nvmet_unsol_fcp_abort_cmp(struct lpfc_hba *phba, struct lpfc_iocbq *cmdwqe,
ctxp->oxid, ctxp->flag, released,
wcqe->word0, wcqe->total_data_placed,
result, wcqe->word3);
+
+ cmdwqe->context2 = NULL;
+ cmdwqe->context3 = NULL;
/*
* if transport has released ctx, then can reuse it. Otherwise,
* will be recycled by transport release call.
*/
if (released)
- lpfc_nvmet_rq_post(phba, ctxp, &ctxp->rqb_buffer->hbuf);
-
- cmdwqe->context2 = NULL;
- cmdwqe->context3 = NULL;
+ lpfc_nvmet_ctxbuf_post(phba, ctxp->ctxbuf);
/* Since iaab/iaar are NOT set, there is no work left.
* For LPFC_NVMET_XBUSY, lpfc_sli4_nvmet_xri_aborted
@@ -1952,7 +2203,7 @@ lpfc_nvmet_xmt_ls_abort_cmp(struct lpfc_hba *phba, struct lpfc_iocbq *cmdwqe,
result = wcqe->parameter;
tgtp = (struct lpfc_nvmet_tgtport *)phba->targetport->private;
- atomic_inc(&tgtp->xmt_abort_cmpl);
+ atomic_inc(&tgtp->xmt_ls_abort_cmpl);
lpfc_printf_log(phba, KERN_INFO, LOG_NVME_ABTS,
"6083 Abort cmpl: ctx %p WCQE: %08x %08x %08x %08x\n",
@@ -1983,10 +2234,6 @@ lpfc_nvmet_unsol_issue_abort(struct lpfc_hba *phba,
sid, xri, ctxp->wqeq->sli4_xritag);
tgtp = (struct lpfc_nvmet_tgtport *)phba->targetport->private;
- if (!ctxp->wqeq) {
- ctxp->wqeq = ctxp->rqb_buffer->iocbq;
- ctxp->wqeq->hba_wqidx = 0;
- }
ndlp = lpfc_findnode_did(phba->pport, sid);
if (!ndlp || !NLP_CHK_NODE_ACT(ndlp) ||
@@ -2082,7 +2329,7 @@ lpfc_nvmet_sol_fcp_issue_abort(struct lpfc_hba *phba,
tgtp = (struct lpfc_nvmet_tgtport *)phba->targetport->private;
if (!ctxp->wqeq) {
- ctxp->wqeq = ctxp->rqb_buffer->iocbq;
+ ctxp->wqeq = ctxp->ctxbuf->iocbq;
ctxp->wqeq->hba_wqidx = 0;
}
@@ -2103,6 +2350,7 @@ lpfc_nvmet_sol_fcp_issue_abort(struct lpfc_hba *phba,
/* Issue ABTS for this WQE based on iotag */
ctxp->abort_wqeq = lpfc_sli_get_iocbq(phba);
if (!ctxp->abort_wqeq) {
+ atomic_inc(&tgtp->xmt_abort_rsp_error);
lpfc_printf_log(phba, KERN_WARNING, LOG_NVME_ABTS,
"6161 ABORT failed: No wqeqs: "
"xri: x%x\n", ctxp->oxid);
@@ -2127,6 +2375,7 @@ lpfc_nvmet_sol_fcp_issue_abort(struct lpfc_hba *phba,
/* driver queued commands are in process of being flushed */
if (phba->hba_flag & HBA_NVME_IOQ_FLUSH) {
spin_unlock_irqrestore(&phba->hbalock, flags);
+ atomic_inc(&tgtp->xmt_abort_rsp_error);
lpfc_printf_log(phba, KERN_ERR, LOG_NVME,
"6163 Driver in reset cleanup - flushing "
"NVME Req now. hba_flag x%x oxid x%x\n",
@@ -2139,6 +2388,7 @@ lpfc_nvmet_sol_fcp_issue_abort(struct lpfc_hba *phba,
/* Outstanding abort is in progress */
if (abts_wqeq->iocb_flag & LPFC_DRIVER_ABORTED) {
spin_unlock_irqrestore(&phba->hbalock, flags);
+ atomic_inc(&tgtp->xmt_abort_rsp_error);
lpfc_printf_log(phba, KERN_ERR, LOG_NVME,
"6164 Outstanding NVME I/O Abort Request "
"still pending on oxid x%x\n",
@@ -2189,9 +2439,12 @@ lpfc_nvmet_sol_fcp_issue_abort(struct lpfc_hba *phba,
abts_wqeq->context2 = ctxp;
rc = lpfc_sli4_issue_wqe(phba, LPFC_FCP_RING, abts_wqeq);
spin_unlock_irqrestore(&phba->hbalock, flags);
- if (rc == WQE_SUCCESS)
+ if (rc == WQE_SUCCESS) {
+ atomic_inc(&tgtp->xmt_abort_sol);
return 0;
+ }
+ atomic_inc(&tgtp->xmt_abort_rsp_error);
ctxp->flag &= ~LPFC_NVMET_ABORT_OP;
lpfc_sli_release_iocbq(phba, abts_wqeq);
lpfc_printf_log(phba, KERN_ERR, LOG_NVME_ABTS,
@@ -2214,7 +2467,7 @@ lpfc_nvmet_unsol_fcp_issue_abort(struct lpfc_hba *phba,
tgtp = (struct lpfc_nvmet_tgtport *)phba->targetport->private;
if (!ctxp->wqeq) {
- ctxp->wqeq = ctxp->rqb_buffer->iocbq;
+ ctxp->wqeq = ctxp->ctxbuf->iocbq;
ctxp->wqeq->hba_wqidx = 0;
}
@@ -2230,11 +2483,11 @@ lpfc_nvmet_unsol_fcp_issue_abort(struct lpfc_hba *phba,
rc = lpfc_sli4_issue_wqe(phba, LPFC_FCP_RING, abts_wqeq);
spin_unlock_irqrestore(&phba->hbalock, flags);
if (rc == WQE_SUCCESS) {
- atomic_inc(&tgtp->xmt_abort_rsp);
return 0;
}
aerr:
+ atomic_inc(&tgtp->xmt_abort_rsp_error);
ctxp->flag &= ~LPFC_NVMET_ABORT_OP;
atomic_inc(&tgtp->xmt_abort_rsp_error);
lpfc_printf_log(phba, KERN_WARNING, LOG_NVME_ABTS,
@@ -2269,6 +2522,7 @@ lpfc_nvmet_unsol_ls_issue_abort(struct lpfc_hba *phba,
}
abts_wqeq = ctxp->wqeq;
wqe_abts = &abts_wqeq->wqe;
+
lpfc_nvmet_unsol_issue_abort(phba, ctxp, sid, xri);
spin_lock_irqsave(&phba->hbalock, flags);
@@ -2278,7 +2532,7 @@ lpfc_nvmet_unsol_ls_issue_abort(struct lpfc_hba *phba,
rc = lpfc_sli4_issue_wqe(phba, LPFC_ELS_RING, abts_wqeq);
spin_unlock_irqrestore(&phba->hbalock, flags);
if (rc == WQE_SUCCESS) {
- atomic_inc(&tgtp->xmt_abort_rsp);
+ atomic_inc(&tgtp->xmt_abort_unsol);
return 0;
}
diff --git a/drivers/scsi/lpfc/lpfc_nvmet.h b/drivers/scsi/lpfc/lpfc_nvmet.h
index 128759fe6650..6eb2f5d8d4ed 100644
--- a/drivers/scsi/lpfc/lpfc_nvmet.h
+++ b/drivers/scsi/lpfc/lpfc_nvmet.h
@@ -22,6 +22,7 @@
********************************************************************/
#define LPFC_NVMET_DEFAULT_SEGS (64 + 1) /* 256K IOs */
+#define LPFC_NVMET_RQE_DEF_COUNT 512
#define LPFC_NVMET_SUCCESS_LEN 12
/* Used for NVME Target */
@@ -34,6 +35,7 @@ struct lpfc_nvmet_tgtport {
atomic_t rcv_ls_req_out;
atomic_t rcv_ls_req_drop;
atomic_t xmt_ls_abort;
+ atomic_t xmt_ls_abort_cmpl;
/* Stats counters - lpfc_nvmet_xmt_ls_rsp */
atomic_t xmt_ls_rsp;
@@ -47,9 +49,9 @@ struct lpfc_nvmet_tgtport {
atomic_t rcv_fcp_cmd_in;
atomic_t rcv_fcp_cmd_out;
atomic_t rcv_fcp_cmd_drop;
+ atomic_t xmt_fcp_release;
/* Stats counters - lpfc_nvmet_xmt_fcp_op */
- atomic_t xmt_fcp_abort;
atomic_t xmt_fcp_drop;
atomic_t xmt_fcp_read_rsp;
atomic_t xmt_fcp_read;
@@ -62,12 +64,13 @@ struct lpfc_nvmet_tgtport {
atomic_t xmt_fcp_rsp_drop;
- /* Stats counters - lpfc_nvmet_unsol_issue_abort */
+ /* Stats counters - lpfc_nvmet_xmt_fcp_abort */
+ atomic_t xmt_fcp_abort;
+ atomic_t xmt_fcp_abort_cmpl;
+ atomic_t xmt_abort_sol;
+ atomic_t xmt_abort_unsol;
atomic_t xmt_abort_rsp;
atomic_t xmt_abort_rsp_error;
-
- /* Stats counters - lpfc_nvmet_xmt_abort_cmp */
- atomic_t xmt_abort_cmpl;
};
struct lpfc_nvmet_rcv_ctx {
@@ -103,6 +106,7 @@ struct lpfc_nvmet_rcv_ctx {
#define LPFC_NVMET_CTX_RLS 0x8 /* ctx free requested */
#define LPFC_NVMET_ABTS_RCV 0x10 /* ABTS received on exchange */
struct rqb_dmabuf *rqb_buffer;
+ struct lpfc_nvmet_ctxbuf *ctxbuf;
#ifdef CONFIG_SCSI_LPFC_DEBUG_FS
uint64_t ts_isr_cmd;
diff --git a/drivers/scsi/lpfc/lpfc_sli.c b/drivers/scsi/lpfc/lpfc_sli.c
index 2a4fc00dfa9b..d6b184839bc2 100644
--- a/drivers/scsi/lpfc/lpfc_sli.c
+++ b/drivers/scsi/lpfc/lpfc_sli.c
@@ -74,6 +74,8 @@ static struct lpfc_iocbq *lpfc_sli4_els_wcqe_to_rspiocbq(struct lpfc_hba *,
struct lpfc_iocbq *);
static void lpfc_sli4_send_seq_to_ulp(struct lpfc_vport *,
struct hbq_dmabuf *);
+static void lpfc_sli4_handle_mds_loopback(struct lpfc_vport *vport,
+ struct hbq_dmabuf *dmabuf);
static int lpfc_sli4_fp_handle_cqe(struct lpfc_hba *, struct lpfc_queue *,
struct lpfc_cqe *);
static int lpfc_sli4_post_sgl_list(struct lpfc_hba *, struct list_head *,
@@ -479,22 +481,23 @@ lpfc_sli4_rq_put(struct lpfc_queue *hq, struct lpfc_queue *dq,
if (unlikely(!hq) || unlikely(!dq))
return -ENOMEM;
put_index = hq->host_index;
- temp_hrqe = hq->qe[hq->host_index].rqe;
+ temp_hrqe = hq->qe[put_index].rqe;
temp_drqe = dq->qe[dq->host_index].rqe;
if (hq->type != LPFC_HRQ || dq->type != LPFC_DRQ)
return -EINVAL;
- if (hq->host_index != dq->host_index)
+ if (put_index != dq->host_index)
return -EINVAL;
/* If the host has not yet processed the next entry then we are done */
- if (((hq->host_index + 1) % hq->entry_count) == hq->hba_index)
+ if (((put_index + 1) % hq->entry_count) == hq->hba_index)
return -EBUSY;
lpfc_sli_pcimem_bcopy(hrqe, temp_hrqe, hq->entry_size);
lpfc_sli_pcimem_bcopy(drqe, temp_drqe, dq->entry_size);
/* Update the host index to point to the next slot */
- hq->host_index = ((hq->host_index + 1) % hq->entry_count);
+ hq->host_index = ((put_index + 1) % hq->entry_count);
dq->host_index = ((dq->host_index + 1) % dq->entry_count);
+ hq->RQ_buf_posted++;
/* Ring The Header Receive Queue Doorbell */
if (!(hq->host_index % hq->entry_repost)) {
@@ -5906,7 +5909,7 @@ lpfc_set_features(struct lpfc_hba *phba, LPFC_MBOXQ_t *mbox,
bf_set(lpfc_mbx_set_feature_mds,
&mbox->u.mqe.un.set_feature, 1);
bf_set(lpfc_mbx_set_feature_mds_deep_loopbk,
- &mbox->u.mqe.un.set_feature, 0);
+ &mbox->u.mqe.un.set_feature, 1);
mbox->u.mqe.un.set_feature.feature = LPFC_SET_MDS_DIAGS;
mbox->u.mqe.un.set_feature.param_len = 8;
break;
@@ -6512,6 +6515,50 @@ lpfc_set_host_data(struct lpfc_hba *phba, LPFC_MBOXQ_t *mbox)
(phba->hba_flag & HBA_FCOE_MODE) ? "FCoE" : "FC");
}
+int
+lpfc_post_rq_buffer(struct lpfc_hba *phba, struct lpfc_queue *hrq,
+ struct lpfc_queue *drq, int count, int idx)
+{
+ int rc, i;
+ struct lpfc_rqe hrqe;
+ struct lpfc_rqe drqe;
+ struct lpfc_rqb *rqbp;
+ struct rqb_dmabuf *rqb_buffer;
+ LIST_HEAD(rqb_buf_list);
+
+ rqbp = hrq->rqbp;
+ for (i = 0; i < count; i++) {
+ /* IF RQ is already full, don't bother */
+ if (rqbp->buffer_count + i >= rqbp->entry_count - 1)
+ break;
+ rqb_buffer = rqbp->rqb_alloc_buffer(phba);
+ if (!rqb_buffer)
+ break;
+ rqb_buffer->hrq = hrq;
+ rqb_buffer->drq = drq;
+ rqb_buffer->idx = idx;
+ list_add_tail(&rqb_buffer->hbuf.list, &rqb_buf_list);
+ }
+ while (!list_empty(&rqb_buf_list)) {
+ list_remove_head(&rqb_buf_list, rqb_buffer, struct rqb_dmabuf,
+ hbuf.list);
+
+ hrqe.address_lo = putPaddrLow(rqb_buffer->hbuf.phys);
+ hrqe.address_hi = putPaddrHigh(rqb_buffer->hbuf.phys);
+ drqe.address_lo = putPaddrLow(rqb_buffer->dbuf.phys);
+ drqe.address_hi = putPaddrHigh(rqb_buffer->dbuf.phys);
+ rc = lpfc_sli4_rq_put(hrq, drq, &hrqe, &drqe);
+ if (rc < 0) {
+ rqbp->rqb_free_buffer(phba, rqb_buffer);
+ } else {
+ list_add_tail(&rqb_buffer->hbuf.list,
+ &rqbp->rqb_buffer_list);
+ rqbp->buffer_count++;
+ }
+ }
+ return 1;
+}
+
/**
* lpfc_sli4_hba_setup - SLI4 device initialization PCI function
* @phba: Pointer to HBA context object.
@@ -6524,7 +6571,7 @@ lpfc_set_host_data(struct lpfc_hba *phba, LPFC_MBOXQ_t *mbox)
int
lpfc_sli4_hba_setup(struct lpfc_hba *phba)
{
- int rc, i;
+ int rc, i, cnt;
LPFC_MBOXQ_t *mboxq;
struct lpfc_mqe *mqe;
uint8_t *vpd;
@@ -6875,6 +6922,21 @@ lpfc_sli4_hba_setup(struct lpfc_hba *phba)
goto out_destroy_queue;
}
phba->sli4_hba.nvmet_xri_cnt = rc;
+
+ cnt = phba->cfg_iocb_cnt * 1024;
+ /* We need 1 iocbq for every SGL, for IO processing */
+ cnt += phba->sli4_hba.nvmet_xri_cnt;
+ /* Initialize and populate the iocb list per host */
+ lpfc_printf_log(phba, KERN_INFO, LOG_INIT,
+ "2821 initialize iocb list %d total %d\n",
+ phba->cfg_iocb_cnt, cnt);
+ rc = lpfc_init_iocb_list(phba, cnt);
+ if (rc) {
+ lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
+ "1413 Failed to init iocb list.\n");
+ goto out_destroy_queue;
+ }
+
lpfc_nvmet_create_targetport(phba);
} else {
/* update host scsi xri-sgl sizes and mappings */
@@ -6894,28 +6956,34 @@ lpfc_sli4_hba_setup(struct lpfc_hba *phba)
"and mapping: %d\n", rc);
goto out_destroy_queue;
}
+
+ cnt = phba->cfg_iocb_cnt * 1024;
+ /* Initialize and populate the iocb list per host */
+ lpfc_printf_log(phba, KERN_INFO, LOG_INIT,
+ "2820 initialize iocb list %d total %d\n",
+ phba->cfg_iocb_cnt, cnt);
+ rc = lpfc_init_iocb_list(phba, cnt);
+ if (rc) {
+ lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
+ "6301 Failed to init iocb list.\n");
+ goto out_destroy_queue;
+ }
}
if (phba->nvmet_support && phba->cfg_nvmet_mrq) {
-
/* Post initial buffers to all RQs created */
for (i = 0; i < phba->cfg_nvmet_mrq; i++) {
rqbp = phba->sli4_hba.nvmet_mrq_hdr[i]->rqbp;
INIT_LIST_HEAD(&rqbp->rqb_buffer_list);
rqbp->rqb_alloc_buffer = lpfc_sli4_nvmet_alloc;
rqbp->rqb_free_buffer = lpfc_sli4_nvmet_free;
- rqbp->entry_count = 256;
+ rqbp->entry_count = LPFC_NVMET_RQE_DEF_COUNT;
rqbp->buffer_count = 0;
- /* Divide by 4 and round down to multiple of 16 */
- rc = (phba->cfg_nvmet_mrq_post >> 2) & 0xfff8;
- phba->sli4_hba.nvmet_mrq_hdr[i]->entry_repost = rc;
- phba->sli4_hba.nvmet_mrq_data[i]->entry_repost = rc;
-
lpfc_post_rq_buffer(
phba, phba->sli4_hba.nvmet_mrq_hdr[i],
phba->sli4_hba.nvmet_mrq_data[i],
- phba->cfg_nvmet_mrq_post);
+ LPFC_NVMET_RQE_DEF_COUNT, i);
}
}
@@ -7082,6 +7150,7 @@ out_unset_queue:
/* Unset all the queues set up in this routine when error out */
lpfc_sli4_queue_unset(phba);
out_destroy_queue:
+ lpfc_free_iocb_list(phba);
lpfc_sli4_queue_destroy(phba);
out_stop_timers:
lpfc_stop_hba_timers(phba);
@@ -8621,8 +8690,11 @@ lpfc_sli4_iocb2wqe(struct lpfc_hba *phba, struct lpfc_iocbq *iocbq,
memset(wqe, 0, sizeof(union lpfc_wqe128));
/* Some of the fields are in the right position already */
memcpy(wqe, &iocbq->iocb, sizeof(union lpfc_wqe));
- wqe->generic.wqe_com.word7 = 0; /* The ct field has moved so reset */
- wqe->generic.wqe_com.word10 = 0;
+ if (iocbq->iocb.ulpCommand != CMD_SEND_FRAME) {
+ /* The ct field has moved so reset */
+ wqe->generic.wqe_com.word7 = 0;
+ wqe->generic.wqe_com.word10 = 0;
+ }
abort_tag = (uint32_t) iocbq->iotag;
xritag = iocbq->sli4_xritag;
@@ -9116,6 +9188,10 @@ lpfc_sli4_iocb2wqe(struct lpfc_hba *phba, struct lpfc_iocbq *iocbq,
}
break;
+ case CMD_SEND_FRAME:
+ bf_set(wqe_xri_tag, &wqe->generic.wqe_com, xritag);
+ bf_set(wqe_reqtag, &wqe->generic.wqe_com, iocbq->iotag);
+ return 0;
case CMD_XRI_ABORTED_CX:
case CMD_CREATE_XRI_CR: /* Do we expect to use this? */
case CMD_IOCB_FCP_IBIDIR64_CR: /* bidirectional xfer */
@@ -12788,6 +12864,7 @@ lpfc_sli4_sp_handle_rcqe(struct lpfc_hba *phba, struct lpfc_rcqe *rcqe)
struct fc_frame_header *fc_hdr;
struct lpfc_queue *hrq = phba->sli4_hba.hdr_rq;
struct lpfc_queue *drq = phba->sli4_hba.dat_rq;
+ struct lpfc_nvmet_tgtport *tgtp;
struct hbq_dmabuf *dma_buf;
uint32_t status, rq_id;
unsigned long iflags;
@@ -12808,7 +12885,6 @@ lpfc_sli4_sp_handle_rcqe(struct lpfc_hba *phba, struct lpfc_rcqe *rcqe)
case FC_STATUS_RQ_BUF_LEN_EXCEEDED:
lpfc_printf_log(phba, KERN_ERR, LOG_SLI,
"2537 Receive Frame Truncated!!\n");
- hrq->RQ_buf_trunc++;
case FC_STATUS_RQ_SUCCESS:
lpfc_sli4_rq_release(hrq, drq);
spin_lock_irqsave(&phba->hbalock, iflags);
@@ -12819,6 +12895,7 @@ lpfc_sli4_sp_handle_rcqe(struct lpfc_hba *phba, struct lpfc_rcqe *rcqe)
goto out;
}
hrq->RQ_rcv_buf++;
+ hrq->RQ_buf_posted--;
memcpy(&dma_buf->cq_event.cqe.rcqe_cmpl, rcqe, sizeof(*rcqe));
/* If a NVME LS event (type 0x28), treat it as Fast path */
@@ -12832,8 +12909,21 @@ lpfc_sli4_sp_handle_rcqe(struct lpfc_hba *phba, struct lpfc_rcqe *rcqe)
spin_unlock_irqrestore(&phba->hbalock, iflags);
workposted = true;
break;
- case FC_STATUS_INSUFF_BUF_NEED_BUF:
case FC_STATUS_INSUFF_BUF_FRM_DISC:
+ if (phba->nvmet_support) {
+ tgtp = phba->targetport->private;
+ lpfc_printf_log(phba, KERN_ERR, LOG_SLI | LOG_NVME,
+ "6402 RQE Error x%x, posted %d err_cnt "
+ "%d: %x %x %x\n",
+ status, hrq->RQ_buf_posted,
+ hrq->RQ_no_posted_buf,
+ atomic_read(&tgtp->rcv_fcp_cmd_in),
+ atomic_read(&tgtp->rcv_fcp_cmd_out),
+ atomic_read(&tgtp->xmt_fcp_release));
+ }
+ /* fallthrough */
+
+ case FC_STATUS_INSUFF_BUF_NEED_BUF:
hrq->RQ_no_posted_buf++;
/* Post more buffers if possible */
spin_lock_irqsave(&phba->hbalock, iflags);
@@ -12951,7 +13041,7 @@ lpfc_sli4_sp_handle_eqe(struct lpfc_hba *phba, struct lpfc_eqe *eqe,
while ((cqe = lpfc_sli4_cq_get(cq))) {
workposted |= lpfc_sli4_sp_handle_mcqe(phba, cqe);
if (!(++ecount % cq->entry_repost))
- lpfc_sli4_cq_release(cq, LPFC_QUEUE_NOARM);
+ break;
cq->CQ_mbox++;
}
break;
@@ -12965,7 +13055,7 @@ lpfc_sli4_sp_handle_eqe(struct lpfc_hba *phba, struct lpfc_eqe *eqe,
workposted |= lpfc_sli4_sp_handle_cqe(phba, cq,
cqe);
if (!(++ecount % cq->entry_repost))
- lpfc_sli4_cq_release(cq, LPFC_QUEUE_NOARM);
+ break;
}
/* Track the max number of CQEs processed in 1 EQ */
@@ -13135,6 +13225,7 @@ lpfc_sli4_nvmet_handle_rcqe(struct lpfc_hba *phba, struct lpfc_queue *cq,
struct lpfc_queue *drq;
struct rqb_dmabuf *dma_buf;
struct fc_frame_header *fc_hdr;
+ struct lpfc_nvmet_tgtport *tgtp;
uint32_t status, rq_id;
unsigned long iflags;
uint32_t fctl, idx;
@@ -13165,8 +13256,6 @@ lpfc_sli4_nvmet_handle_rcqe(struct lpfc_hba *phba, struct lpfc_queue *cq,
case FC_STATUS_RQ_BUF_LEN_EXCEEDED:
lpfc_printf_log(phba, KERN_ERR, LOG_SLI,
"6126 Receive Frame Truncated!!\n");
- hrq->RQ_buf_trunc++;
- break;
case FC_STATUS_RQ_SUCCESS:
lpfc_sli4_rq_release(hrq, drq);
spin_lock_irqsave(&phba->hbalock, iflags);
@@ -13178,6 +13267,7 @@ lpfc_sli4_nvmet_handle_rcqe(struct lpfc_hba *phba, struct lpfc_queue *cq,
}
spin_unlock_irqrestore(&phba->hbalock, iflags);
hrq->RQ_rcv_buf++;
+ hrq->RQ_buf_posted--;
fc_hdr = (struct fc_frame_header *)dma_buf->hbuf.virt;
/* Just some basic sanity checks on FCP Command frame */
@@ -13200,14 +13290,23 @@ lpfc_sli4_nvmet_handle_rcqe(struct lpfc_hba *phba, struct lpfc_queue *cq,
drop:
lpfc_in_buf_free(phba, &dma_buf->dbuf);
break;
- case FC_STATUS_INSUFF_BUF_NEED_BUF:
case FC_STATUS_INSUFF_BUF_FRM_DISC:
+ if (phba->nvmet_support) {
+ tgtp = phba->targetport->private;
+ lpfc_printf_log(phba, KERN_ERR, LOG_SLI | LOG_NVME,
+ "6401 RQE Error x%x, posted %d err_cnt "
+ "%d: %x %x %x\n",
+ status, hrq->RQ_buf_posted,
+ hrq->RQ_no_posted_buf,
+ atomic_read(&tgtp->rcv_fcp_cmd_in),
+ atomic_read(&tgtp->rcv_fcp_cmd_out),
+ atomic_read(&tgtp->xmt_fcp_release));
+ }
+ /* fallthrough */
+
+ case FC_STATUS_INSUFF_BUF_NEED_BUF:
hrq->RQ_no_posted_buf++;
/* Post more buffers if possible */
- spin_lock_irqsave(&phba->hbalock, iflags);
- phba->hba_flag |= HBA_POST_RECEIVE_BUFFER;
- spin_unlock_irqrestore(&phba->hbalock, iflags);
- workposted = true;
break;
}
out:
@@ -13361,7 +13460,7 @@ process_cq:
while ((cqe = lpfc_sli4_cq_get(cq))) {
workposted |= lpfc_sli4_fp_handle_cqe(phba, cq, cqe);
if (!(++ecount % cq->entry_repost))
- lpfc_sli4_cq_release(cq, LPFC_QUEUE_NOARM);
+ break;
}
/* Track the max number of CQEs processed in 1 EQ */
@@ -13452,7 +13551,7 @@ lpfc_sli4_fof_handle_eqe(struct lpfc_hba *phba, struct lpfc_eqe *eqe)
while ((cqe = lpfc_sli4_cq_get(cq))) {
workposted |= lpfc_sli4_fp_handle_cqe(phba, cq, cqe);
if (!(++ecount % cq->entry_repost))
- lpfc_sli4_cq_release(cq, LPFC_QUEUE_NOARM);
+ break;
}
/* Track the max number of CQEs processed in 1 EQ */
@@ -13534,7 +13633,7 @@ lpfc_sli4_fof_intr_handler(int irq, void *dev_id)
while ((eqe = lpfc_sli4_eq_get(eq))) {
lpfc_sli4_fof_handle_eqe(phba, eqe);
if (!(++ecount % eq->entry_repost))
- lpfc_sli4_eq_release(eq, LPFC_QUEUE_NOARM);
+ break;
eq->EQ_processed++;
}
@@ -13651,7 +13750,7 @@ lpfc_sli4_hba_intr_handler(int irq, void *dev_id)
lpfc_sli4_hba_handle_eqe(phba, eqe, hba_eqidx);
if (!(++ecount % fpeq->entry_repost))
- lpfc_sli4_eq_release(fpeq, LPFC_QUEUE_NOARM);
+ break;
fpeq->EQ_processed++;
}
@@ -13832,17 +13931,10 @@ lpfc_sli4_queue_alloc(struct lpfc_hba *phba, uint32_t entry_size,
}
queue->entry_size = entry_size;
queue->entry_count = entry_count;
-
- /*
- * entry_repost is calculated based on the number of entries in the
- * queue. This works out except for RQs. If buffers are NOT initially
- * posted for every RQE, entry_repost should be adjusted accordingly.
- */
- queue->entry_repost = (entry_count >> 3);
- if (queue->entry_repost < LPFC_QUEUE_MIN_REPOST)
- queue->entry_repost = LPFC_QUEUE_MIN_REPOST;
queue->phba = phba;
+ /* entry_repost will be set during q creation */
+
return queue;
out_fail:
lpfc_sli4_queue_free(queue);
@@ -14073,6 +14165,7 @@ lpfc_eq_create(struct lpfc_hba *phba, struct lpfc_queue *eq, uint32_t imax)
status = -ENXIO;
eq->host_index = 0;
eq->hba_index = 0;
+ eq->entry_repost = LPFC_EQ_REPOST;
mempool_free(mbox, phba->mbox_mem_pool);
return status;
@@ -14146,9 +14239,9 @@ lpfc_cq_create(struct lpfc_hba *phba, struct lpfc_queue *cq,
default:
lpfc_printf_log(phba, KERN_ERR, LOG_SLI,
"0361 Unsupported CQ count: "
- "entry cnt %d sz %d pg cnt %d repost %d\n",
+ "entry cnt %d sz %d pg cnt %d\n",
cq->entry_count, cq->entry_size,
- cq->page_count, cq->entry_repost);
+ cq->page_count);
if (cq->entry_count < 256) {
status = -EINVAL;
goto out;
@@ -14201,6 +14294,7 @@ lpfc_cq_create(struct lpfc_hba *phba, struct lpfc_queue *cq,
cq->assoc_qid = eq->queue_id;
cq->host_index = 0;
cq->hba_index = 0;
+ cq->entry_repost = LPFC_CQ_REPOST;
out:
mempool_free(mbox, phba->mbox_mem_pool);
@@ -14392,6 +14486,7 @@ lpfc_cq_create_set(struct lpfc_hba *phba, struct lpfc_queue **cqp,
cq->assoc_qid = eq->queue_id;
cq->host_index = 0;
cq->hba_index = 0;
+ cq->entry_repost = LPFC_CQ_REPOST;
rc = 0;
list_for_each_entry(dmabuf, &cq->page_list, list) {
@@ -14640,6 +14735,7 @@ lpfc_mq_create(struct lpfc_hba *phba, struct lpfc_queue *mq,
mq->subtype = subtype;
mq->host_index = 0;
mq->hba_index = 0;
+ mq->entry_repost = LPFC_MQ_REPOST;
/* link the mq onto the parent cq child list */
list_add_tail(&mq->list, &cq->child_list);
@@ -14865,34 +14961,6 @@ out:
}
/**
- * lpfc_rq_adjust_repost - Adjust entry_repost for an RQ
- * @phba: HBA structure that indicates port to create a queue on.
- * @rq: The queue structure to use for the receive queue.
- * @qno: The associated HBQ number
- *
- *
- * For SLI4 we need to adjust the RQ repost value based on
- * the number of buffers that are initially posted to the RQ.
- */
-void
-lpfc_rq_adjust_repost(struct lpfc_hba *phba, struct lpfc_queue *rq, int qno)
-{
- uint32_t cnt;
-
- /* sanity check on queue memory */
- if (!rq)
- return;
- cnt = lpfc_hbq_defs[qno]->entry_count;
-
- /* Recalc repost for RQs based on buffers initially posted */
- cnt = (cnt >> 3);
- if (cnt < LPFC_QUEUE_MIN_REPOST)
- cnt = LPFC_QUEUE_MIN_REPOST;
-
- rq->entry_repost = cnt;
-}
-
-/**
* lpfc_rq_create - Create a Receive Queue on the HBA
* @phba: HBA structure that indicates port to create a queue on.
* @hrq: The queue structure to use to create the header receive queue.
@@ -15077,6 +15145,7 @@ lpfc_rq_create(struct lpfc_hba *phba, struct lpfc_queue *hrq,
hrq->subtype = subtype;
hrq->host_index = 0;
hrq->hba_index = 0;
+ hrq->entry_repost = LPFC_RQ_REPOST;
/* now create the data queue */
lpfc_sli4_config(phba, mbox, LPFC_MBOX_SUBSYSTEM_FCOE,
@@ -15087,7 +15156,12 @@ lpfc_rq_create(struct lpfc_hba *phba, struct lpfc_queue *hrq,
if (phba->sli4_hba.pc_sli4_params.rqv == LPFC_Q_CREATE_VERSION_1) {
bf_set(lpfc_rq_context_rqe_count_1,
&rq_create->u.request.context, hrq->entry_count);
- rq_create->u.request.context.buffer_size = LPFC_DATA_BUF_SIZE;
+ if (subtype == LPFC_NVMET)
+ rq_create->u.request.context.buffer_size =
+ LPFC_NVMET_DATA_BUF_SIZE;
+ else
+ rq_create->u.request.context.buffer_size =
+ LPFC_DATA_BUF_SIZE;
bf_set(lpfc_rq_context_rqe_size, &rq_create->u.request.context,
LPFC_RQE_SIZE_8);
bf_set(lpfc_rq_context_page_size, &rq_create->u.request.context,
@@ -15124,8 +15198,14 @@ lpfc_rq_create(struct lpfc_hba *phba, struct lpfc_queue *hrq,
LPFC_RQ_RING_SIZE_4096);
break;
}
- bf_set(lpfc_rq_context_buf_size, &rq_create->u.request.context,
- LPFC_DATA_BUF_SIZE);
+ if (subtype == LPFC_NVMET)
+ bf_set(lpfc_rq_context_buf_size,
+ &rq_create->u.request.context,
+ LPFC_NVMET_DATA_BUF_SIZE);
+ else
+ bf_set(lpfc_rq_context_buf_size,
+ &rq_create->u.request.context,
+ LPFC_DATA_BUF_SIZE);
}
bf_set(lpfc_rq_context_cq_id, &rq_create->u.request.context,
cq->queue_id);
@@ -15158,6 +15238,7 @@ lpfc_rq_create(struct lpfc_hba *phba, struct lpfc_queue *hrq,
drq->subtype = subtype;
drq->host_index = 0;
drq->hba_index = 0;
+ drq->entry_repost = LPFC_RQ_REPOST;
/* link the header and data RQs onto the parent cq child list */
list_add_tail(&hrq->list, &cq->child_list);
@@ -15270,7 +15351,7 @@ lpfc_mrq_create(struct lpfc_hba *phba, struct lpfc_queue **hrqp,
cq->queue_id);
bf_set(lpfc_rq_context_data_size,
&rq_create->u.request.context,
- LPFC_DATA_BUF_SIZE);
+ LPFC_NVMET_DATA_BUF_SIZE);
bf_set(lpfc_rq_context_hdr_size,
&rq_create->u.request.context,
LPFC_HDR_BUF_SIZE);
@@ -15315,6 +15396,7 @@ lpfc_mrq_create(struct lpfc_hba *phba, struct lpfc_queue **hrqp,
hrq->subtype = subtype;
hrq->host_index = 0;
hrq->hba_index = 0;
+ hrq->entry_repost = LPFC_RQ_REPOST;
drq->db_format = LPFC_DB_RING_FORMAT;
drq->db_regaddr = phba->sli4_hba.RQDBregaddr;
@@ -15323,6 +15405,7 @@ lpfc_mrq_create(struct lpfc_hba *phba, struct lpfc_queue **hrqp,
drq->subtype = subtype;
drq->host_index = 0;
drq->hba_index = 0;
+ drq->entry_repost = LPFC_RQ_REPOST;
list_add_tail(&hrq->list, &cq->child_list);
list_add_tail(&drq->list, &cq->child_list);
@@ -16063,6 +16146,8 @@ lpfc_fc_frame_check(struct lpfc_hba *phba, struct fc_frame_header *fc_hdr)
struct fc_vft_header *fc_vft_hdr;
uint32_t *header = (uint32_t *) fc_hdr;
+#define FC_RCTL_MDS_DIAGS 0xF4
+
switch (fc_hdr->fh_r_ctl) {
case FC_RCTL_DD_UNCAT: /* uncategorized information */
case FC_RCTL_DD_SOL_DATA: /* solicited data */
@@ -16090,6 +16175,7 @@ lpfc_fc_frame_check(struct lpfc_hba *phba, struct fc_frame_header *fc_hdr)
case FC_RCTL_F_BSY: /* fabric busy to data frame */
case FC_RCTL_F_BSYL: /* fabric busy to link control frame */
case FC_RCTL_LCR: /* link credit reset */
+ case FC_RCTL_MDS_DIAGS: /* MDS Diagnostics */
case FC_RCTL_END: /* end */
break;
case FC_RCTL_VFTH: /* Virtual Fabric tagging Header */
@@ -16099,12 +16185,16 @@ lpfc_fc_frame_check(struct lpfc_hba *phba, struct fc_frame_header *fc_hdr)
default:
goto drop;
}
+
+#define FC_TYPE_VENDOR_UNIQUE 0xFF
+
switch (fc_hdr->fh_type) {
case FC_TYPE_BLS:
case FC_TYPE_ELS:
case FC_TYPE_FCP:
case FC_TYPE_CT:
case FC_TYPE_NVME:
+ case FC_TYPE_VENDOR_UNIQUE:
break;
case FC_TYPE_IP:
case FC_TYPE_ILS:
@@ -16115,12 +16205,14 @@ lpfc_fc_frame_check(struct lpfc_hba *phba, struct fc_frame_header *fc_hdr)
lpfc_printf_log(phba, KERN_INFO, LOG_ELS,
"2538 Received frame rctl:%s (x%x), type:%s (x%x), "
"frame Data:%08x %08x %08x %08x %08x %08x %08x\n",
+ (fc_hdr->fh_r_ctl == FC_RCTL_MDS_DIAGS) ? "MDS Diags" :
lpfc_rctl_names[fc_hdr->fh_r_ctl], fc_hdr->fh_r_ctl,
- lpfc_type_names[fc_hdr->fh_type], fc_hdr->fh_type,
- be32_to_cpu(header[0]), be32_to_cpu(header[1]),
- be32_to_cpu(header[2]), be32_to_cpu(header[3]),
- be32_to_cpu(header[4]), be32_to_cpu(header[5]),
- be32_to_cpu(header[6]));
+ (fc_hdr->fh_type == FC_TYPE_VENDOR_UNIQUE) ?
+ "Vendor Unique" : lpfc_type_names[fc_hdr->fh_type],
+ fc_hdr->fh_type, be32_to_cpu(header[0]),
+ be32_to_cpu(header[1]), be32_to_cpu(header[2]),
+ be32_to_cpu(header[3]), be32_to_cpu(header[4]),
+ be32_to_cpu(header[5]), be32_to_cpu(header[6]));
return 0;
drop:
lpfc_printf_log(phba, KERN_WARNING, LOG_ELS,
@@ -16926,6 +17018,96 @@ lpfc_sli4_send_seq_to_ulp(struct lpfc_vport *vport,
lpfc_sli_release_iocbq(phba, iocbq);
}
+static void
+lpfc_sli4_mds_loopback_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
+ struct lpfc_iocbq *rspiocb)
+{
+ struct lpfc_dmabuf *pcmd = cmdiocb->context2;
+
+ if (pcmd && pcmd->virt)
+ pci_pool_free(phba->lpfc_drb_pool, pcmd->virt, pcmd->phys);
+ kfree(pcmd);
+ lpfc_sli_release_iocbq(phba, cmdiocb);
+}
+
+static void
+lpfc_sli4_handle_mds_loopback(struct lpfc_vport *vport,
+ struct hbq_dmabuf *dmabuf)
+{
+ struct fc_frame_header *fc_hdr;
+ struct lpfc_hba *phba = vport->phba;
+ struct lpfc_iocbq *iocbq = NULL;
+ union lpfc_wqe *wqe;
+ struct lpfc_dmabuf *pcmd = NULL;
+ uint32_t frame_len;
+ int rc;
+
+ fc_hdr = (struct fc_frame_header *)dmabuf->hbuf.virt;
+ frame_len = bf_get(lpfc_rcqe_length, &dmabuf->cq_event.cqe.rcqe_cmpl);
+
+ /* Send the received frame back */
+ iocbq = lpfc_sli_get_iocbq(phba);
+ if (!iocbq)
+ goto exit;
+
+ /* Allocate buffer for command payload */
+ pcmd = kmalloc(sizeof(struct lpfc_dmabuf), GFP_KERNEL);
+ if (pcmd)
+ pcmd->virt = pci_pool_alloc(phba->lpfc_drb_pool, GFP_KERNEL,
+ &pcmd->phys);
+ if (!pcmd || !pcmd->virt)
+ goto exit;
+
+ INIT_LIST_HEAD(&pcmd->list);
+
+ /* copyin the payload */
+ memcpy(pcmd->virt, dmabuf->dbuf.virt, frame_len);
+
+ /* fill in BDE's for command */
+ iocbq->iocb.un.xseq64.bdl.addrHigh = putPaddrHigh(pcmd->phys);
+ iocbq->iocb.un.xseq64.bdl.addrLow = putPaddrLow(pcmd->phys);
+ iocbq->iocb.un.xseq64.bdl.bdeFlags = BUFF_TYPE_BDE_64;
+ iocbq->iocb.un.xseq64.bdl.bdeSize = frame_len;
+
+ iocbq->context2 = pcmd;
+ iocbq->vport = vport;
+ iocbq->iocb_flag &= ~LPFC_FIP_ELS_ID_MASK;
+ iocbq->iocb_flag |= LPFC_USE_FCPWQIDX;
+
+ /*
+ * Setup rest of the iocb as though it were a WQE
+ * Build the SEND_FRAME WQE
+ */
+ wqe = (union lpfc_wqe *)&iocbq->iocb;
+
+ wqe->send_frame.frame_len = frame_len;
+ wqe->send_frame.fc_hdr_wd0 = be32_to_cpu(*((uint32_t *)fc_hdr));
+ wqe->send_frame.fc_hdr_wd1 = be32_to_cpu(*((uint32_t *)fc_hdr + 1));
+ wqe->send_frame.fc_hdr_wd2 = be32_to_cpu(*((uint32_t *)fc_hdr + 2));
+ wqe->send_frame.fc_hdr_wd3 = be32_to_cpu(*((uint32_t *)fc_hdr + 3));
+ wqe->send_frame.fc_hdr_wd4 = be32_to_cpu(*((uint32_t *)fc_hdr + 4));
+ wqe->send_frame.fc_hdr_wd5 = be32_to_cpu(*((uint32_t *)fc_hdr + 5));
+
+ iocbq->iocb.ulpCommand = CMD_SEND_FRAME;
+ iocbq->iocb.ulpLe = 1;
+ iocbq->iocb_cmpl = lpfc_sli4_mds_loopback_cmpl;
+ rc = lpfc_sli_issue_iocb(phba, LPFC_ELS_RING, iocbq, 0);
+ if (rc == IOCB_ERROR)
+ goto exit;
+
+ lpfc_in_buf_free(phba, &dmabuf->dbuf);
+ return;
+
+exit:
+ lpfc_printf_log(phba, KERN_WARNING, LOG_SLI,
+ "2023 Unable to process MDS loopback frame\n");
+ if (pcmd && pcmd->virt)
+ pci_pool_free(phba->lpfc_drb_pool, pcmd->virt, pcmd->phys);
+ kfree(pcmd);
+ lpfc_sli_release_iocbq(phba, iocbq);
+ lpfc_in_buf_free(phba, &dmabuf->dbuf);
+}
+
/**
* lpfc_sli4_handle_received_buffer - Handle received buffers from firmware
* @phba: Pointer to HBA context object.
@@ -16964,6 +17146,13 @@ lpfc_sli4_handle_received_buffer(struct lpfc_hba *phba,
fcfi = bf_get(lpfc_rcqe_fcf_id,
&dmabuf->cq_event.cqe.rcqe_cmpl);
+ if (fc_hdr->fh_r_ctl == 0xF4 && fc_hdr->fh_type == 0xFF) {
+ vport = phba->pport;
+ /* Handle MDS Loopback frames */
+ lpfc_sli4_handle_mds_loopback(vport, dmabuf);
+ return;
+ }
+
/* d_id this frame is directed to */
did = sli4_did_from_fc_hdr(fc_hdr);
@@ -17137,6 +17326,14 @@ lpfc_sli4_post_rpi_hdr(struct lpfc_hba *phba, struct lpfc_rpi_hdr *rpi_page)
"status x%x add_status x%x, mbx status x%x\n",
shdr_status, shdr_add_status, rc);
rc = -ENXIO;
+ } else {
+ /*
+ * The next_rpi stores the next logical module-64 rpi value used
+ * to post physical rpis in subsequent rpi postings.
+ */
+ spin_lock_irq(&phba->hbalock);
+ phba->sli4_hba.next_rpi = rpi_page->next_rpi;
+ spin_unlock_irq(&phba->hbalock);
}
return rc;
}
@@ -18717,7 +18914,7 @@ lpfc_sli4_issue_wqe(struct lpfc_hba *phba, uint32_t ring_number,
spin_lock_irqsave(&pring->ring_lock, iflags);
ctxp = pwqe->context2;
- sglq = ctxp->rqb_buffer->sglq;
+ sglq = ctxp->ctxbuf->sglq;
if (pwqe->sli4_xritag == NO_XRI) {
pwqe->sli4_lxritag = sglq->sli4_lxritag;
pwqe->sli4_xritag = sglq->sli4_xritag;
diff --git a/drivers/scsi/lpfc/lpfc_sli4.h b/drivers/scsi/lpfc/lpfc_sli4.h
index da46471337c8..cf863db27700 100644
--- a/drivers/scsi/lpfc/lpfc_sli4.h
+++ b/drivers/scsi/lpfc/lpfc_sli4.h
@@ -24,7 +24,6 @@
#define LPFC_XRI_EXCH_BUSY_WAIT_TMO 10000
#define LPFC_XRI_EXCH_BUSY_WAIT_T1 10
#define LPFC_XRI_EXCH_BUSY_WAIT_T2 30000
-#define LPFC_RELEASE_NOTIFICATION_INTERVAL 32
#define LPFC_RPI_LOW_WATER_MARK 10
#define LPFC_UNREG_FCF 1
@@ -155,7 +154,11 @@ struct lpfc_queue {
uint32_t entry_count; /* Number of entries to support on the queue */
uint32_t entry_size; /* Size of each queue entry. */
uint32_t entry_repost; /* Count of entries before doorbell is rung */
-#define LPFC_QUEUE_MIN_REPOST 8
+#define LPFC_EQ_REPOST 8
+#define LPFC_MQ_REPOST 8
+#define LPFC_CQ_REPOST 64
+#define LPFC_RQ_REPOST 64
+#define LPFC_RELEASE_NOTIFICATION_INTERVAL 32 /* For WQs */
uint32_t queue_id; /* Queue ID assigned by the hardware */
uint32_t assoc_qid; /* Queue ID associated with, for CQ/WQ/MQ */
uint32_t page_count; /* Number of pages allocated for this queue */
@@ -195,7 +198,7 @@ struct lpfc_queue {
/* defines for RQ stats */
#define RQ_no_posted_buf q_cnt_1
#define RQ_no_buf_found q_cnt_2
-#define RQ_buf_trunc q_cnt_3
+#define RQ_buf_posted q_cnt_3
#define RQ_rcv_buf q_cnt_4
uint64_t isr_timestamp;
@@ -617,12 +620,17 @@ struct lpfc_sli4_hba {
uint16_t scsi_xri_start;
uint16_t els_xri_cnt;
uint16_t nvmet_xri_cnt;
+ uint16_t nvmet_ctx_cnt;
+ uint16_t nvmet_io_wait_cnt;
+ uint16_t nvmet_io_wait_total;
struct list_head lpfc_els_sgl_list;
struct list_head lpfc_abts_els_sgl_list;
struct list_head lpfc_nvmet_sgl_list;
struct list_head lpfc_abts_nvmet_ctx_list;
struct list_head lpfc_abts_scsi_buf_list;
struct list_head lpfc_abts_nvme_buf_list;
+ struct list_head lpfc_nvmet_ctx_list;
+ struct list_head lpfc_nvmet_io_wait_list;
struct lpfc_sglq **lpfc_sglq_active_list;
struct list_head lpfc_rpi_hdr_list;
unsigned long *rpi_bmask;
@@ -654,6 +662,7 @@ struct lpfc_sli4_hba {
spinlock_t abts_scsi_buf_list_lock; /* list of aborted SCSI IOs */
spinlock_t sgl_list_lock; /* list of aborted els IOs */
spinlock_t nvmet_io_lock;
+ spinlock_t nvmet_io_wait_lock; /* IOs waiting for ctx resources */
uint32_t physical_port;
/* CPU to vector mapping information */
@@ -661,8 +670,6 @@ struct lpfc_sli4_hba {
uint16_t num_online_cpu;
uint16_t num_present_cpu;
uint16_t curr_disp_cpu;
-
- uint16_t nvmet_mrq_post_idx;
};
enum lpfc_sge_type {
@@ -698,6 +705,7 @@ struct lpfc_rpi_hdr {
struct lpfc_dmabuf *dmabuf;
uint32_t page_count;
uint32_t start_rpi;
+ uint16_t next_rpi;
};
struct lpfc_rsrc_blks {
@@ -762,7 +770,6 @@ int lpfc_rq_create(struct lpfc_hba *, struct lpfc_queue *,
int lpfc_mrq_create(struct lpfc_hba *phba, struct lpfc_queue **hrqp,
struct lpfc_queue **drqp, struct lpfc_queue **cqp,
uint32_t subtype);
-void lpfc_rq_adjust_repost(struct lpfc_hba *, struct lpfc_queue *, int);
int lpfc_eq_destroy(struct lpfc_hba *, struct lpfc_queue *);
int lpfc_cq_destroy(struct lpfc_hba *, struct lpfc_queue *);
int lpfc_mq_destroy(struct lpfc_hba *, struct lpfc_queue *);
diff --git a/drivers/scsi/lpfc/lpfc_version.h b/drivers/scsi/lpfc/lpfc_version.h
index 1c26dc67151b..c2653244221c 100644
--- a/drivers/scsi/lpfc/lpfc_version.h
+++ b/drivers/scsi/lpfc/lpfc_version.h
@@ -20,7 +20,7 @@
* included with this package. *
*******************************************************************/
-#define LPFC_DRIVER_VERSION "11.2.0.12"
+#define LPFC_DRIVER_VERSION "11.2.0.14"
#define LPFC_DRIVER_NAME "lpfc"
/* Used for SLI 2/3 */
diff --git a/drivers/scsi/osd/osd_initiator.c b/drivers/scsi/osd/osd_initiator.c
index 8a1b94816419..a4f28b7e4c65 100644
--- a/drivers/scsi/osd/osd_initiator.c
+++ b/drivers/scsi/osd/osd_initiator.c
@@ -446,7 +446,7 @@ static void _put_request(struct request *rq)
* code paths.
*/
if (unlikely(rq->bio))
- blk_end_request(rq, -ENOMEM, blk_rq_bytes(rq));
+ blk_end_request(rq, BLK_STS_IOERR, blk_rq_bytes(rq));
else
blk_put_request(rq);
}
@@ -474,10 +474,10 @@ void osd_end_request(struct osd_request *or)
EXPORT_SYMBOL(osd_end_request);
static void _set_error_resid(struct osd_request *or, struct request *req,
- int error)
+ blk_status_t error)
{
or->async_error = error;
- or->req_errors = scsi_req(req)->result ? : error;
+ or->req_errors = scsi_req(req)->result;
or->sense_len = scsi_req(req)->sense_len;
if (or->sense_len)
memcpy(or->sense, scsi_req(req)->sense, or->sense_len);
@@ -489,17 +489,19 @@ static void _set_error_resid(struct osd_request *or, struct request *req,
int osd_execute_request(struct osd_request *or)
{
- int error;
-
blk_execute_rq(or->request->q, NULL, or->request, 0);
- error = scsi_req(or->request)->result ? -EIO : 0;
- _set_error_resid(or, or->request, error);
- return error;
+ if (scsi_req(or->request)->result) {
+ _set_error_resid(or, or->request, BLK_STS_IOERR);
+ return -EIO;
+ }
+
+ _set_error_resid(or, or->request, BLK_STS_OK);
+ return 0;
}
EXPORT_SYMBOL(osd_execute_request);
-static void osd_request_async_done(struct request *req, int error)
+static void osd_request_async_done(struct request *req, blk_status_t error)
{
struct osd_request *or = req->end_io_data;
@@ -1572,13 +1574,9 @@ static struct request *_make_request(struct request_queue *q, bool has_write,
flags);
if (IS_ERR(req))
return req;
- scsi_req_init(req);
for_each_bio(bio) {
- struct bio *bounce_bio = bio;
-
- blk_queue_bounce(req->q, &bounce_bio);
- ret = blk_rq_append_bio(req, bounce_bio);
+ ret = blk_rq_append_bio(req, bio);
if (ret)
return ERR_PTR(ret);
}
@@ -1617,7 +1615,6 @@ static int _init_blk_request(struct osd_request *or,
ret = PTR_ERR(req);
goto out;
}
- scsi_req_init(req);
or->in.req = or->request->next_rq = req;
}
} else if (has_in)
@@ -1914,7 +1911,7 @@ analyze:
/* scsi sense is Empty, the request was never issued to target
* linux return code might tell us what happened.
*/
- if (or->async_error == -ENOMEM)
+ if (or->async_error == BLK_STS_RESOURCE)
osi->osd_err_pri = OSD_ERR_PRI_RESOURCE;
else
osi->osd_err_pri = OSD_ERR_PRI_UNREACHABLE;
diff --git a/drivers/scsi/osst.c b/drivers/scsi/osst.c
index 67cbed92f07d..929ee7e88120 100644
--- a/drivers/scsi/osst.c
+++ b/drivers/scsi/osst.c
@@ -320,7 +320,7 @@ static int osst_chk_result(struct osst_tape * STp, struct osst_request * SRpnt)
/* Wakeup from interrupt */
-static void osst_end_async(struct request *req, int update)
+static void osst_end_async(struct request *req, blk_status_t status)
{
struct scsi_request *rq = scsi_req(req);
struct osst_request *SRpnt = req->end_io_data;
@@ -373,7 +373,6 @@ static int osst_execute(struct osst_request *SRpnt, const unsigned char *cmd,
return DRIVER_ERROR << 24;
rq = scsi_req(req);
- scsi_req_init(req);
req->rq_flags |= RQF_QUIET;
SRpnt->bio = NULL;
diff --git a/drivers/scsi/qedi/qedi.h b/drivers/scsi/qedi/qedi.h
index 5ca3e8c28a3f..32632c9b2276 100644
--- a/drivers/scsi/qedi/qedi.h
+++ b/drivers/scsi/qedi/qedi.h
@@ -38,7 +38,7 @@ struct qedi_endpoint;
#define QEDI_MAX_ISCSI_TASK 4096
#define QEDI_MAX_TASK_NUM 0x0FFF
#define QEDI_MAX_ISCSI_CONNS_PER_HBA 1024
-#define QEDI_ISCSI_MAX_BDS_PER_CMD 256 /* Firmware max BDs is 256 */
+#define QEDI_ISCSI_MAX_BDS_PER_CMD 255 /* Firmware max BDs is 255 */
#define MAX_OUSTANDING_TASKS_PER_CON 1024
#define QEDI_MAX_BD_LEN 0xffff
@@ -63,6 +63,7 @@ struct qedi_endpoint;
#define QEDI_PAGE_MASK (~((QEDI_PAGE_SIZE) - 1))
#define QEDI_PAGE_SIZE 4096
+#define QEDI_HW_DMA_BOUNDARY 0xfff
#define QEDI_PATH_HANDLE 0xFE0000000UL
struct qedi_uio_ctrl {
diff --git a/drivers/scsi/qedi/qedi_fw.c b/drivers/scsi/qedi/qedi_fw.c
index d6978cbc56f0..507512cc478b 100644
--- a/drivers/scsi/qedi/qedi_fw.c
+++ b/drivers/scsi/qedi/qedi_fw.c
@@ -870,7 +870,6 @@ static void qedi_process_cmd_cleanup_resp(struct qedi_ctx *qedi,
QEDI_ERR(&qedi->dbg_ctx,
"Delayed or untracked cleanup response, itt=0x%x, tid=0x%x, cid=0x%x, task=%p\n",
protoitt, cqe->itid, qedi_conn->iscsi_conn_id, task);
- WARN_ON(1);
}
}
@@ -1494,6 +1493,8 @@ static int qedi_send_iscsi_tmf(struct qedi_conn *qedi_conn,
tmf_hdr = (struct iscsi_tm *)mtask->hdr;
qedi_cmd = (struct qedi_cmd *)mtask->dd_data;
ep = qedi_conn->ep;
+ if (!ep)
+ return -ENODEV;
tid = qedi_get_task_idx(qedi);
if (tid == -1)
diff --git a/drivers/scsi/qedi/qedi_iscsi.c b/drivers/scsi/qedi/qedi_iscsi.c
index 3548d46f9b27..87f0af358b33 100644
--- a/drivers/scsi/qedi/qedi_iscsi.c
+++ b/drivers/scsi/qedi/qedi_iscsi.c
@@ -59,6 +59,7 @@ struct scsi_host_template qedi_host_template = {
.this_id = -1,
.sg_tablesize = QEDI_ISCSI_MAX_BDS_PER_CMD,
.max_sectors = 0xffff,
+ .dma_boundary = QEDI_HW_DMA_BOUNDARY,
.cmd_per_lun = 128,
.use_clustering = ENABLE_CLUSTERING,
.shost_attrs = qedi_shost_attrs,
@@ -1223,8 +1224,12 @@ static int qedi_set_path(struct Scsi_Host *shost, struct iscsi_path *path_data)
iscsi_cid = (u32)path_data->handle;
qedi_ep = qedi->ep_tbl[iscsi_cid];
- QEDI_INFO(&qedi->dbg_ctx, QEDI_LOG_CONN,
+ QEDI_INFO(&qedi->dbg_ctx, QEDI_LOG_INFO,
"iscsi_cid=0x%x, qedi_ep=%p\n", iscsi_cid, qedi_ep);
+ if (!qedi_ep) {
+ ret = -EINVAL;
+ goto set_path_exit;
+ }
if (!is_valid_ether_addr(&path_data->mac_addr[0])) {
QEDI_NOTICE(&qedi->dbg_ctx, "dst mac NOT VALID\n");
diff --git a/drivers/scsi/qedi/qedi_main.c b/drivers/scsi/qedi/qedi_main.c
index 92775a8b74b1..879d3b7462f9 100644
--- a/drivers/scsi/qedi/qedi_main.c
+++ b/drivers/scsi/qedi/qedi_main.c
@@ -151,6 +151,11 @@ static int qedi_uio_close(struct uio_info *uinfo, struct inode *inode)
static void __qedi_free_uio_rings(struct qedi_uio_dev *udev)
{
+ if (udev->uctrl) {
+ free_page((unsigned long)udev->uctrl);
+ udev->uctrl = NULL;
+ }
+
if (udev->ll2_ring) {
free_page((unsigned long)udev->ll2_ring);
udev->ll2_ring = NULL;
@@ -169,7 +174,6 @@ static void __qedi_free_uio(struct qedi_uio_dev *udev)
__qedi_free_uio_rings(udev);
pci_dev_put(udev->pdev);
- kfree(udev->uctrl);
kfree(udev);
}
@@ -208,6 +212,11 @@ static int __qedi_alloc_uio_rings(struct qedi_uio_dev *udev)
if (udev->ll2_ring || udev->ll2_buf)
return rc;
+ /* Memory for control area. */
+ udev->uctrl = (void *)get_zeroed_page(GFP_KERNEL);
+ if (!udev->uctrl)
+ return -ENOMEM;
+
/* Allocating memory for LL2 ring */
udev->ll2_ring_size = QEDI_PAGE_SIZE;
udev->ll2_ring = (void *)get_zeroed_page(GFP_KERNEL | __GFP_COMP);
@@ -237,7 +246,6 @@ exit_alloc_ring:
static int qedi_alloc_uio_rings(struct qedi_ctx *qedi)
{
struct qedi_uio_dev *udev = NULL;
- struct qedi_uio_ctrl *uctrl = NULL;
int rc = 0;
list_for_each_entry(udev, &qedi_udev_list, list) {
@@ -258,21 +266,14 @@ static int qedi_alloc_uio_rings(struct qedi_ctx *qedi)
goto err_udev;
}
- uctrl = kzalloc(sizeof(*uctrl), GFP_KERNEL);
- if (!uctrl) {
- rc = -ENOMEM;
- goto err_uctrl;
- }
-
udev->uio_dev = -1;
udev->qedi = qedi;
udev->pdev = qedi->pdev;
- udev->uctrl = uctrl;
rc = __qedi_alloc_uio_rings(udev);
if (rc)
- goto err_uio_rings;
+ goto err_uctrl;
list_add(&udev->list, &qedi_udev_list);
@@ -283,8 +284,6 @@ static int qedi_alloc_uio_rings(struct qedi_ctx *qedi)
udev->rx_pkt = udev->ll2_buf + LL2_SINGLE_BUF_SIZE;
return 0;
- err_uio_rings:
- kfree(uctrl);
err_uctrl:
kfree(udev);
err_udev:
@@ -828,6 +827,8 @@ static int qedi_set_iscsi_pf_param(struct qedi_ctx *qedi)
qedi->pf_params.iscsi_pf_params.num_uhq_pages_in_ring = num_sq_pages;
qedi->pf_params.iscsi_pf_params.num_queues = qedi->num_queues;
qedi->pf_params.iscsi_pf_params.debug_mode = qedi_fw_debug;
+ qedi->pf_params.iscsi_pf_params.two_msl_timer = 4000;
+ qedi->pf_params.iscsi_pf_params.max_fin_rt = 2;
for (log_page_size = 0 ; log_page_size < 32 ; log_page_size++) {
if ((1 << log_page_size) == PAGE_SIZE)
@@ -1498,11 +1499,9 @@ err_idx:
void qedi_clear_task_idx(struct qedi_ctx *qedi, int idx)
{
- if (!test_and_clear_bit(idx, qedi->task_idx_map)) {
+ if (!test_and_clear_bit(idx, qedi->task_idx_map))
QEDI_ERR(&qedi->dbg_ctx,
"FW task context, already cleared, tid=0x%x\n", idx);
- WARN_ON(1);
- }
}
void qedi_update_itt_map(struct qedi_ctx *qedi, u32 tid, u32 proto_itt,
diff --git a/drivers/scsi/qla2xxx/qla_bsg.c b/drivers/scsi/qla2xxx/qla_bsg.c
index 16d1cd50feed..ca3420de5a01 100644
--- a/drivers/scsi/qla2xxx/qla_bsg.c
+++ b/drivers/scsi/qla2xxx/qla_bsg.c
@@ -730,6 +730,8 @@ qla2x00_process_loopback(struct bsg_job *bsg_job)
return -EIO;
}
+ memset(&elreq, 0, sizeof(elreq));
+
elreq.req_sg_cnt = dma_map_sg(&ha->pdev->dev,
bsg_job->request_payload.sg_list, bsg_job->request_payload.sg_cnt,
DMA_TO_DEVICE);
@@ -795,10 +797,9 @@ qla2x00_process_loopback(struct bsg_job *bsg_job)
if (atomic_read(&vha->loop_state) == LOOP_READY &&
(ha->current_topology == ISP_CFG_F ||
- ((IS_QLA81XX(ha) || IS_QLA8031(ha) || IS_QLA8044(ha)) &&
- le32_to_cpu(*(uint32_t *)req_data) == ELS_OPCODE_BYTE
- && req_data_len == MAX_ELS_FRAME_PAYLOAD)) &&
- elreq.options == EXTERNAL_LOOPBACK) {
+ (le32_to_cpu(*(uint32_t *)req_data) == ELS_OPCODE_BYTE &&
+ req_data_len == MAX_ELS_FRAME_PAYLOAD)) &&
+ elreq.options == EXTERNAL_LOOPBACK) {
type = "FC_BSG_HST_VENDOR_ECHO_DIAG";
ql_dbg(ql_dbg_user, vha, 0x701e,
"BSG request type: %s.\n", type);
diff --git a/drivers/scsi/qla2xxx/qla_dbg.c b/drivers/scsi/qla2xxx/qla_dbg.c
index 51b4179469d1..88748a6ab73f 100644
--- a/drivers/scsi/qla2xxx/qla_dbg.c
+++ b/drivers/scsi/qla2xxx/qla_dbg.c
@@ -1131,7 +1131,7 @@ qla24xx_fw_dump(scsi_qla_host_t *vha, int hardware_locked)
/* Mailbox registers. */
mbx_reg = &reg->mailbox0;
- for (cnt = 0; cnt < sizeof(fw->mailbox_reg) / 2; cnt++, dmp_reg++)
+ for (cnt = 0; cnt < sizeof(fw->mailbox_reg) / 2; cnt++, mbx_reg++)
fw->mailbox_reg[cnt] = htons(RD_REG_WORD(mbx_reg));
/* Transfer sequence registers. */
@@ -2090,7 +2090,7 @@ qla83xx_fw_dump(scsi_qla_host_t *vha, int hardware_locked)
/* Mailbox registers. */
mbx_reg = &reg->mailbox0;
- for (cnt = 0; cnt < sizeof(fw->mailbox_reg) / 2; cnt++, dmp_reg++)
+ for (cnt = 0; cnt < sizeof(fw->mailbox_reg) / 2; cnt++, mbx_reg++)
fw->mailbox_reg[cnt] = htons(RD_REG_WORD(mbx_reg));
/* Transfer sequence registers. */
diff --git a/drivers/scsi/qla2xxx/qla_def.h b/drivers/scsi/qla2xxx/qla_def.h
index ae119018dfaa..eddbc1218a39 100644
--- a/drivers/scsi/qla2xxx/qla_def.h
+++ b/drivers/scsi/qla2xxx/qla_def.h
@@ -3425,6 +3425,7 @@ struct qla_hw_data {
uint8_t max_req_queues;
uint8_t max_rsp_queues;
uint8_t max_qpairs;
+ uint8_t num_qpairs;
struct qla_qpair *base_qpair;
struct qla_npiv_entry *npiv_info;
uint16_t nvram_npiv_size;
diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c
index 034743309ada..0391fc317003 100644
--- a/drivers/scsi/qla2xxx/qla_init.c
+++ b/drivers/scsi/qla2xxx/qla_init.c
@@ -7543,12 +7543,13 @@ struct qla_qpair *qla2xxx_create_qpair(struct scsi_qla_host *vha, int qos, int v
/* Assign available que pair id */
mutex_lock(&ha->mq_lock);
qpair_id = find_first_zero_bit(ha->qpair_qid_map, ha->max_qpairs);
- if (qpair_id >= ha->max_qpairs) {
+ if (ha->num_qpairs >= ha->max_qpairs) {
mutex_unlock(&ha->mq_lock);
ql_log(ql_log_warn, vha, 0x0183,
"No resources to create additional q pair.\n");
goto fail_qid_map;
}
+ ha->num_qpairs++;
set_bit(qpair_id, ha->qpair_qid_map);
ha->queue_pair_map[qpair_id] = qpair;
qpair->id = qpair_id;
@@ -7635,6 +7636,7 @@ fail_rsp:
fail_msix:
ha->queue_pair_map[qpair_id] = NULL;
clear_bit(qpair_id, ha->qpair_qid_map);
+ ha->num_qpairs--;
mutex_unlock(&ha->mq_lock);
fail_qid_map:
kfree(qpair);
@@ -7660,6 +7662,7 @@ int qla2xxx_delete_qpair(struct scsi_qla_host *vha, struct qla_qpair *qpair)
mutex_lock(&ha->mq_lock);
ha->queue_pair_map[qpair->id] = NULL;
clear_bit(qpair->id, ha->qpair_qid_map);
+ ha->num_qpairs--;
list_del(&qpair->qp_list_elem);
if (list_empty(&vha->qp_list))
vha->flags.qpairs_available = 0;
diff --git a/drivers/scsi/qla2xxx/qla_inline.h b/drivers/scsi/qla2xxx/qla_inline.h
index 66df6cec59da..c61a6a871c8e 100644
--- a/drivers/scsi/qla2xxx/qla_inline.h
+++ b/drivers/scsi/qla2xxx/qla_inline.h
@@ -129,28 +129,16 @@ qla2x00_clear_loop_id(fc_port_t *fcport) {
}
static inline void
-qla2x00_clean_dsd_pool(struct qla_hw_data *ha, srb_t *sp,
- struct qla_tgt_cmd *tc)
+qla2x00_clean_dsd_pool(struct qla_hw_data *ha, struct crc_context *ctx)
{
- struct dsd_dma *dsd_ptr, *tdsd_ptr;
- struct crc_context *ctx;
-
- if (sp)
- ctx = (struct crc_context *)GET_CMD_CTX_SP(sp);
- else if (tc)
- ctx = (struct crc_context *)tc->ctx;
- else {
- BUG();
- return;
- }
+ struct dsd_dma *dsd, *tdsd;
/* clean up allocated prev pool */
- list_for_each_entry_safe(dsd_ptr, tdsd_ptr,
- &ctx->dsd_list, list) {
- dma_pool_free(ha->dl_dma_pool, dsd_ptr->dsd_addr,
- dsd_ptr->dsd_list_dma);
- list_del(&dsd_ptr->list);
- kfree(dsd_ptr);
+ list_for_each_entry_safe(dsd, tdsd, &ctx->dsd_list, list) {
+ dma_pool_free(ha->dl_dma_pool, dsd->dsd_addr,
+ dsd->dsd_list_dma);
+ list_del(&dsd->list);
+ kfree(dsd);
}
INIT_LIST_HEAD(&ctx->dsd_list);
}
diff --git a/drivers/scsi/qla2xxx/qla_isr.c b/drivers/scsi/qla2xxx/qla_isr.c
index aac03504d9a3..2572121b765b 100644
--- a/drivers/scsi/qla2xxx/qla_isr.c
+++ b/drivers/scsi/qla2xxx/qla_isr.c
@@ -3282,7 +3282,7 @@ msix_register_fail:
}
/* Enable MSI-X vector for response queue update for queue 0 */
- if (IS_QLA83XX(ha) || IS_QLA27XX(ha)) {
+ if (IS_QLA25XX(ha) || IS_QLA83XX(ha) || IS_QLA27XX(ha)) {
if (ha->msixbase && ha->mqiobase &&
(ha->max_rsp_queues > 1 || ha->max_req_queues > 1 ||
ql2xmqsupport))
diff --git a/drivers/scsi/qla2xxx/qla_mbx.c b/drivers/scsi/qla2xxx/qla_mbx.c
index a113ab3592a7..cba1fc5e8be9 100644
--- a/drivers/scsi/qla2xxx/qla_mbx.c
+++ b/drivers/scsi/qla2xxx/qla_mbx.c
@@ -3676,15 +3676,6 @@ qla24xx_report_id_acquisition(scsi_qla_host_t *vha,
qlt_update_host_map(vha, id);
}
- fc_host_port_name(vha->host) =
- wwn_to_u64(vha->port_name);
-
- if (qla_ini_mode_enabled(vha))
- ql_dbg(ql_dbg_mbx, vha, 0x1018,
- "FA-WWN portname %016llx (%x)\n",
- fc_host_port_name(vha->host),
- rptid_entry->vp_status);
-
set_bit(REGISTER_FC4_NEEDED, &vha->dpc_flags);
set_bit(REGISTER_FDMI_NEEDED, &vha->dpc_flags);
} else {
@@ -4821,9 +4812,9 @@ qla2x00_echo_test(scsi_qla_host_t *vha, struct msg_echo_lb *mreq,
memset(mcp->mb, 0 , sizeof(mcp->mb));
mcp->mb[0] = MBC_DIAGNOSTIC_ECHO;
- mcp->mb[1] = mreq->options | BIT_6; /* BIT_6 specifies 64bit address */
+ /* BIT_6 specifies 64bit address */
+ mcp->mb[1] = mreq->options | BIT_15 | BIT_6;
if (IS_CNA_CAPABLE(ha)) {
- mcp->mb[1] |= BIT_15;
mcp->mb[2] = vha->fcoe_fcf_idx;
}
mcp->mb[16] = LSW(mreq->rcv_dma);
diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c
index 1c7957903283..79f050256c55 100644
--- a/drivers/scsi/qla2xxx/qla_os.c
+++ b/drivers/scsi/qla2xxx/qla_os.c
@@ -630,29 +630,34 @@ qla2x00_sp_free_dma(void *ptr)
sp->flags &= ~SRB_CRC_PROT_DMA_VALID;
}
+ if (!ctx)
+ goto end;
+
if (sp->flags & SRB_CRC_CTX_DSD_VALID) {
/* List assured to be having elements */
- qla2x00_clean_dsd_pool(ha, sp, NULL);
+ qla2x00_clean_dsd_pool(ha, ctx);
sp->flags &= ~SRB_CRC_CTX_DSD_VALID;
}
if (sp->flags & SRB_CRC_CTX_DMA_VALID) {
- dma_pool_free(ha->dl_dma_pool, ctx,
- ((struct crc_context *)ctx)->crc_ctx_dma);
+ struct crc_context *ctx0 = ctx;
+
+ dma_pool_free(ha->dl_dma_pool, ctx0, ctx0->crc_ctx_dma);
sp->flags &= ~SRB_CRC_CTX_DMA_VALID;
}
if (sp->flags & SRB_FCP_CMND_DMA_VALID) {
- struct ct6_dsd *ctx1 = (struct ct6_dsd *)ctx;
+ struct ct6_dsd *ctx1 = ctx;
dma_pool_free(ha->fcp_cmnd_dma_pool, ctx1->fcp_cmnd,
- ctx1->fcp_cmnd_dma);
+ ctx1->fcp_cmnd_dma);
list_splice(&ctx1->dsd_list, &ha->gbl_dsd_list);
ha->gbl_dsd_inuse -= ctx1->dsd_use_cnt;
ha->gbl_dsd_avail += ctx1->dsd_use_cnt;
mempool_free(ctx1, ha->ctx_mempool);
}
+end:
CMD_SP(cmd) = NULL;
qla2x00_rel_sp(sp);
}
@@ -699,21 +704,24 @@ qla2xxx_qpair_sp_free_dma(void *ptr)
sp->flags &= ~SRB_CRC_PROT_DMA_VALID;
}
+ if (!ctx)
+ goto end;
+
if (sp->flags & SRB_CRC_CTX_DSD_VALID) {
/* List assured to be having elements */
- qla2x00_clean_dsd_pool(ha, sp, NULL);
+ qla2x00_clean_dsd_pool(ha, ctx);
sp->flags &= ~SRB_CRC_CTX_DSD_VALID;
}
if (sp->flags & SRB_CRC_CTX_DMA_VALID) {
- dma_pool_free(ha->dl_dma_pool, ctx,
- ((struct crc_context *)ctx)->crc_ctx_dma);
+ struct crc_context *ctx0 = ctx;
+
+ dma_pool_free(ha->dl_dma_pool, ctx, ctx0->crc_ctx_dma);
sp->flags &= ~SRB_CRC_CTX_DMA_VALID;
}
if (sp->flags & SRB_FCP_CMND_DMA_VALID) {
- struct ct6_dsd *ctx1 = (struct ct6_dsd *)ctx;
-
+ struct ct6_dsd *ctx1 = ctx;
dma_pool_free(ha->fcp_cmnd_dma_pool, ctx1->fcp_cmnd,
ctx1->fcp_cmnd_dma);
list_splice(&ctx1->dsd_list, &ha->gbl_dsd_list);
@@ -721,7 +729,7 @@ qla2xxx_qpair_sp_free_dma(void *ptr)
ha->gbl_dsd_avail += ctx1->dsd_use_cnt;
mempool_free(ctx1, ha->ctx_mempool);
}
-
+end:
CMD_SP(cmd) = NULL;
qla2xxx_rel_qpair_sp(sp->qpair, sp);
}
@@ -1632,7 +1640,7 @@ qla2x00_loop_reset(scsi_qla_host_t *vha)
void
qla2x00_abort_all_cmds(scsi_qla_host_t *vha, int res)
{
- int que, cnt;
+ int que, cnt, status;
unsigned long flags;
srb_t *sp;
struct qla_hw_data *ha = vha->hw;
@@ -1662,8 +1670,12 @@ qla2x00_abort_all_cmds(scsi_qla_host_t *vha, int res)
*/
sp_get(sp);
spin_unlock_irqrestore(&ha->hardware_lock, flags);
- qla2xxx_eh_abort(GET_CMD_SP(sp));
+ status = qla2xxx_eh_abort(GET_CMD_SP(sp));
spin_lock_irqsave(&ha->hardware_lock, flags);
+ /* Get rid of extra reference if immediate exit
+ * from ql2xxx_eh_abort */
+ if (status == FAILED && (qla2x00_isp_reg_stat(ha)))
+ atomic_dec(&sp->ref_count);
}
req->outstanding_cmds[cnt] = NULL;
sp->done(sp, res);
@@ -2623,10 +2635,10 @@ qla2x00_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
if (mem_only) {
if (pci_enable_device_mem(pdev))
- goto probe_out;
+ return ret;
} else {
if (pci_enable_device(pdev))
- goto probe_out;
+ return ret;
}
/* This may fail but that's ok */
@@ -2636,7 +2648,7 @@ qla2x00_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
if (!ha) {
ql_log_pci(ql_log_fatal, pdev, 0x0009,
"Unable to allocate memory for ha.\n");
- goto probe_out;
+ goto disable_device;
}
ql_dbg_pci(ql_dbg_init, pdev, 0x000a,
"Memory allocated for ha=%p.\n", ha);
@@ -3254,7 +3266,7 @@ iospace_config_failed:
pci_release_selected_regions(ha->pdev, ha->bars);
kfree(ha);
-probe_out:
+disable_device:
pci_disable_device(pdev);
return ret;
}
diff --git a/drivers/scsi/qla2xxx/qla_target.c b/drivers/scsi/qla2xxx/qla_target.c
index 0e03ca2ab3e5..e766d8412384 100644
--- a/drivers/scsi/qla2xxx/qla_target.c
+++ b/drivers/scsi/qla2xxx/qla_target.c
@@ -2245,11 +2245,13 @@ static void qlt_unmap_sg(struct scsi_qla_host *vha, struct qla_tgt_cmd *cmd)
pci_unmap_sg(ha->pdev, cmd->prot_sg, cmd->prot_sg_cnt,
cmd->dma_data_direction);
+ if (!cmd->ctx)
+ return;
+
if (cmd->ctx_dsd_alloced)
- qla2x00_clean_dsd_pool(ha, NULL, cmd);
+ qla2x00_clean_dsd_pool(ha, cmd->ctx);
- if (cmd->ctx)
- dma_pool_free(ha->dl_dma_pool, cmd->ctx, cmd->ctx->crc_ctx_dma);
+ dma_pool_free(ha->dl_dma_pool, cmd->ctx, cmd->ctx->crc_ctx_dma);
}
static int qlt_check_reserve_free_req(struct scsi_qla_host *vha,
diff --git a/drivers/scsi/qla2xxx/qla_tmpl.c b/drivers/scsi/qla2xxx/qla_tmpl.c
index 8a58ef3adab4..c197972a3e2d 100644
--- a/drivers/scsi/qla2xxx/qla_tmpl.c
+++ b/drivers/scsi/qla2xxx/qla_tmpl.c
@@ -371,7 +371,7 @@ qla27xx_fwdt_entry_t262(struct scsi_qla_host *vha,
goto done;
}
- if (end <= start || start == 0 || end == 0) {
+ if (end < start || start == 0 || end == 0) {
ql_dbg(ql_dbg_misc, vha, 0xd023,
"%s: unusable range (start=%x end=%x)\n", __func__,
ent->t262.end_addr, ent->t262.start_addr);
diff --git a/drivers/scsi/scsi_debug.c b/drivers/scsi/scsi_debug.c
index 17249c3650fe..3be980d47268 100644
--- a/drivers/scsi/scsi_debug.c
+++ b/drivers/scsi/scsi_debug.c
@@ -245,7 +245,7 @@ struct sdebug_dev_info {
unsigned int channel;
unsigned int target;
u64 lun;
- uuid_be lu_name;
+ uuid_t lu_name;
struct sdebug_host_info *sdbg_host;
unsigned long uas_bm[1];
atomic_t num_in_q;
@@ -965,7 +965,7 @@ static const u64 naa3_comp_c = 0x3111111000000000ULL;
static int inquiry_vpd_83(unsigned char *arr, int port_group_id,
int target_dev_id, int dev_id_num,
const char *dev_id_str, int dev_id_str_len,
- const uuid_be *lu_name)
+ const uuid_t *lu_name)
{
int num, port_a;
char b[32];
@@ -1404,7 +1404,7 @@ static int resp_inquiry(struct scsi_cmnd *scp, struct sdebug_dev_info *devip)
arr[4] = SDEBUG_LONG_INQ_SZ - 5;
arr[5] = (int)have_dif_prot; /* PROTECT bit */
if (sdebug_vpd_use_hostno == 0)
- arr[5] = 0x10; /* claim: implicit TGPS */
+ arr[5] |= 0x10; /* claim: implicit TPGS */
arr[6] = 0x10; /* claim: MultiP */
/* arr[6] |= 0x40; ... claim: EncServ (enclosure services) */
arr[7] = 0xa; /* claim: LINKED + CMDQUE */
@@ -3568,7 +3568,7 @@ static void sdebug_q_cmd_wq_complete(struct work_struct *work)
}
static bool got_shared_uuid;
-static uuid_be shared_uuid;
+static uuid_t shared_uuid;
static struct sdebug_dev_info *sdebug_device_create(
struct sdebug_host_info *sdbg_host, gfp_t flags)
@@ -3578,12 +3578,12 @@ static struct sdebug_dev_info *sdebug_device_create(
devip = kzalloc(sizeof(*devip), flags);
if (devip) {
if (sdebug_uuid_ctl == 1)
- uuid_be_gen(&devip->lu_name);
+ uuid_gen(&devip->lu_name);
else if (sdebug_uuid_ctl == 2) {
if (got_shared_uuid)
devip->lu_name = shared_uuid;
else {
- uuid_be_gen(&shared_uuid);
+ uuid_gen(&shared_uuid);
got_shared_uuid = true;
devip->lu_name = shared_uuid;
}
diff --git a/drivers/scsi/scsi_error.c b/drivers/scsi/scsi_error.c
index ecc07dab893d..304a7158540f 100644
--- a/drivers/scsi/scsi_error.c
+++ b/drivers/scsi/scsi_error.c
@@ -1874,7 +1874,7 @@ int scsi_decide_disposition(struct scsi_cmnd *scmd)
}
}
-static void eh_lock_door_done(struct request *req, int uptodate)
+static void eh_lock_door_done(struct request *req, blk_status_t status)
{
__blk_put_request(req->q, req);
}
@@ -1903,7 +1903,6 @@ static void scsi_eh_lock_door(struct scsi_device *sdev)
if (IS_ERR(req))
return;
rq = scsi_req(req);
- scsi_req_init(req);
rq->cmd[0] = ALLOW_MEDIUM_REMOVAL;
rq->cmd[1] = 0;
diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c
index e31f1cc90b81..550e29f903b7 100644
--- a/drivers/scsi/scsi_lib.c
+++ b/drivers/scsi/scsi_lib.c
@@ -250,7 +250,6 @@ int scsi_execute(struct scsi_device *sdev, const unsigned char *cmd,
if (IS_ERR(req))
return ret;
rq = scsi_req(req);
- scsi_req_init(req);
if (bufflen && blk_rq_map_kern(sdev->request_queue, req,
buffer, bufflen, __GFP_RECLAIM))
@@ -635,7 +634,7 @@ static void scsi_release_bidi_buffers(struct scsi_cmnd *cmd)
cmd->request->next_rq->special = NULL;
}
-static bool scsi_end_request(struct request *req, int error,
+static bool scsi_end_request(struct request *req, blk_status_t error,
unsigned int bytes, unsigned int bidi_bytes)
{
struct scsi_cmnd *cmd = req->special;
@@ -694,45 +693,28 @@ static bool scsi_end_request(struct request *req, int error,
* @cmd: SCSI command (unused)
* @result: scsi error code
*
- * Translate SCSI error code into standard UNIX errno.
- * Return values:
- * -ENOLINK temporary transport failure
- * -EREMOTEIO permanent target failure, do not retry
- * -EBADE permanent nexus failure, retry on other path
- * -ENOSPC No write space available
- * -ENODATA Medium error
- * -EIO unspecified I/O error
+ * Translate SCSI error code into block errors.
*/
-static int __scsi_error_from_host_byte(struct scsi_cmnd *cmd, int result)
+static blk_status_t __scsi_error_from_host_byte(struct scsi_cmnd *cmd,
+ int result)
{
- int error = 0;
-
- switch(host_byte(result)) {
+ switch (host_byte(result)) {
case DID_TRANSPORT_FAILFAST:
- error = -ENOLINK;
- break;
+ return BLK_STS_TRANSPORT;
case DID_TARGET_FAILURE:
set_host_byte(cmd, DID_OK);
- error = -EREMOTEIO;
- break;
+ return BLK_STS_TARGET;
case DID_NEXUS_FAILURE:
- set_host_byte(cmd, DID_OK);
- error = -EBADE;
- break;
+ return BLK_STS_NEXUS;
case DID_ALLOC_FAILURE:
set_host_byte(cmd, DID_OK);
- error = -ENOSPC;
- break;
+ return BLK_STS_NOSPC;
case DID_MEDIUM_ERROR:
set_host_byte(cmd, DID_OK);
- error = -ENODATA;
- break;
+ return BLK_STS_MEDIUM;
default:
- error = -EIO;
- break;
+ return BLK_STS_IOERR;
}
-
- return error;
}
/*
@@ -769,7 +751,7 @@ void scsi_io_completion(struct scsi_cmnd *cmd, unsigned int good_bytes)
int result = cmd->result;
struct request_queue *q = cmd->device->request_queue;
struct request *req = cmd->request;
- int error = 0;
+ blk_status_t error = BLK_STS_OK;
struct scsi_sense_hdr sshdr;
bool sense_valid = false;
int sense_deferred = 0, level = 0;
@@ -808,7 +790,7 @@ void scsi_io_completion(struct scsi_cmnd *cmd, unsigned int good_bytes)
* both sides at once.
*/
scsi_req(req->next_rq)->resid_len = scsi_in(cmd)->resid;
- if (scsi_end_request(req, 0, blk_rq_bytes(req),
+ if (scsi_end_request(req, BLK_STS_OK, blk_rq_bytes(req),
blk_rq_bytes(req->next_rq)))
BUG();
return;
@@ -850,7 +832,7 @@ void scsi_io_completion(struct scsi_cmnd *cmd, unsigned int good_bytes)
scsi_print_sense(cmd);
result = 0;
/* for passthrough error may be set */
- error = 0;
+ error = BLK_STS_OK;
}
/*
@@ -922,18 +904,18 @@ void scsi_io_completion(struct scsi_cmnd *cmd, unsigned int good_bytes)
action = ACTION_REPREP;
} else if (sshdr.asc == 0x10) /* DIX */ {
action = ACTION_FAIL;
- error = -EILSEQ;
+ error = BLK_STS_PROTECTION;
/* INVALID COMMAND OPCODE or INVALID FIELD IN CDB */
} else if (sshdr.asc == 0x20 || sshdr.asc == 0x24) {
action = ACTION_FAIL;
- error = -EREMOTEIO;
+ error = BLK_STS_TARGET;
} else
action = ACTION_FAIL;
break;
case ABORTED_COMMAND:
action = ACTION_FAIL;
if (sshdr.asc == 0x10) /* DIF */
- error = -EILSEQ;
+ error = BLK_STS_PROTECTION;
break;
case NOT_READY:
/* If the device is in the process of becoming
@@ -1134,6 +1116,20 @@ err_exit:
}
EXPORT_SYMBOL(scsi_init_io);
+/**
+ * scsi_initialize_rq - initialize struct scsi_cmnd.req
+ *
+ * Called from inside blk_get_request().
+ */
+void scsi_initialize_rq(struct request *rq)
+{
+ struct scsi_cmnd *cmd = blk_mq_rq_to_pdu(rq);
+
+ scsi_req_init(&cmd->req);
+}
+EXPORT_SYMBOL(scsi_initialize_rq);
+
+/* Called after a request has been started. */
void scsi_init_command(struct scsi_device *dev, struct scsi_cmnd *cmd)
{
void *buf = cmd->sense_buffer;
@@ -1829,15 +1825,15 @@ out_delay:
blk_delay_queue(q, SCSI_QUEUE_DELAY);
}
-static inline int prep_to_mq(int ret)
+static inline blk_status_t prep_to_mq(int ret)
{
switch (ret) {
case BLKPREP_OK:
- return BLK_MQ_RQ_QUEUE_OK;
+ return BLK_STS_OK;
case BLKPREP_DEFER:
- return BLK_MQ_RQ_QUEUE_BUSY;
+ return BLK_STS_RESOURCE;
default:
- return BLK_MQ_RQ_QUEUE_ERROR;
+ return BLK_STS_IOERR;
}
}
@@ -1851,7 +1847,7 @@ static int scsi_mq_prep_fn(struct request *req)
/* zero out the cmd, except for the embedded scsi_request */
memset((char *)cmd + sizeof(cmd->req), 0,
- sizeof(*cmd) - sizeof(cmd->req));
+ sizeof(*cmd) - sizeof(cmd->req) + shost->hostt->cmd_size);
req->special = cmd;
@@ -1909,7 +1905,7 @@ static void scsi_mq_done(struct scsi_cmnd *cmd)
blk_mq_complete_request(cmd->request);
}
-static int scsi_queue_rq(struct blk_mq_hw_ctx *hctx,
+static blk_status_t scsi_queue_rq(struct blk_mq_hw_ctx *hctx,
const struct blk_mq_queue_data *bd)
{
struct request *req = bd->rq;
@@ -1917,14 +1913,14 @@ static int scsi_queue_rq(struct blk_mq_hw_ctx *hctx,
struct scsi_device *sdev = q->queuedata;
struct Scsi_Host *shost = sdev->host;
struct scsi_cmnd *cmd = blk_mq_rq_to_pdu(req);
- int ret;
+ blk_status_t ret;
int reason;
ret = prep_to_mq(scsi_prep_state_check(sdev, req));
- if (ret != BLK_MQ_RQ_QUEUE_OK)
+ if (ret != BLK_STS_OK)
goto out;
- ret = BLK_MQ_RQ_QUEUE_BUSY;
+ ret = BLK_STS_RESOURCE;
if (!get_device(&sdev->sdev_gendev))
goto out;
@@ -1937,7 +1933,7 @@ static int scsi_queue_rq(struct blk_mq_hw_ctx *hctx,
if (!(req->rq_flags & RQF_DONTPREP)) {
ret = prep_to_mq(scsi_mq_prep_fn(req));
- if (ret != BLK_MQ_RQ_QUEUE_OK)
+ if (ret != BLK_STS_OK)
goto out_dec_host_busy;
req->rq_flags |= RQF_DONTPREP;
} else {
@@ -1955,11 +1951,11 @@ static int scsi_queue_rq(struct blk_mq_hw_ctx *hctx,
reason = scsi_dispatch_cmd(cmd);
if (reason) {
scsi_set_blocked(cmd, reason);
- ret = BLK_MQ_RQ_QUEUE_BUSY;
+ ret = BLK_STS_RESOURCE;
goto out_dec_host_busy;
}
- return BLK_MQ_RQ_QUEUE_OK;
+ return BLK_STS_OK;
out_dec_host_busy:
atomic_dec(&shost->host_busy);
@@ -1972,12 +1968,14 @@ out_put_device:
put_device(&sdev->sdev_gendev);
out:
switch (ret) {
- case BLK_MQ_RQ_QUEUE_BUSY:
+ case BLK_STS_OK:
+ break;
+ case BLK_STS_RESOURCE:
if (atomic_read(&sdev->device_busy) == 0 &&
!scsi_device_blocked(sdev))
blk_mq_delay_run_hw_queue(hctx, SCSI_QUEUE_DELAY);
break;
- case BLK_MQ_RQ_QUEUE_ERROR:
+ default:
/*
* Make sure to release all allocated ressources when
* we hit an error, as we will never see this command
@@ -1986,8 +1984,6 @@ out:
if (req->rq_flags & RQF_DONTPREP)
scsi_mq_uninit_cmd(cmd);
break;
- default:
- break;
}
return ret;
}
@@ -2057,6 +2053,8 @@ void __scsi_init_queue(struct Scsi_Host *shost, struct request_queue *q)
{
struct device *dev = shost->dma_dev;
+ queue_flag_set_unlocked(QUEUE_FLAG_SCSI_PASSTHROUGH, q);
+
/*
* this limit is imposed by hardware restrictions
*/
@@ -2139,6 +2137,7 @@ struct request_queue *scsi_alloc_queue(struct scsi_device *sdev)
q->request_fn = scsi_request_fn;
q->init_rq_fn = scsi_init_rq;
q->exit_rq_fn = scsi_exit_rq;
+ q->initialize_rq_fn = scsi_initialize_rq;
if (blk_init_allocated_queue(q) < 0) {
blk_cleanup_queue(q);
@@ -2163,6 +2162,7 @@ static const struct blk_mq_ops scsi_mq_ops = {
#endif
.init_request = scsi_init_request,
.exit_request = scsi_exit_request,
+ .initialize_rq_fn = scsi_initialize_rq,
.map_queues = scsi_map_queues,
};
@@ -2977,7 +2977,7 @@ scsi_internal_device_block(struct scsi_device *sdev, bool wait)
if (wait)
blk_mq_quiesce_queue(q);
else
- blk_mq_stop_hw_queues(q);
+ blk_mq_quiesce_queue_nowait(q);
} else {
spin_lock_irqsave(q->queue_lock, flags);
blk_stop_queue(q);
@@ -3031,7 +3031,7 @@ scsi_internal_device_unblock(struct scsi_device *sdev,
return -EINVAL;
if (q->mq_ops) {
- blk_mq_start_stopped_hw_queues(q, false);
+ blk_mq_unquiesce_queue(q);
} else {
spin_lock_irqsave(q->queue_lock, flags);
blk_start_queue(q);
diff --git a/drivers/scsi/scsi_transport_sas.c b/drivers/scsi/scsi_transport_sas.c
index 0ebe2f1bb908..5006a656e16a 100644
--- a/drivers/scsi/scsi_transport_sas.c
+++ b/drivers/scsi/scsi_transport_sas.c
@@ -33,6 +33,7 @@
#include <linux/bsg.h>
#include <scsi/scsi.h>
+#include <scsi/scsi_cmnd.h>
#include <scsi/scsi_request.h>
#include <scsi/scsi_device.h>
#include <scsi/scsi_host.h>
@@ -172,7 +173,7 @@ static void sas_smp_request(struct request_queue *q, struct Scsi_Host *shost,
struct sas_rphy *rphy)
{
struct request *req;
- int ret;
+ blk_status_t ret;
int (*handler)(struct Scsi_Host *, struct sas_rphy *, struct request *);
while ((req = blk_fetch_request(q)) != NULL) {
@@ -230,6 +231,7 @@ static int sas_bsg_initialize(struct Scsi_Host *shost, struct sas_rphy *rphy)
q = blk_alloc_queue(GFP_KERNEL);
if (!q)
return -ENOMEM;
+ q->initialize_rq_fn = scsi_initialize_rq;
q->cmd_size = sizeof(struct scsi_request);
if (rphy) {
@@ -249,6 +251,11 @@ static int sas_bsg_initialize(struct Scsi_Host *shost, struct sas_rphy *rphy)
if (error)
goto out_cleanup_queue;
+ /*
+ * by default assume old behaviour and bounce for any highmem page
+ */
+ blk_queue_bounce_limit(q, BLK_BOUNCE_HIGH);
+
error = bsg_register_queue(q, dev, name, release);
if (error)
goto out_cleanup_queue;
@@ -264,6 +271,7 @@ static int sas_bsg_initialize(struct Scsi_Host *shost, struct sas_rphy *rphy)
q->queuedata = shost;
queue_flag_set_unlocked(QUEUE_FLAG_BIDI, q);
+ queue_flag_set_unlocked(QUEUE_FLAG_SCSI_PASSTHROUGH, q);
return 0;
out_cleanup_queue:
diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c
index f9d1432d7cc5..b6bb4e0ce0e3 100644
--- a/drivers/scsi/sd.c
+++ b/drivers/scsi/sd.c
@@ -827,21 +827,32 @@ static int sd_setup_write_zeroes_cmnd(struct scsi_cmnd *cmd)
struct scsi_disk *sdkp = scsi_disk(rq->rq_disk);
u64 sector = blk_rq_pos(rq) >> (ilog2(sdp->sector_size) - 9);
u32 nr_sectors = blk_rq_sectors(rq) >> (ilog2(sdp->sector_size) - 9);
+ int ret;
if (!(rq->cmd_flags & REQ_NOUNMAP)) {
switch (sdkp->zeroing_mode) {
case SD_ZERO_WS16_UNMAP:
- return sd_setup_write_same16_cmnd(cmd, true);
+ ret = sd_setup_write_same16_cmnd(cmd, true);
+ goto out;
case SD_ZERO_WS10_UNMAP:
- return sd_setup_write_same10_cmnd(cmd, true);
+ ret = sd_setup_write_same10_cmnd(cmd, true);
+ goto out;
}
}
if (sdp->no_write_same)
return BLKPREP_INVALID;
+
if (sdkp->ws16 || sector > 0xffffffff || nr_sectors > 0xffff)
- return sd_setup_write_same16_cmnd(cmd, false);
- return sd_setup_write_same10_cmnd(cmd, false);
+ ret = sd_setup_write_same16_cmnd(cmd, false);
+ else
+ ret = sd_setup_write_same10_cmnd(cmd, false);
+
+out:
+ if (sd_is_zoned(sdkp) && ret == BLKPREP_OK)
+ return sd_zbc_write_lock_zone(cmd);
+
+ return ret;
}
static void sd_config_write_same(struct scsi_disk *sdkp)
@@ -948,6 +959,10 @@ static int sd_setup_write_same_cmnd(struct scsi_cmnd *cmd)
rq->__data_len = sdp->sector_size;
ret = scsi_init_io(cmd);
rq->__data_len = nr_bytes;
+
+ if (sd_is_zoned(sdkp) && ret != BLKPREP_OK)
+ sd_zbc_write_unlock_zone(cmd);
+
return ret;
}
@@ -1567,17 +1582,21 @@ out:
return retval;
}
-static int sd_sync_cache(struct scsi_disk *sdkp)
+static int sd_sync_cache(struct scsi_disk *sdkp, struct scsi_sense_hdr *sshdr)
{
int retries, res;
struct scsi_device *sdp = sdkp->device;
const int timeout = sdp->request_queue->rq_timeout
* SD_FLUSH_TIMEOUT_MULTIPLIER;
- struct scsi_sense_hdr sshdr;
+ struct scsi_sense_hdr my_sshdr;
if (!scsi_device_online(sdp))
return -ENODEV;
+ /* caller might not be interested in sense, but we need it */
+ if (!sshdr)
+ sshdr = &my_sshdr;
+
for (retries = 3; retries > 0; --retries) {
unsigned char cmd[10] = { 0 };
@@ -1586,7 +1605,7 @@ static int sd_sync_cache(struct scsi_disk *sdkp)
* Leave the rest of the command zero to indicate
* flush everything.
*/
- res = scsi_execute(sdp, cmd, DMA_NONE, NULL, 0, NULL, &sshdr,
+ res = scsi_execute(sdp, cmd, DMA_NONE, NULL, 0, NULL, sshdr,
timeout, SD_MAX_RETRIES, 0, RQF_PM, NULL);
if (res == 0)
break;
@@ -1596,11 +1615,12 @@ static int sd_sync_cache(struct scsi_disk *sdkp)
sd_print_result(sdkp, "Synchronize Cache(10) failed", res);
if (driver_byte(res) & DRIVER_SENSE)
- sd_print_sense_hdr(sdkp, &sshdr);
+ sd_print_sense_hdr(sdkp, sshdr);
+
/* we need to evaluate the error return */
- if (scsi_sense_valid(&sshdr) &&
- (sshdr.asc == 0x3a || /* medium not present */
- sshdr.asc == 0x20)) /* invalid command */
+ if (scsi_sense_valid(sshdr) &&
+ (sshdr->asc == 0x3a || /* medium not present */
+ sshdr->asc == 0x20)) /* invalid command */
/* this is no error here */
return 0;
@@ -3444,7 +3464,7 @@ static void sd_shutdown(struct device *dev)
if (sdkp->WCE && sdkp->media_present) {
sd_printk(KERN_NOTICE, sdkp, "Synchronizing SCSI cache\n");
- sd_sync_cache(sdkp);
+ sd_sync_cache(sdkp, NULL);
}
if (system_state != SYSTEM_RESTART && sdkp->device->manage_start_stop) {
@@ -3456,6 +3476,7 @@ static void sd_shutdown(struct device *dev)
static int sd_suspend_common(struct device *dev, bool ignore_stop_errors)
{
struct scsi_disk *sdkp = dev_get_drvdata(dev);
+ struct scsi_sense_hdr sshdr;
int ret = 0;
if (!sdkp) /* E.g.: runtime suspend following sd_remove() */
@@ -3463,12 +3484,23 @@ static int sd_suspend_common(struct device *dev, bool ignore_stop_errors)
if (sdkp->WCE && sdkp->media_present) {
sd_printk(KERN_NOTICE, sdkp, "Synchronizing SCSI cache\n");
- ret = sd_sync_cache(sdkp);
+ ret = sd_sync_cache(sdkp, &sshdr);
+
if (ret) {
/* ignore OFFLINE device */
if (ret == -ENODEV)
- ret = 0;
- goto done;
+ return 0;
+
+ if (!scsi_sense_valid(&sshdr) ||
+ sshdr.sense_key != ILLEGAL_REQUEST)
+ return ret;
+
+ /*
+ * sshdr.sense_key == ILLEGAL_REQUEST means this drive
+ * doesn't support sync. There's not much to do and
+ * suspend shouldn't fail.
+ */
+ ret = 0;
}
}
@@ -3480,7 +3512,6 @@ static int sd_suspend_common(struct device *dev, bool ignore_stop_errors)
ret = 0;
}
-done:
return ret;
}
diff --git a/drivers/scsi/sg.c b/drivers/scsi/sg.c
index 0a38ba01b7b4..21225d62b0c1 100644
--- a/drivers/scsi/sg.c
+++ b/drivers/scsi/sg.c
@@ -177,7 +177,7 @@ typedef struct sg_device { /* holds the state of each scsi generic device */
} Sg_device;
/* tasklet or soft irq callback */
-static void sg_rq_end_io(struct request *rq, int uptodate);
+static void sg_rq_end_io(struct request *rq, blk_status_t status);
static int sg_start_req(Sg_request *srp, unsigned char *cmd);
static int sg_finish_rem_req(Sg_request * srp);
static int sg_build_indirect(Sg_scatter_hold * schp, Sg_fd * sfp, int buff_size);
@@ -808,7 +808,7 @@ sg_common_write(Sg_fd * sfp, Sg_request * srp,
if (atomic_read(&sdp->detaching)) {
if (srp->bio) {
scsi_req_free_cmd(scsi_req(srp->rq));
- blk_end_request_all(srp->rq, -EIO);
+ blk_end_request_all(srp->rq, BLK_STS_IOERR);
srp->rq = NULL;
}
@@ -1300,7 +1300,7 @@ sg_rq_end_io_usercontext(struct work_struct *work)
* level when a command is completed (or has failed).
*/
static void
-sg_rq_end_io(struct request *rq, int uptodate)
+sg_rq_end_io(struct request *rq, blk_status_t status)
{
struct sg_request *srp = rq->end_io_data;
struct scsi_request *req = scsi_req(rq);
@@ -1732,8 +1732,6 @@ sg_start_req(Sg_request *srp, unsigned char *cmd)
}
req = scsi_req(rq);
- scsi_req_init(rq);
-
if (hp->cmd_len > BLK_MAX_CDB)
req->cmd = long_cmdp;
memcpy(req->cmd, cmd, hp->cmd_len);
@@ -2074,11 +2072,12 @@ sg_get_rq_mark(Sg_fd * sfp, int pack_id)
if ((1 == resp->done) && (!resp->sg_io_owned) &&
((-1 == pack_id) || (resp->header.pack_id == pack_id))) {
resp->done = 2; /* guard against other readers */
- break;
+ write_unlock_irqrestore(&sfp->rq_list_lock, iflags);
+ return resp;
}
}
write_unlock_irqrestore(&sfp->rq_list_lock, iflags);
- return resp;
+ return NULL;
}
/* always adds to end of list */
diff --git a/drivers/scsi/st.c b/drivers/scsi/st.c
index 1ea34d6f5437..8e5013d9cad4 100644
--- a/drivers/scsi/st.c
+++ b/drivers/scsi/st.c
@@ -511,7 +511,7 @@ static void st_do_stats(struct scsi_tape *STp, struct request *req)
atomic64_dec(&STp->stats->in_flight);
}
-static void st_scsi_execute_end(struct request *req, int uptodate)
+static void st_scsi_execute_end(struct request *req, blk_status_t status)
{
struct st_request *SRpnt = req->end_io_data;
struct scsi_request *rq = scsi_req(req);
@@ -549,7 +549,6 @@ static int st_scsi_execute(struct st_request *SRpnt, const unsigned char *cmd,
if (IS_ERR(req))
return DRIVER_ERROR << 24;
rq = scsi_req(req);
- scsi_req_init(req);
req->rq_flags |= RQF_QUIET;
mdata->null_mapped = 1;
diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c
index abc7e87937cc..ffe8d8608818 100644
--- a/drivers/scsi/ufs/ufshcd.c
+++ b/drivers/scsi/ufs/ufshcd.c
@@ -7698,6 +7698,12 @@ static inline void ufshcd_add_sysfs_nodes(struct ufs_hba *hba)
ufshcd_add_spm_lvl_sysfs_nodes(hba);
}
+static inline void ufshcd_remove_sysfs_nodes(struct ufs_hba *hba)
+{
+ device_remove_file(hba->dev, &hba->rpm_lvl_attr);
+ device_remove_file(hba->dev, &hba->spm_lvl_attr);
+}
+
/**
* ufshcd_shutdown - shutdown routine
* @hba: per adapter instance
@@ -7735,6 +7741,7 @@ EXPORT_SYMBOL(ufshcd_shutdown);
*/
void ufshcd_remove(struct ufs_hba *hba)
{
+ ufshcd_remove_sysfs_nodes(hba);
scsi_remove_host(hba->host);
/* disable interrupts */
ufshcd_disable_intr(hba, hba->intr_mask);
diff --git a/drivers/staging/android/ion/ion-ioctl.c b/drivers/staging/android/ion/ion-ioctl.c
index 76427e4773a8..d9f8b1424da1 100644
--- a/drivers/staging/android/ion/ion-ioctl.c
+++ b/drivers/staging/android/ion/ion-ioctl.c
@@ -83,8 +83,8 @@ long ion_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
int fd;
fd = ion_alloc(data.allocation.len,
- data.allocation.heap_id_mask,
- data.allocation.flags);
+ data.allocation.heap_id_mask,
+ data.allocation.flags);
if (fd < 0)
return fd;
diff --git a/drivers/staging/android/ion/ion.c b/drivers/staging/android/ion/ion.c
index 03d3a4fce0e2..93e2c90fa77d 100644
--- a/drivers/staging/android/ion/ion.c
+++ b/drivers/staging/android/ion/ion.c
@@ -103,7 +103,7 @@ static struct ion_buffer *ion_buffer_create(struct ion_heap *heap,
goto err2;
}
- if (buffer->sg_table == NULL) {
+ if (!buffer->sg_table) {
WARN_ONCE(1, "This heap needs to set the sgtable");
ret = -EINVAL;
goto err1;
@@ -115,7 +115,6 @@ static struct ion_buffer *ion_buffer_create(struct ion_heap *heap,
buffer->dev = dev;
buffer->size = len;
- INIT_LIST_HEAD(&buffer->vmas);
INIT_LIST_HEAD(&buffer->attachments);
mutex_init(&buffer->lock);
mutex_lock(&dev->buffer_lock);
@@ -135,7 +134,6 @@ void ion_buffer_destroy(struct ion_buffer *buffer)
if (WARN_ON(buffer->kmap_cnt > 0))
buffer->heap->ops->unmap_kernel(buffer->heap, buffer);
buffer->heap->ops->free(buffer);
- vfree(buffer->pages);
kfree(buffer);
}
@@ -163,7 +161,7 @@ static void *ion_buffer_kmap_get(struct ion_buffer *buffer)
return buffer->vaddr;
}
vaddr = buffer->heap->ops->map_kernel(buffer->heap, buffer);
- if (WARN_ONCE(vaddr == NULL,
+ if (WARN_ONCE(!vaddr,
"heap->ops->map_kernel should return ERR_PTR on error"))
return ERR_PTR(-EINVAL);
if (IS_ERR(vaddr))
@@ -221,7 +219,7 @@ struct ion_dma_buf_attachment {
};
static int ion_dma_buf_attach(struct dma_buf *dmabuf, struct device *dev,
- struct dma_buf_attachment *attachment)
+ struct dma_buf_attachment *attachment)
{
struct ion_dma_buf_attachment *a;
struct sg_table *table;
@@ -264,26 +262,19 @@ static void ion_dma_buf_detatch(struct dma_buf *dmabuf,
kfree(a);
}
-
static struct sg_table *ion_map_dma_buf(struct dma_buf_attachment *attachment,
enum dma_data_direction direction)
{
struct ion_dma_buf_attachment *a = attachment->priv;
struct sg_table *table;
- int ret;
table = a->table;
if (!dma_map_sg(attachment->dev, table->sgl, table->nents,
- direction)){
- ret = -ENOMEM;
- goto err;
- }
- return table;
+ direction))
+ return ERR_PTR(-ENOMEM);
-err:
- free_duped_table(table);
- return ERR_PTR(ret);
+ return table;
}
static void ion_unmap_dma_buf(struct dma_buf_attachment *attachment,
@@ -354,11 +345,10 @@ static int ion_dma_buf_begin_cpu_access(struct dma_buf *dmabuf,
mutex_unlock(&buffer->lock);
}
-
mutex_lock(&buffer->lock);
list_for_each_entry(a, &buffer->attachments, list) {
dma_sync_sg_for_cpu(a->dev, a->table->sgl, a->table->nents,
- DMA_BIDIRECTIONAL);
+ DMA_BIDIRECTIONAL);
}
mutex_unlock(&buffer->lock);
@@ -380,7 +370,7 @@ static int ion_dma_buf_end_cpu_access(struct dma_buf *dmabuf,
mutex_lock(&buffer->lock);
list_for_each_entry(a, &buffer->attachments, list) {
dma_sync_sg_for_device(a->dev, a->table->sgl, a->table->nents,
- DMA_BIDIRECTIONAL);
+ DMA_BIDIRECTIONAL);
}
mutex_unlock(&buffer->lock);
@@ -435,7 +425,7 @@ int ion_alloc(size_t len, unsigned int heap_id_mask, unsigned int flags)
}
up_read(&dev->lock);
- if (buffer == NULL)
+ if (!buffer)
return -ENODEV;
if (IS_ERR(buffer))
@@ -596,7 +586,7 @@ void ion_device_add_heap(struct ion_heap *heap)
}
EXPORT_SYMBOL(ion_device_add_heap);
-int ion_device_create(void)
+static int ion_device_create(void)
{
struct ion_device *idev;
int ret;
diff --git a/drivers/staging/android/ion/ion.h b/drivers/staging/android/ion/ion.h
index ace8416bd509..fa9ed81ab972 100644
--- a/drivers/staging/android/ion/ion.h
+++ b/drivers/staging/android/ion/ion.h
@@ -68,14 +68,6 @@ struct ion_platform_heap {
* @kmap_cnt: number of times the buffer is mapped to the kernel
* @vaddr: the kernel mapping if kmap_cnt is not zero
* @sg_table: the sg table for the buffer if dmap_cnt is not zero
- * @pages: flat array of pages in the buffer -- used by fault
- * handler and only valid for buffers that are faulted in
- * @vmas: list of vma's mapping this buffer
- * @handle_count: count of handles referencing this buffer
- * @task_comm: taskcomm of last client to reference this buffer in a
- * handle, used for debugging
- * @pid: pid of last client to reference this buffer in a
- * handle, used for debugging
*/
struct ion_buffer {
union {
@@ -92,13 +84,7 @@ struct ion_buffer {
int kmap_cnt;
void *vaddr;
struct sg_table *sg_table;
- struct page **pages;
- struct list_head vmas;
struct list_head attachments;
- /* used to track orphaned buffers */
- int handle_count;
- char task_comm[TASK_COMM_LEN];
- pid_t pid;
};
void ion_buffer_destroy(struct ion_buffer *buffer);
diff --git a/drivers/staging/android/ion/ion_carveout_heap.c b/drivers/staging/android/ion/ion_carveout_heap.c
index 5fdc1f328f61..fee7650d6fbb 100644
--- a/drivers/staging/android/ion/ion_carveout_heap.c
+++ b/drivers/staging/android/ion/ion_carveout_heap.c
@@ -33,7 +33,7 @@ struct ion_carveout_heap {
};
static phys_addr_t ion_carveout_allocate(struct ion_heap *heap,
- unsigned long size)
+ unsigned long size)
{
struct ion_carveout_heap *carveout_heap =
container_of(heap, struct ion_carveout_heap, heap);
diff --git a/drivers/staging/android/ion/ion_system_heap.c b/drivers/staging/android/ion/ion_system_heap.c
index c50f2d9fc58c..5964bf21fd80 100644
--- a/drivers/staging/android/ion/ion_system_heap.c
+++ b/drivers/staging/android/ion/ion_system_heap.c
@@ -153,7 +153,7 @@ static int ion_system_heap_allocate(struct ion_heap *heap,
max_order = compound_order(page);
i++;
}
- table = kmalloc(sizeof(struct sg_table), GFP_KERNEL);
+ table = kmalloc(sizeof(*table), GFP_KERNEL);
if (!table)
goto free_pages;
@@ -383,7 +383,7 @@ static int ion_system_contig_heap_allocate(struct ion_heap *heap,
for (i = len >> PAGE_SHIFT; i < (1 << order); i++)
__free_page(page + i);
- table = kmalloc(sizeof(struct sg_table), GFP_KERNEL);
+ table = kmalloc(sizeof(*table), GFP_KERNEL);
if (!table) {
ret = -ENOMEM;
goto free_pages;
@@ -433,7 +433,7 @@ static struct ion_heap *__ion_system_contig_heap_create(void)
{
struct ion_heap *heap;
- heap = kzalloc(sizeof(struct ion_heap), GFP_KERNEL);
+ heap = kzalloc(sizeof(*heap), GFP_KERNEL);
if (!heap)
return ERR_PTR(-ENOMEM);
heap->ops = &kmalloc_ops;
diff --git a/drivers/staging/android/uapi/ion.h b/drivers/staging/android/uapi/ion.h
index b76db1b2e197..9e21451149d0 100644
--- a/drivers/staging/android/uapi/ion.h
+++ b/drivers/staging/android/uapi/ion.h
@@ -57,12 +57,6 @@ enum ion_heap_type {
*/
#define ION_FLAG_CACHED 1
-/*
- * mappings of this buffer will created at mmap time, if this is set
- * caches must be managed manually
- */
-#define ION_FLAG_CACHED_NEEDS_SYNC 2
-
/**
* DOC: Ion Userspace API
*
@@ -131,24 +125,6 @@ struct ion_heap_query {
struct ion_allocation_data)
/**
- * DOC: ION_IOC_FREE - free memory
- *
- * Takes an ion_handle_data struct and frees the handle.
- */
-#define ION_IOC_FREE _IOWR(ION_IOC_MAGIC, 1, struct ion_handle_data)
-
-/**
- * DOC: ION_IOC_SHARE - creates a file descriptor to use to share an allocation
- *
- * Takes an ion_fd_data struct with the handle field populated with a valid
- * opaque handle. Returns the struct with the fd field set to a file
- * descriptor open in the current address space. This file descriptor
- * can then be passed to another process. The corresponding opaque handle can
- * be retrieved via ION_IOC_IMPORT.
- */
-#define ION_IOC_SHARE _IOWR(ION_IOC_MAGIC, 4, struct ion_fd_data)
-
-/**
* DOC: ION_IOC_HEAP_QUERY - information about available heaps
*
* Takes an ion_heap_query structure and populates information about
diff --git a/drivers/staging/ccree/Kconfig b/drivers/staging/ccree/Kconfig
index ae627049c499..36a87c686a2a 100644
--- a/drivers/staging/ccree/Kconfig
+++ b/drivers/staging/ccree/Kconfig
@@ -1,6 +1,6 @@
config CRYPTO_DEV_CCREE
tristate "Support for ARM TrustZone CryptoCell C7XX family of Crypto accelerators"
- depends on CRYPTO_HW && OF && HAS_DMA
+ depends on CRYPTO && CRYPTO_HW && OF && HAS_DMA
default n
select CRYPTO_HASH
select CRYPTO_BLKCIPHER
@@ -18,7 +18,7 @@ config CRYPTO_DEV_CCREE
select CRYPTO_CTR
select CRYPTO_XTS
help
- Say 'Y' to enable a driver for the Arm TrustZone CryptoCell
+ Say 'Y' to enable a driver for the Arm TrustZone CryptoCell
C7xx. Currently only the CryptoCell 712 REE is supported.
Choose this if you wish to use hardware acceleration of
cryptographic operations on the system REE.
@@ -32,12 +32,3 @@ config CCREE_FIPS_SUPPORT
Say 'Y' to enable support for FIPS compliant mode by the
CCREE driver.
If unsure say N.
-
-config CCREE_DISABLE_COHERENT_DMA_OPS
- bool "Disable Coherent DMA operations for the CCREE driver"
- depends on CRYPTO_DEV_CCREE
- default n
- help
- Say 'Y' to disable the use of coherent DMA operations by the
- CCREE driver for debugging purposes.
- If unsure say N.
diff --git a/drivers/staging/ccree/Makefile b/drivers/staging/ccree/Makefile
index 44f3e3e33989..318c2b39acf6 100644
--- a/drivers/staging/ccree/Makefile
+++ b/drivers/staging/ccree/Makefile
@@ -1,3 +1,3 @@
obj-$(CONFIG_CRYPTO_DEV_CCREE) := ccree.o
-ccree-y := ssi_driver.o ssi_sysfs.o ssi_buffer_mgr.o ssi_request_mgr.o ssi_cipher.o ssi_hash.o ssi_aead.o ssi_ivgen.o ssi_sram_mgr.o ssi_pm.o ssi_pm_ext.o
+ccree-y := ssi_driver.o ssi_sysfs.o ssi_buffer_mgr.o ssi_request_mgr.o ssi_cipher.o ssi_hash.o ssi_aead.o ssi_ivgen.o ssi_sram_mgr.o ssi_pm.o
ccree-$(CCREE_FIPS_SUPPORT) += ssi_fips.o ssi_fips_ll.o ssi_fips_ext.o ssi_fips_local.o
diff --git a/drivers/staging/ccree/cc_bitops.h b/drivers/staging/ccree/cc_bitops.h
deleted file mode 100644
index 3a39565ef73b..000000000000
--- a/drivers/staging/ccree/cc_bitops.h
+++ /dev/null
@@ -1,62 +0,0 @@
-/*
- * Copyright (C) 2012-2017 ARM Limited or its affiliates.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, see <http://www.gnu.org/licenses/>.
- */
-
-/*!
- * \file cc_bitops.h
- * Bit fields operations macros.
- */
-#ifndef _CC_BITOPS_H_
-#define _CC_BITOPS_H_
-
-#define BITMASK(mask_size) (((mask_size) < 32) ? \
- ((1UL << (mask_size)) - 1) : 0xFFFFFFFFUL)
-#define BITMASK_AT(mask_size, mask_offset) (BITMASK(mask_size) << (mask_offset))
-
-#define BITFIELD_GET(word, bit_offset, bit_size) \
- (((word) >> (bit_offset)) & BITMASK(bit_size))
-#define BITFIELD_SET(word, bit_offset, bit_size, new_val) do { \
- word = ((word) & ~BITMASK_AT(bit_size, bit_offset)) | \
- (((new_val) & BITMASK(bit_size)) << (bit_offset)); \
-} while (0)
-
-/* Is val aligned to "align" ("align" must be power of 2) */
-#ifndef IS_ALIGNED
-#define IS_ALIGNED(val, align) \
- (((uintptr_t)(val) & ((align) - 1)) == 0)
-#endif
-
-#define SWAP_ENDIAN(word) \
- (((word) >> 24) | (((word) & 0x00FF0000) >> 8) | \
- (((word) & 0x0000FF00) << 8) | (((word) & 0x000000FF) << 24))
-
-#ifdef BIG__ENDIAN
-#define SWAP_TO_LE(word) SWAP_ENDIAN(word)
-#define SWAP_TO_BE(word) word
-#else
-#define SWAP_TO_LE(word) word
-#define SWAP_TO_BE(word) SWAP_ENDIAN(word)
-#endif
-
-
-
-/* Is val a multiple of "mult" ("mult" must be power of 2) */
-#define IS_MULT(val, mult) \
- (((val) & ((mult) - 1)) == 0)
-
-#define IS_NULL_ADDR(adr) \
- (!(adr))
-
-#endif /*_CC_BITOPS_H_*/
diff --git a/drivers/staging/ccree/cc_crypto_ctx.h b/drivers/staging/ccree/cc_crypto_ctx.h
index 9e10b2670313..591f6fdadc59 100644
--- a/drivers/staging/ccree/cc_crypto_ctx.h
+++ b/drivers/staging/ccree/cc_crypto_ctx.h
@@ -1,35 +1,23 @@
/*
* Copyright (C) 2012-2017 ARM Limited or its affiliates.
- *
+ *
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
- *
+ *
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
- *
+ *
* You should have received a copy of the GNU General Public License
* along with this program; if not, see <http://www.gnu.org/licenses/>.
*/
-
#ifndef _CC_CRYPTO_CTX_H_
#define _CC_CRYPTO_CTX_H_
-#ifdef __KERNEL__
#include <linux/types.h>
-#define INT32_MAX 0x7FFFFFFFL
-#else
-#include <stdint.h>
-#endif
-
-
-#ifndef max
-#define max(a, b) ((a) > (b) ? (a) : (b))
-#define min(a, b) ((a) < (b) ? (a) : (b))
-#endif
/* context size */
#ifndef CC_CTX_SIZE_LOG2
@@ -39,7 +27,7 @@
#define CC_CTX_SIZE_LOG2 7
#endif
#endif
-#define CC_CTX_SIZE (1<<CC_CTX_SIZE_LOG2)
+#define CC_CTX_SIZE BIT(CC_CTX_SIZE_LOG2)
#define CC_DRV_CTX_SIZE_WORDS (CC_CTX_SIZE >> 2)
#define CC_DRV_DES_IV_SIZE 8
@@ -65,13 +53,13 @@
#define CC_AES_KEY_SIZE_MAX CC_AES_256_BIT_KEY_SIZE
#define CC_AES_KEY_SIZE_WORDS_MAX (CC_AES_KEY_SIZE_MAX >> 2)
-#define CC_MD5_DIGEST_SIZE 16
-#define CC_SHA1_DIGEST_SIZE 20
-#define CC_SHA224_DIGEST_SIZE 28
-#define CC_SHA256_DIGEST_SIZE 32
+#define CC_MD5_DIGEST_SIZE 16
+#define CC_SHA1_DIGEST_SIZE 20
+#define CC_SHA224_DIGEST_SIZE 28
+#define CC_SHA256_DIGEST_SIZE 32
#define CC_SHA256_DIGEST_SIZE_IN_WORDS 8
-#define CC_SHA384_DIGEST_SIZE 48
-#define CC_SHA512_DIGEST_SIZE 64
+#define CC_SHA384_DIGEST_SIZE 48
+#define CC_SHA512_DIGEST_SIZE 64
#define CC_SHA1_BLOCK_SIZE 64
#define CC_SHA1_BLOCK_SIZE_IN_WORDS 16
@@ -94,18 +82,17 @@
#define CC_HMAC_BLOCK_SIZE_MAX CC_HASH_BLOCK_SIZE_MAX
-#define CC_MULTI2_SYSTEM_KEY_SIZE 32
-#define CC_MULTI2_DATA_KEY_SIZE 8
-#define CC_MULTI2_SYSTEM_N_DATA_KEY_SIZE (CC_MULTI2_SYSTEM_KEY_SIZE + CC_MULTI2_DATA_KEY_SIZE)
+#define CC_MULTI2_SYSTEM_KEY_SIZE 32
+#define CC_MULTI2_DATA_KEY_SIZE 8
+#define CC_MULTI2_SYSTEM_N_DATA_KEY_SIZE \
+ (CC_MULTI2_SYSTEM_KEY_SIZE + CC_MULTI2_DATA_KEY_SIZE)
#define CC_MULTI2_BLOCK_SIZE 8
#define CC_MULTI2_IV_SIZE 8
#define CC_MULTI2_MIN_NUM_ROUNDS 8
#define CC_MULTI2_MAX_NUM_ROUNDS 128
-
#define CC_DRV_ALG_MAX_BLOCK_SIZE CC_HASH_BLOCK_SIZE_MAX
-
enum drv_engine_type {
DRV_ENGINE_NULL = 0,
DRV_ENGINE_AES = 1,
@@ -113,7 +100,7 @@ enum drv_engine_type {
DRV_ENGINE_HASH = 3,
DRV_ENGINE_RC4 = 4,
DRV_ENGINE_DOUT = 5,
- DRV_ENGINE_RESERVE32B = INT32_MAX,
+ DRV_ENGINE_RESERVE32B = S32_MAX,
};
enum drv_crypto_alg {
@@ -126,7 +113,7 @@ enum drv_crypto_alg {
DRV_CRYPTO_ALG_AEAD = 5,
DRV_CRYPTO_ALG_BYPASS = 6,
DRV_CRYPTO_ALG_NUM = 7,
- DRV_CRYPTO_ALG_RESERVE32B = INT32_MAX
+ DRV_CRYPTO_ALG_RESERVE32B = S32_MAX
};
enum drv_crypto_direction {
@@ -134,7 +121,7 @@ enum drv_crypto_direction {
DRV_CRYPTO_DIRECTION_ENCRYPT = 0,
DRV_CRYPTO_DIRECTION_DECRYPT = 1,
DRV_CRYPTO_DIRECTION_DECRYPT_ENCRYPT = 3,
- DRV_CRYPTO_DIRECTION_RESERVE32B = INT32_MAX
+ DRV_CRYPTO_DIRECTION_RESERVE32B = S32_MAX
};
enum drv_cipher_mode {
@@ -152,7 +139,7 @@ enum drv_cipher_mode {
DRV_CIPHER_GCTR = 12,
DRV_CIPHER_ESSIV = 13,
DRV_CIPHER_BITLOCKER = 14,
- DRV_CIPHER_RESERVE32B = INT32_MAX
+ DRV_CIPHER_RESERVE32B = S32_MAX
};
enum drv_hash_mode {
@@ -163,11 +150,11 @@ enum drv_hash_mode {
DRV_HASH_SHA512 = 3,
DRV_HASH_SHA384 = 4,
DRV_HASH_MD5 = 5,
- DRV_HASH_CBC_MAC = 6,
+ DRV_HASH_CBC_MAC = 6,
DRV_HASH_XCBC_MAC = 7,
DRV_HASH_CMAC = 8,
DRV_HASH_MODE_NUM = 9,
- DRV_HASH_RESERVE32B = INT32_MAX
+ DRV_HASH_RESERVE32B = S32_MAX
};
enum drv_hash_hw_mode {
@@ -178,7 +165,7 @@ enum drv_hash_hw_mode {
DRV_HASH_HW_SHA512 = 4,
DRV_HASH_HW_SHA384 = 12,
DRV_HASH_HW_GHASH = 6,
- DRV_HASH_HW_RESERVE32B = INT32_MAX
+ DRV_HASH_HW_RESERVE32B = S32_MAX
};
enum drv_multi2_mode {
@@ -186,10 +173,9 @@ enum drv_multi2_mode {
DRV_MULTI2_ECB = 0,
DRV_MULTI2_CBC = 1,
DRV_MULTI2_OFB = 2,
- DRV_MULTI2_RESERVE32B = INT32_MAX
+ DRV_MULTI2_RESERVE32B = S32_MAX
};
-
/* drv_crypto_key_type[1:0] is mapped to cipher_do[1:0] */
/* drv_crypto_key_type[2] is mapped to cipher_config2 */
enum drv_crypto_key_type {
@@ -201,99 +187,14 @@ enum drv_crypto_key_type {
DRV_APPLET_KEY = 4, /* NA */
DRV_PLATFORM_KEY = 5, /* 0x101 */
DRV_CUSTOMER_KEY = 6, /* 0x110 */
- DRV_END_OF_KEYS = INT32_MAX,
+ DRV_END_OF_KEYS = S32_MAX,
};
enum drv_crypto_padding_type {
DRV_PADDING_NONE = 0,
DRV_PADDING_PKCS7 = 1,
- DRV_PADDING_RESERVE32B = INT32_MAX
+ DRV_PADDING_RESERVE32B = S32_MAX
};
-/*******************************************************************/
-/***************** DESCRIPTOR BASED CONTEXTS ***********************/
-/*******************************************************************/
-
- /* Generic context ("super-class") */
-struct drv_ctx_generic {
- enum drv_crypto_alg alg;
-} __attribute__((__may_alias__));
-
-
-struct drv_ctx_hash {
- enum drv_crypto_alg alg; /* DRV_CRYPTO_ALG_HASH */
- enum drv_hash_mode mode;
- uint8_t digest[CC_DIGEST_SIZE_MAX];
- /* reserve to end of allocated context size */
- uint8_t reserved[CC_CTX_SIZE - 2 * sizeof(uint32_t) -
- CC_DIGEST_SIZE_MAX];
-};
-
-/* !!!! drv_ctx_hmac should have the same structure as drv_ctx_hash except
- k0, k0_size fields */
-struct drv_ctx_hmac {
- enum drv_crypto_alg alg; /* DRV_CRYPTO_ALG_HMAC */
- enum drv_hash_mode mode;
- uint8_t digest[CC_DIGEST_SIZE_MAX];
- uint32_t k0[CC_HMAC_BLOCK_SIZE_MAX/sizeof(uint32_t)];
- uint32_t k0_size;
- /* reserve to end of allocated context size */
- uint8_t reserved[CC_CTX_SIZE - 3 * sizeof(uint32_t) -
- CC_DIGEST_SIZE_MAX - CC_HMAC_BLOCK_SIZE_MAX];
-};
-
-struct drv_ctx_cipher {
- enum drv_crypto_alg alg; /* DRV_CRYPTO_ALG_AES */
- enum drv_cipher_mode mode;
- enum drv_crypto_direction direction;
- enum drv_crypto_key_type crypto_key_type;
- enum drv_crypto_padding_type padding_type;
- uint32_t key_size; /* numeric value in bytes */
- uint32_t data_unit_size; /* required for XTS */
- /* block_state is the AES engine block state.
- * It is used by the host to pass IV or counter at initialization.
- * It is used by SeP for intermediate block chaining state and for
- * returning MAC algorithms results. */
- uint8_t block_state[CC_AES_BLOCK_SIZE];
- uint8_t key[CC_AES_KEY_SIZE_MAX];
- uint8_t xex_key[CC_AES_KEY_SIZE_MAX];
- /* reserve to end of allocated context size */
- uint32_t reserved[CC_DRV_CTX_SIZE_WORDS - 7 -
- CC_AES_BLOCK_SIZE/sizeof(uint32_t) - 2 *
- (CC_AES_KEY_SIZE_MAX/sizeof(uint32_t))];
-};
-
-/* authentication and encryption with associated data class */
-struct drv_ctx_aead {
- enum drv_crypto_alg alg; /* DRV_CRYPTO_ALG_AES */
- enum drv_cipher_mode mode;
- enum drv_crypto_direction direction;
- uint32_t key_size; /* numeric value in bytes */
- uint32_t nonce_size; /* nonce size (octets) */
- uint32_t header_size; /* finit additional data size (octets) */
- uint32_t text_size; /* finit text data size (octets) */
- uint32_t tag_size; /* mac size, element of {4, 6, 8, 10, 12, 14, 16} */
- /* block_state1/2 is the AES engine block state */
- uint8_t block_state[CC_AES_BLOCK_SIZE];
- uint8_t mac_state[CC_AES_BLOCK_SIZE]; /* MAC result */
- uint8_t nonce[CC_AES_BLOCK_SIZE]; /* nonce buffer */
- uint8_t key[CC_AES_KEY_SIZE_MAX];
- /* reserve to end of allocated context size */
- uint32_t reserved[CC_DRV_CTX_SIZE_WORDS - 8 -
- 3 * (CC_AES_BLOCK_SIZE/sizeof(uint32_t)) -
- CC_AES_KEY_SIZE_MAX/sizeof(uint32_t)];
-};
-
-/*******************************************************************/
-/***************** MESSAGE BASED CONTEXTS **************************/
-/*******************************************************************/
-
-
-/* Get the address of a @member within a given @ctx address
- @ctx: The context address
- @type: Type of context structure
- @member: Associated context field */
-#define GET_CTX_FIELD_ADDR(ctx, type, member) (ctx + offsetof(type, member))
-
#endif /* _CC_CRYPTO_CTX_H_ */
diff --git a/drivers/staging/ccree/cc_hal.h b/drivers/staging/ccree/cc_hal.h
index 75a0ce3e80d6..eecc866dfc74 100644
--- a/drivers/staging/ccree/cc_hal.h
+++ b/drivers/staging/ccree/cc_hal.h
@@ -1,20 +1,22 @@
/*
* Copyright (C) 2012-2017 ARM Limited or its affiliates.
- *
+ *
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
- *
+ *
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
- *
+ *
* You should have received a copy of the GNU General Public License
* along with this program; if not, see <http://www.gnu.org/licenses/>.
*/
-/* pseudo cc_hal.h for cc7x_perf_test_driver (to be able to include code from CC drivers) */
+/* pseudo cc_hal.h for cc7x_perf_test_driver (to be able to include code from
+ * CC drivers).
+ */
#ifndef __CC_HAL_H__
#define __CC_HAL_H__
@@ -24,7 +26,8 @@
#define READ_REGISTER(_addr) ioread32((_addr))
#define WRITE_REGISTER(_addr, _data) iowrite32((_data), (_addr))
-#define CC_HAL_WRITE_REGISTER(offset, val) WRITE_REGISTER(cc_base + offset, val)
-#define CC_HAL_READ_REGISTER(offset) READ_REGISTER(cc_base + offset)
+#define CC_HAL_WRITE_REGISTER(offset, val) \
+ WRITE_REGISTER(cc_base + (offset), val)
+#define CC_HAL_READ_REGISTER(offset) READ_REGISTER(cc_base + (offset))
#endif
diff --git a/drivers/staging/ccree/cc_hw_queue_defs.h b/drivers/staging/ccree/cc_hw_queue_defs.h
index fbaf1b6fcd90..e6b8cea3f88d 100644
--- a/drivers/staging/ccree/cc_hw_queue_defs.h
+++ b/drivers/staging/ccree/cc_hw_queue_defs.h
@@ -1,15 +1,15 @@
/*
* Copyright (C) 2012-2017 ARM Limited or its affiliates.
- *
+ *
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
- *
+ *
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
- *
+ *
* You should have received a copy of the GNU General Public License
* along with this program; if not, see <http://www.gnu.org/licenses/>.
*/
@@ -17,63 +17,95 @@
#ifndef __CC_HW_QUEUE_DEFS_H__
#define __CC_HW_QUEUE_DEFS_H__
-#include "cc_pal_log.h"
-#include "cc_regs.h"
-#include "dx_crys_kernel.h"
-
-#ifdef __KERNEL__
#include <linux/types.h>
-#define UINT32_MAX 0xFFFFFFFFL
-#define INT32_MAX 0x7FFFFFFFL
-#define UINT16_MAX 0xFFFFL
-#else
-#include <stdint.h>
-#endif
-
-/******************************************************************************
-* DEFINITIONS
-******************************************************************************/
+#include "dx_crys_kernel.h"
+#include <linux/bitfield.h>
-/* Dma AXI Secure bit */
-#define AXI_SECURE 0
-#define AXI_NOT_SECURE 1
+/******************************************************************************
+ * DEFINITIONS
+ ******************************************************************************/
#define HW_DESC_SIZE_WORDS 6
#define HW_QUEUE_SLOTS_MAX 15 /* Max. available slots in HW queue */
-#define _HW_DESC_MONITOR_KICK 0x7FFFC00
+#define CC_REG_NAME(word, name) DX_DSCRPTR_QUEUE_WORD ## word ## _ ## name
+
+#define CC_REG_LOW(word, name) \
+ (DX_DSCRPTR_QUEUE_WORD ## word ## _ ## name ## _BIT_SHIFT)
+
+#define CC_REG_HIGH(word, name) \
+ (CC_REG_LOW(word, name) + \
+ DX_DSCRPTR_QUEUE_WORD ## word ## _ ## name ## _BIT_SIZE - 1)
+
+#define CC_GENMASK(word, name) \
+ GENMASK(CC_REG_HIGH(word, name), CC_REG_LOW(word, name))
+
+#define WORD0_VALUE CC_GENMASK(0, VALUE)
+#define WORD1_DIN_CONST_VALUE CC_GENMASK(1, DIN_CONST_VALUE)
+#define WORD1_DIN_DMA_MODE CC_GENMASK(1, DIN_DMA_MODE)
+#define WORD1_DIN_SIZE CC_GENMASK(1, DIN_SIZE)
+#define WORD1_NOT_LAST CC_GENMASK(1, NOT_LAST)
+#define WORD1_NS_BIT CC_GENMASK(1, NS_BIT)
+#define WORD2_VALUE CC_GENMASK(2, VALUE)
+#define WORD3_DOUT_DMA_MODE CC_GENMASK(3, DOUT_DMA_MODE)
+#define WORD3_DOUT_LAST_IND CC_GENMASK(3, DOUT_LAST_IND)
+#define WORD3_DOUT_SIZE CC_GENMASK(3, DOUT_SIZE)
+#define WORD3_HASH_XOR_BIT CC_GENMASK(3, HASH_XOR_BIT)
+#define WORD3_NS_BIT CC_GENMASK(3, NS_BIT)
+#define WORD3_QUEUE_LAST_IND CC_GENMASK(3, QUEUE_LAST_IND)
+#define WORD4_ACK_NEEDED CC_GENMASK(4, ACK_NEEDED)
+#define WORD4_AES_SEL_N_HASH CC_GENMASK(4, AES_SEL_N_HASH)
+#define WORD4_BYTES_SWAP CC_GENMASK(4, BYTES_SWAP)
+#define WORD4_CIPHER_CONF0 CC_GENMASK(4, CIPHER_CONF0)
+#define WORD4_CIPHER_CONF1 CC_GENMASK(4, CIPHER_CONF1)
+#define WORD4_CIPHER_CONF2 CC_GENMASK(4, CIPHER_CONF2)
+#define WORD4_CIPHER_DO CC_GENMASK(4, CIPHER_DO)
+#define WORD4_CIPHER_MODE CC_GENMASK(4, CIPHER_MODE)
+#define WORD4_CMAC_SIZE0 CC_GENMASK(4, CMAC_SIZE0)
+#define WORD4_DATA_FLOW_MODE CC_GENMASK(4, DATA_FLOW_MODE)
+#define WORD4_KEY_SIZE CC_GENMASK(4, KEY_SIZE)
+#define WORD4_SETUP_OPERATION CC_GENMASK(4, SETUP_OPERATION)
+#define WORD5_DIN_ADDR_HIGH CC_GENMASK(5, DIN_ADDR_HIGH)
+#define WORD5_DOUT_ADDR_HIGH CC_GENMASK(5, DOUT_ADDR_HIGH)
/******************************************************************************
-* TYPE DEFINITIONS
-******************************************************************************/
+ * TYPE DEFINITIONS
+ ******************************************************************************/
+
+struct cc_hw_desc {
+ union {
+ u32 word[HW_DESC_SIZE_WORDS];
+ u16 hword[HW_DESC_SIZE_WORDS * 2];
+ };
+};
-typedef struct HwDesc {
- uint32_t word[HW_DESC_SIZE_WORDS];
-} HwDesc_s;
+enum cc_axi_sec {
+ AXI_SECURE = 0,
+ AXI_NOT_SECURE = 1
+};
-typedef enum DescDirection {
+enum cc_desc_direction {
DESC_DIRECTION_ILLEGAL = -1,
DESC_DIRECTION_ENCRYPT_ENCRYPT = 0,
DESC_DIRECTION_DECRYPT_DECRYPT = 1,
DESC_DIRECTION_DECRYPT_ENCRYPT = 3,
- DESC_DIRECTION_END = INT32_MAX,
-}DescDirection_t;
+ DESC_DIRECTION_END = S32_MAX,
+};
-typedef enum DmaMode {
+enum cc_dma_mode {
DMA_MODE_NULL = -1,
- NO_DMA = 0,
+ NO_DMA = 0,
DMA_SRAM = 1,
DMA_DLLI = 2,
DMA_MLLI = 3,
- DmaMode_OPTIONTS,
- DmaMode_END = INT32_MAX,
-}DmaMode_t;
+ DMA_MODE_END = S32_MAX,
+};
-typedef enum FlowMode {
+enum cc_flow_mode {
FLOW_MODE_NULL = -1,
/* data flows */
- BYPASS = 0,
+ BYPASS = 0,
DIN_AES_DOUT = 1,
AES_to_HASH = 2,
AES_and_HASH = 3,
@@ -93,11 +125,11 @@ typedef enum FlowMode {
DIN_AES_AESMAC = 17,
HASH_to_DOUT = 18,
/* setup flows */
- S_DIN_to_AES = 32,
+ S_DIN_to_AES = 32,
S_DIN_to_AES2 = 33,
S_DIN_to_DES = 34,
S_DIN_to_RC4 = 35,
- S_DIN_to_MULTI2 = 36,
+ S_DIN_to_MULTI2 = 36,
S_DIN_to_HASH = 37,
S_AES_to_DOUT = 38,
S_AES2_to_DOUT = 39,
@@ -105,47 +137,43 @@ typedef enum FlowMode {
S_DES_to_DOUT = 42,
S_HASH_to_DOUT = 43,
SET_FLOW_ID = 44,
- FlowMode_OPTIONTS,
- FlowMode_END = INT32_MAX,
-}FlowMode_t;
+ FLOW_MODE_END = S32_MAX,
+};
-typedef enum TunnelOp {
+enum cc_tunnel_op {
TUNNEL_OP_INVALID = -1,
TUNNEL_OFF = 0,
TUNNEL_ON = 1,
- TunnelOp_OPTIONS,
- TunnelOp_END = INT32_MAX,
-} TunnelOp_t;
+ TUNNEL_OP_END = S32_MAX,
+};
-typedef enum SetupOp {
+enum cc_setup_op {
SETUP_LOAD_NOP = 0,
SETUP_LOAD_STATE0 = 1,
SETUP_LOAD_STATE1 = 2,
SETUP_LOAD_STATE2 = 3,
SETUP_LOAD_KEY0 = 4,
SETUP_LOAD_XEX_KEY = 5,
- SETUP_WRITE_STATE0 = 8,
+ SETUP_WRITE_STATE0 = 8,
SETUP_WRITE_STATE1 = 9,
SETUP_WRITE_STATE2 = 10,
SETUP_WRITE_STATE3 = 11,
- setupOp_OPTIONTS,
- setupOp_END = INT32_MAX,
-}SetupOp_t;
+ SETUP_OP_END = S32_MAX,
+};
-enum AesMacSelector {
+enum cc_aes_mac_selector {
AES_SK = 1,
AES_CMAC_INIT = 2,
AES_CMAC_SIZE0 = 3,
- AesMacEnd = INT32_MAX,
+ AES_MAC_END = S32_MAX,
};
-#define HW_KEY_MASK_CIPHER_DO 0x3
+#define HW_KEY_MASK_CIPHER_DO 0x3
#define HW_KEY_SHIFT_CIPHER_CFG2 2
-
/* HwCryptoKey[1:0] is mapped to cipher_do[1:0] */
/* HwCryptoKey[2:3] is mapped to cipher_config2[1:0] */
-typedef enum HwCryptoKey {
+enum cc_hw_crypto_key {
USER_KEY = 0, /* 0x0000 */
ROOT_KEY = 1, /* 0x0001 */
PROVISIONING_KEY = 2, /* 0x0010 */ /* ==KCP */
@@ -157,447 +185,409 @@ typedef enum HwCryptoKey {
KFDE1_KEY = 9, /* 0x1001 */
KFDE2_KEY = 10, /* 0x1010 */
KFDE3_KEY = 11, /* 0x1011 */
- END_OF_KEYS = INT32_MAX,
-}HwCryptoKey_t;
+ END_OF_KEYS = S32_MAX,
+};
-typedef enum HwAesKeySize {
+enum cc_hw_aes_key_size {
AES_128_KEY = 0,
AES_192_KEY = 1,
AES_256_KEY = 2,
- END_OF_AES_KEYS = INT32_MAX,
-}HwAesKeySize_t;
+ END_OF_AES_KEYS = S32_MAX,
+};
-typedef enum HwDesKeySize {
+enum cc_hw_des_key_size {
DES_ONE_KEY = 0,
DES_TWO_KEYS = 1,
DES_THREE_KEYS = 2,
- END_OF_DES_KEYS = INT32_MAX,
-}HwDesKeySize_t;
+ END_OF_DES_KEYS = S32_MAX,
+};
/*****************************/
/* Descriptor packing macros */
/*****************************/
-#define GET_HW_Q_DESC_WORD_IDX(descWordIdx) (CC_REG_OFFSET(CRY_KERNEL, DSCRPTR_QUEUE_WORD ## descWordIdx) )
-
-#define HW_DESC_INIT(pDesc) do { \
- (pDesc)->word[0] = 0; \
- (pDesc)->word[1] = 0; \
- (pDesc)->word[2] = 0; \
- (pDesc)->word[3] = 0; \
- (pDesc)->word[4] = 0; \
- (pDesc)->word[5] = 0; \
-} while (0)
-
-/* HW descriptor debug functions */
-int createDetailedDump(HwDesc_s *pDesc);
-void descriptor_log(HwDesc_s *desc);
-
-#if defined(HW_DESCRIPTOR_LOG) || defined(HW_DESC_DUMP_HOST_BUF)
-#define LOG_HW_DESC(pDesc) descriptor_log(pDesc)
-#else
-#define LOG_HW_DESC(pDesc)
-#endif
-
-#if (CC_PAL_MAX_LOG_LEVEL >= CC_PAL_LOG_LEVEL_TRACE) || defined(OEMFW_LOG)
-
-#ifdef UART_PRINTF
-#define CREATE_DETAILED_DUMP(pDesc) createDetailedDump(pDesc)
-#else
-#define CREATE_DETAILED_DUMP(pDesc)
-#endif
-
-#define HW_DESC_DUMP(pDesc) do { \
- CC_PAL_LOG_TRACE("\n---------------------------------------------------\n"); \
- CREATE_DETAILED_DUMP(pDesc); \
- CC_PAL_LOG_TRACE("0x%08X, ", (unsigned int)(pDesc)->word[0]); \
- CC_PAL_LOG_TRACE("0x%08X, ", (unsigned int)(pDesc)->word[1]); \
- CC_PAL_LOG_TRACE("0x%08X, ", (unsigned int)(pDesc)->word[2]); \
- CC_PAL_LOG_TRACE("0x%08X, ", (unsigned int)(pDesc)->word[3]); \
- CC_PAL_LOG_TRACE("0x%08X, ", (unsigned int)(pDesc)->word[4]); \
- CC_PAL_LOG_TRACE("0x%08X\n", (unsigned int)(pDesc)->word[5]); \
- CC_PAL_LOG_TRACE("---------------------------------------------------\n\n"); \
-} while (0)
-
-#else
-#define HW_DESC_DUMP(pDesc) do {} while (0)
-#endif
-
-
-/*!
- * This macro indicates the end of current HW descriptors flow and release the HW engines.
- *
- * \param pDesc pointer HW descriptor struct
- */
-#define HW_DESC_SET_QUEUE_LAST_IND(pDesc) \
- do { \
- CC_REG_FLD_SET(CRY_KERNEL, DSCRPTR_QUEUE_WORD3, QUEUE_LAST_IND, (pDesc)->word[3], 1); \
- } while (0)
-
-/*!
- * This macro signs the end of HW descriptors flow by asking for completion ack, and release the HW engines
- *
- * \param pDesc pointer HW descriptor struct
- */
-#define HW_DESC_SET_ACK_LAST(pDesc) \
- do { \
- CC_REG_FLD_SET(CRY_KERNEL, DSCRPTR_QUEUE_WORD3, QUEUE_LAST_IND, (pDesc)->word[3], 1); \
- CC_REG_FLD_SET(CRY_KERNEL, DSCRPTR_QUEUE_WORD4, ACK_NEEDED, (pDesc)->word[4], 1); \
- } while (0)
-
-
-#define MSB64(_addr) (sizeof(_addr) == 4 ? 0 : ((_addr) >> 32)&UINT16_MAX)
-
-/*!
- * This macro sets the DIN field of a HW descriptors
- *
- * \param pDesc pointer HW descriptor struct
- * \param dmaMode The DMA mode: NO_DMA, SRAM, DLLI, MLLI, CONSTANT
- * \param dinAdr DIN address
- * \param dinSize Data size in bytes
- * \param axiNs AXI secure bit
+/*
+ * Init a HW descriptor struct
+ * @pdesc: pointer HW descriptor struct
*/
-#define HW_DESC_SET_DIN_TYPE(pDesc, dmaMode, dinAdr, dinSize, axiNs) \
- do { \
- CC_REG_FLD_SET(CRY_KERNEL, DSCRPTR_QUEUE_WORD0, VALUE, (pDesc)->word[0], (dinAdr)&UINT32_MAX ); \
- CC_REG_FLD_SET(CRY_KERNEL, DSCRPTR_QUEUE_WORD5, DIN_ADDR_HIGH, (pDesc)->word[5], MSB64(dinAdr) ); \
- CC_REG_FLD_SET(CRY_KERNEL, DSCRPTR_QUEUE_WORD1, DIN_DMA_MODE, (pDesc)->word[1], (dmaMode)); \
- CC_REG_FLD_SET(CRY_KERNEL, DSCRPTR_QUEUE_WORD1, DIN_SIZE, (pDesc)->word[1], (dinSize)); \
- CC_REG_FLD_SET(CRY_KERNEL, DSCRPTR_QUEUE_WORD1, NS_BIT, (pDesc)->word[1], (axiNs)); \
- } while (0)
-
-
-/*!
- * This macro sets the DIN field of a HW descriptors to NO DMA mode. Used for NOP descriptor, register patches and
- * other special modes
- *
- * \param pDesc pointer HW descriptor struct
- * \param dinAdr DIN address
- * \param dinSize Data size in bytes
+static inline void hw_desc_init(struct cc_hw_desc *pdesc)
+{
+ memset(pdesc, 0, sizeof(struct cc_hw_desc));
+}
+
+/*
+ * Indicates the end of current HW descriptors flow and release the HW engines.
+ *
+ * @pdesc: pointer HW descriptor struct
*/
-#define HW_DESC_SET_DIN_NO_DMA(pDesc, dinAdr, dinSize) \
- do { \
- CC_REG_FLD_SET(CRY_KERNEL, DSCRPTR_QUEUE_WORD0, VALUE, (pDesc)->word[0], (uint32_t)(dinAdr)); \
- CC_REG_FLD_SET(CRY_KERNEL, DSCRPTR_QUEUE_WORD1, DIN_SIZE, (pDesc)->word[1], (dinSize)); \
- } while (0)
-
-/*!
- * This macro sets the DIN field of a HW descriptors to SRAM mode.
- * Note: No need to check SRAM alignment since host requests do not use SRAM and
- * adaptor will enforce alignment check.
- *
- * \param pDesc pointer HW descriptor struct
- * \param dinAdr DIN address
- * \param dinSize Data size in bytes
+static inline void set_queue_last_ind(struct cc_hw_desc *pdesc)
+{
+ pdesc->word[3] |= FIELD_PREP(WORD3_QUEUE_LAST_IND, 1);
+}
+
+/*
+ * Set the DIN field of a HW descriptors
+ *
+ * @pdesc: pointer HW descriptor struct
+ * @dma_mode: dmaMode The DMA mode: NO_DMA, SRAM, DLLI, MLLI, CONSTANT
+ * @addr: dinAdr DIN address
+ * @size: Data size in bytes
+ * @axi_sec: AXI secure bit
*/
-#define HW_DESC_SET_DIN_SRAM(pDesc, dinAdr, dinSize) \
- do { \
- CC_REG_FLD_SET(CRY_KERNEL, DSCRPTR_QUEUE_WORD0, VALUE, (pDesc)->word[0], (uint32_t)(dinAdr)); \
- CC_REG_FLD_SET(CRY_KERNEL, DSCRPTR_QUEUE_WORD1, DIN_DMA_MODE, (pDesc)->word[1], DMA_SRAM); \
- CC_REG_FLD_SET(CRY_KERNEL, DSCRPTR_QUEUE_WORD1, DIN_SIZE, (pDesc)->word[1], (dinSize)); \
- } while (0)
-
-/*! This macro sets the DIN field of a HW descriptors to CONST mode
- *
- * \param pDesc pointer HW descriptor struct
- * \param val DIN const value
- * \param dinSize Data size in bytes
+static inline void set_din_type(struct cc_hw_desc *pdesc,
+ enum cc_dma_mode dma_mode, dma_addr_t addr,
+ u32 size, enum cc_axi_sec axi_sec)
+{
+ pdesc->word[0] = (u32)addr;
+#ifdef CONFIG_ARCH_DMA_ADDR_T_64BIT
+ pdesc->word[5] |= FIELD_PREP(WORD5_DIN_ADDR_HIGH, ((u16)(addr >> 32)));
+#endif
+ pdesc->word[1] |= FIELD_PREP(WORD1_DIN_DMA_MODE, dma_mode) |
+ FIELD_PREP(WORD1_DIN_SIZE, size) |
+ FIELD_PREP(WORD1_NS_BIT, axi_sec);
+}
+
+/*
+ * Set the DIN field of a HW descriptors to NO DMA mode.
+ * Used for NOP descriptor, register patches and other special modes.
+ *
+ * @pdesc: pointer HW descriptor struct
+ * @addr: DIN address
+ * @size: Data size in bytes
*/
-#define HW_DESC_SET_DIN_CONST(pDesc, val, dinSize) \
- do { \
- CC_REG_FLD_SET(CRY_KERNEL, DSCRPTR_QUEUE_WORD0, VALUE, (pDesc)->word[0], (uint32_t)(val)); \
- CC_REG_FLD_SET(CRY_KERNEL, DSCRPTR_QUEUE_WORD1, DIN_CONST_VALUE, (pDesc)->word[1], 1); \
- CC_REG_FLD_SET(CRY_KERNEL, DSCRPTR_QUEUE_WORD1, DIN_DMA_MODE, (pDesc)->word[1], DMA_SRAM); \
- CC_REG_FLD_SET(CRY_KERNEL, DSCRPTR_QUEUE_WORD1, DIN_SIZE, (pDesc)->word[1], (dinSize)); \
- } while (0)
-
-/*!
- * This macro sets the DIN not last input data indicator
- *
- * \param pDesc pointer HW descriptor struct
+static inline void set_din_no_dma(struct cc_hw_desc *pdesc, u32 addr, u32 size)
+{
+ pdesc->word[0] = addr;
+ pdesc->word[1] |= FIELD_PREP(WORD1_DIN_SIZE, size);
+}
+
+/*
+ * Set the DIN field of a HW descriptors to SRAM mode.
+ * Note: No need to check SRAM alignment since host requests do not use SRAM and
+ * adaptor will enforce alignment check.
+ *
+ * @pdesc: pointer HW descriptor struct
+ * @addr: DIN address
+ * @size Data size in bytes
*/
-#define HW_DESC_SET_DIN_NOT_LAST_INDICATION(pDesc) \
- do { \
- CC_REG_FLD_SET(CRY_KERNEL, DSCRPTR_QUEUE_WORD1, NOT_LAST, (pDesc)->word[1], 1); \
- } while (0)
-
-/*!
- * This macro sets the DOUT field of a HW descriptors
- *
- * \param pDesc pointer HW descriptor struct
- * \param dmaMode The DMA mode: NO_DMA, SRAM, DLLI, MLLI, CONSTANT
- * \param doutAdr DOUT address
- * \param doutSize Data size in bytes
- * \param axiNs AXI secure bit
+static inline void set_din_sram(struct cc_hw_desc *pdesc, dma_addr_t addr,
+ u32 size)
+{
+ pdesc->word[0] = (u32)addr;
+ pdesc->word[1] |= FIELD_PREP(WORD1_DIN_SIZE, size) |
+ FIELD_PREP(WORD1_DIN_DMA_MODE, DMA_SRAM);
+}
+
+/*
+ * Set the DIN field of a HW descriptors to CONST mode
+ *
+ * @pdesc: pointer HW descriptor struct
+ * @val: DIN const value
+ * @size: Data size in bytes
*/
-#define HW_DESC_SET_DOUT_TYPE(pDesc, dmaMode, doutAdr, doutSize, axiNs) \
- do { \
- CC_REG_FLD_SET(CRY_KERNEL, DSCRPTR_QUEUE_WORD2, VALUE, (pDesc)->word[2], (doutAdr)&UINT32_MAX ); \
- CC_REG_FLD_SET(CRY_KERNEL, DSCRPTR_QUEUE_WORD5, DOUT_ADDR_HIGH, (pDesc)->word[5], MSB64(doutAdr) ); \
- CC_REG_FLD_SET(CRY_KERNEL, DSCRPTR_QUEUE_WORD3, DOUT_DMA_MODE, (pDesc)->word[3], (dmaMode)); \
- CC_REG_FLD_SET(CRY_KERNEL, DSCRPTR_QUEUE_WORD3, DOUT_SIZE, (pDesc)->word[3], (doutSize)); \
- CC_REG_FLD_SET(CRY_KERNEL, DSCRPTR_QUEUE_WORD3, NS_BIT, (pDesc)->word[3], (axiNs)); \
- } while (0)
-
-/*!
- * This macro sets the DOUT field of a HW descriptors to DLLI type
- * The LAST INDICATION is provided by the user
- *
- * \param pDesc pointer HW descriptor struct
- * \param doutAdr DOUT address
- * \param doutSize Data size in bytes
- * \param lastInd The last indication bit
- * \param axiNs AXI secure bit
+static inline void set_din_const(struct cc_hw_desc *pdesc, u32 val, u32 size)
+{
+ pdesc->word[0] = val;
+ pdesc->word[1] |= FIELD_PREP(WORD1_DIN_CONST_VALUE, 1) |
+ FIELD_PREP(WORD1_DIN_DMA_MODE, DMA_SRAM) |
+ FIELD_PREP(WORD1_DIN_SIZE, size);
+}
+
+/*
+ * Set the DIN not last input data indicator
+ *
+ * @pdesc: pointer HW descriptor struct
*/
-#define HW_DESC_SET_DOUT_DLLI(pDesc, doutAdr, doutSize, axiNs ,lastInd) \
- do { \
- CC_REG_FLD_SET(CRY_KERNEL, DSCRPTR_QUEUE_WORD2, VALUE, (pDesc)->word[2], (doutAdr)&UINT32_MAX ); \
- CC_REG_FLD_SET(CRY_KERNEL, DSCRPTR_QUEUE_WORD5, DOUT_ADDR_HIGH, (pDesc)->word[5], MSB64(doutAdr) ); \
- CC_REG_FLD_SET(CRY_KERNEL, DSCRPTR_QUEUE_WORD3, DOUT_DMA_MODE, (pDesc)->word[3], DMA_DLLI); \
- CC_REG_FLD_SET(CRY_KERNEL, DSCRPTR_QUEUE_WORD3, DOUT_SIZE, (pDesc)->word[3], (doutSize)); \
- CC_REG_FLD_SET(CRY_KERNEL, DSCRPTR_QUEUE_WORD3, DOUT_LAST_IND, (pDesc)->word[3], lastInd); \
- CC_REG_FLD_SET(CRY_KERNEL, DSCRPTR_QUEUE_WORD3, NS_BIT, (pDesc)->word[3], (axiNs)); \
- } while (0)
-
-/*!
- * This macro sets the DOUT field of a HW descriptors to DLLI type
- * The LAST INDICATION is provided by the user
- *
- * \param pDesc pointer HW descriptor struct
- * \param doutAdr DOUT address
- * \param doutSize Data size in bytes
- * \param lastInd The last indication bit
- * \param axiNs AXI secure bit
+static inline void set_din_not_last_indication(struct cc_hw_desc *pdesc)
+{
+ pdesc->word[1] |= FIELD_PREP(WORD1_NOT_LAST, 1);
+}
+
+/*
+ * Set the DOUT field of a HW descriptors
+ *
+ * @pdesc: pointer HW descriptor struct
+ * @dma_mode: The DMA mode: NO_DMA, SRAM, DLLI, MLLI, CONSTANT
+ * @addr: DOUT address
+ * @size: Data size in bytes
+ * @axi_sec: AXI secure bit
*/
-#define HW_DESC_SET_DOUT_MLLI(pDesc, doutAdr, doutSize, axiNs ,lastInd) \
- do { \
- CC_REG_FLD_SET(CRY_KERNEL, DSCRPTR_QUEUE_WORD2, VALUE, (pDesc)->word[2], (doutAdr)&UINT32_MAX ); \
- CC_REG_FLD_SET(CRY_KERNEL, DSCRPTR_QUEUE_WORD5, DOUT_ADDR_HIGH, (pDesc)->word[5], MSB64(doutAdr) ); \
- CC_REG_FLD_SET(CRY_KERNEL, DSCRPTR_QUEUE_WORD3, DOUT_DMA_MODE, (pDesc)->word[3], DMA_MLLI); \
- CC_REG_FLD_SET(CRY_KERNEL, DSCRPTR_QUEUE_WORD3, DOUT_SIZE, (pDesc)->word[3], (doutSize)); \
- CC_REG_FLD_SET(CRY_KERNEL, DSCRPTR_QUEUE_WORD3, DOUT_LAST_IND, (pDesc)->word[3], lastInd); \
- CC_REG_FLD_SET(CRY_KERNEL, DSCRPTR_QUEUE_WORD3, NS_BIT, (pDesc)->word[3], (axiNs)); \
- } while (0)
-
-/*!
- * This macro sets the DOUT field of a HW descriptors to NO DMA mode. Used for NOP descriptor, register patches and
- * other special modes
- *
- * \param pDesc pointer HW descriptor struct
- * \param doutAdr DOUT address
- * \param doutSize Data size in bytes
- * \param registerWriteEnable Enables a write operation to a register
+static inline void set_dout_type(struct cc_hw_desc *pdesc,
+ enum cc_dma_mode dma_mode, dma_addr_t addr,
+ u32 size, enum cc_axi_sec axi_sec)
+{
+ pdesc->word[2] = (u32)addr;
+#ifdef CONFIG_ARCH_DMA_ADDR_T_64BIT
+ pdesc->word[5] |= FIELD_PREP(WORD5_DOUT_ADDR_HIGH, ((u16)(addr >> 32)));
+#endif
+ pdesc->word[3] |= FIELD_PREP(WORD3_DOUT_DMA_MODE, dma_mode) |
+ FIELD_PREP(WORD3_DOUT_SIZE, size) |
+ FIELD_PREP(WORD3_NS_BIT, axi_sec);
+}
+
+/*
+ * Set the DOUT field of a HW descriptors to DLLI type
+ * The LAST INDICATION is provided by the user
+ *
+ * @pdesc pointer HW descriptor struct
+ * @addr: DOUT address
+ * @size: Data size in bytes
+ * @last_ind: The last indication bit
+ * @axi_sec: AXI secure bit
*/
-#define HW_DESC_SET_DOUT_NO_DMA(pDesc, doutAdr, doutSize, registerWriteEnable) \
- do { \
- CC_REG_FLD_SET(CRY_KERNEL, DSCRPTR_QUEUE_WORD2, VALUE, (pDesc)->word[2], (uint32_t)(doutAdr)); \
- CC_REG_FLD_SET(CRY_KERNEL, DSCRPTR_QUEUE_WORD3, DOUT_SIZE, (pDesc)->word[3], (doutSize)); \
- CC_REG_FLD_SET(CRY_KERNEL, DSCRPTR_QUEUE_WORD3, DOUT_LAST_IND, (pDesc)->word[3], (registerWriteEnable)); \
- } while (0)
-
-/*!
- * This macro sets the word for the XOR operation.
- *
- * \param pDesc pointer HW descriptor struct
- * \param xorVal xor data value
+static inline void set_dout_dlli(struct cc_hw_desc *pdesc, dma_addr_t addr,
+ u32 size, enum cc_axi_sec axi_sec,
+ u32 last_ind)
+{
+ set_dout_type(pdesc, DMA_DLLI, addr, size, axi_sec);
+ pdesc->word[3] |= FIELD_PREP(WORD3_DOUT_LAST_IND, last_ind);
+}
+
+/*
+ * Set the DOUT field of a HW descriptors to DLLI type
+ * The LAST INDICATION is provided by the user
+ *
+ * @pdesc: pointer HW descriptor struct
+ * @addr: DOUT address
+ * @size: Data size in bytes
+ * @last_ind: The last indication bit
+ * @axi_sec: AXI secure bit
*/
-#define HW_DESC_SET_XOR_VAL(pDesc, xorVal) \
- do { \
- CC_REG_FLD_SET(CRY_KERNEL, DSCRPTR_QUEUE_WORD2, VALUE, (pDesc)->word[2], (uint32_t)(xorVal)); \
- } while (0)
-
-/*!
- * This macro sets the XOR indicator bit in the descriptor
- *
- * \param pDesc pointer HW descriptor struct
+static inline void set_dout_mlli(struct cc_hw_desc *pdesc, dma_addr_t addr,
+ u32 size, enum cc_axi_sec axi_sec,
+ bool last_ind)
+{
+ set_dout_type(pdesc, DMA_MLLI, addr, size, axi_sec);
+ pdesc->word[3] |= FIELD_PREP(WORD3_DOUT_LAST_IND, last_ind);
+}
+
+/*
+ * Set the DOUT field of a HW descriptors to NO DMA mode.
+ * Used for NOP descriptor, register patches and other special modes.
+ *
+ * @pdesc: pointer HW descriptor struct
+ * @addr: DOUT address
+ * @size: Data size in bytes
+ * @write_enable: Enables a write operation to a register
*/
-#define HW_DESC_SET_XOR_ACTIVE(pDesc) \
- do { \
- CC_REG_FLD_SET(CRY_KERNEL, DSCRPTR_QUEUE_WORD3, HASH_XOR_BIT, (pDesc)->word[3], 1); \
- } while (0)
-
-/*!
- * This macro selects the AES engine instead of HASH engine when setting up combined mode with AES XCBC MAC
- *
- * \param pDesc pointer HW descriptor struct
+static inline void set_dout_no_dma(struct cc_hw_desc *pdesc, u32 addr,
+ u32 size, bool write_enable)
+{
+ pdesc->word[2] = addr;
+ pdesc->word[3] |= FIELD_PREP(WORD3_DOUT_SIZE, size) |
+ FIELD_PREP(WORD3_DOUT_LAST_IND, write_enable);
+}
+
+/*
+ * Set the word for the XOR operation.
+ *
+ * @pdesc: pointer HW descriptor struct
+ * @val: xor data value
*/
-#define HW_DESC_SET_AES_NOT_HASH_MODE(pDesc) \
- do { \
- CC_REG_FLD_SET(CRY_KERNEL, DSCRPTR_QUEUE_WORD4, AES_SEL_N_HASH, (pDesc)->word[4], 1); \
- } while (0)
-
-/*!
- * This macro sets the DOUT field of a HW descriptors to SRAM mode
- * Note: No need to check SRAM alignment since host requests do not use SRAM and
- * adaptor will enforce alignment check.
- *
- * \param pDesc pointer HW descriptor struct
- * \param doutAdr DOUT address
- * \param doutSize Data size in bytes
+static inline void set_xor_val(struct cc_hw_desc *pdesc, u32 val)
+{
+ pdesc->word[2] = val;
+}
+
+/*
+ * Sets the XOR indicator bit in the descriptor
+ *
+ * @pdesc: pointer HW descriptor struct
*/
-#define HW_DESC_SET_DOUT_SRAM(pDesc, doutAdr, doutSize) \
- do { \
- CC_REG_FLD_SET(CRY_KERNEL, DSCRPTR_QUEUE_WORD2, VALUE, (pDesc)->word[2], (uint32_t)(doutAdr)); \
- CC_REG_FLD_SET(CRY_KERNEL, DSCRPTR_QUEUE_WORD3, DOUT_DMA_MODE, (pDesc)->word[3], DMA_SRAM); \
- CC_REG_FLD_SET(CRY_KERNEL, DSCRPTR_QUEUE_WORD3, DOUT_SIZE, (pDesc)->word[3], (doutSize)); \
- } while (0)
-
-
-/*!
- * This macro sets the data unit size for XEX mode in data_out_addr[15:0]
- *
- * \param pDesc pointer HW descriptor struct
- * \param dataUnitSize data unit size for XEX mode
+static inline void set_xor_active(struct cc_hw_desc *pdesc)
+{
+ pdesc->word[3] |= FIELD_PREP(WORD3_HASH_XOR_BIT, 1);
+}
+
+/*
+ * Select the AES engine instead of HASH engine when setting up combined mode
+ * with AES XCBC MAC
+ *
+ * @pdesc: pointer HW descriptor struct
*/
-#define HW_DESC_SET_XEX_DATA_UNIT_SIZE(pDesc, dataUnitSize) \
- do { \
- CC_REG_FLD_SET(CRY_KERNEL, DSCRPTR_QUEUE_WORD2, VALUE, (pDesc)->word[2], (uint32_t)(dataUnitSize)); \
- } while (0)
+static inline void set_aes_not_hash_mode(struct cc_hw_desc *pdesc)
+{
+ pdesc->word[4] |= FIELD_PREP(WORD4_AES_SEL_N_HASH, 1);
+}
-/*!
- * This macro sets the number of rounds for Multi2 in data_out_addr[15:0]
+/*
+ * Set the DOUT field of a HW descriptors to SRAM mode
+ * Note: No need to check SRAM alignment since host requests do not use SRAM and
+ * adaptor will enforce alignment check.
*
- * \param pDesc pointer HW descriptor struct
- * \param numRounds number of rounds for Multi2
-*/
-#define HW_DESC_SET_MULTI2_NUM_ROUNDS(pDesc, numRounds) \
- do { \
- CC_REG_FLD_SET(CRY_KERNEL, DSCRPTR_QUEUE_WORD2, VALUE, (pDesc)->word[2], (uint32_t)(numRounds)); \
- } while (0)
-
-/*!
- * This macro sets the flow mode.
+ * @pdesc: pointer HW descriptor struct
+ * @addr: DOUT address
+ * @size: Data size in bytes
+ */
+static inline void set_dout_sram(struct cc_hw_desc *pdesc, u32 addr, u32 size)
+{
+ pdesc->word[2] = addr;
+ pdesc->word[3] |= FIELD_PREP(WORD3_DOUT_DMA_MODE, DMA_SRAM) |
+ FIELD_PREP(WORD3_DOUT_SIZE, size);
+}
+
+/*
+ * Sets the data unit size for XEX mode in data_out_addr[15:0]
*
- * \param pDesc pointer HW descriptor struct
- * \param flowMode Any one of the modes defined in [CC7x-DESC]
-*/
+ * @pdesc: pDesc pointer HW descriptor struct
+ * @size: data unit size for XEX mode
+ */
+static inline void set_xex_data_unit_size(struct cc_hw_desc *pdesc, u32 size)
+{
+ pdesc->word[2] = size;
+}
-#define HW_DESC_SET_FLOW_MODE(pDesc, flowMode) \
- do { \
- CC_REG_FLD_SET(CRY_KERNEL, DSCRPTR_QUEUE_WORD4, DATA_FLOW_MODE, (pDesc)->word[4], (flowMode)); \
- } while (0)
+/*
+ * Set the number of rounds for Multi2 in data_out_addr[15:0]
+ *
+ * @pdesc: pointer HW descriptor struct
+ * @num: number of rounds for Multi2
+ */
+static inline void set_multi2_num_rounds(struct cc_hw_desc *pdesc, u32 num)
+{
+ pdesc->word[2] = num;
+}
-/*!
- * This macro sets the cipher mode.
+/*
+ * Set the flow mode.
*
- * \param pDesc pointer HW descriptor struct
- * \param cipherMode Any one of the modes defined in [CC7x-DESC]
-*/
-#define HW_DESC_SET_CIPHER_MODE(pDesc, cipherMode) \
- do { \
- CC_REG_FLD_SET(CRY_KERNEL, DSCRPTR_QUEUE_WORD4, CIPHER_MODE, (pDesc)->word[4], (cipherMode)); \
- } while (0)
-
-/*!
- * This macro sets the cipher configuration fields.
+ * @pdesc: pointer HW descriptor struct
+ * @mode: Any one of the modes defined in [CC7x-DESC]
+ */
+static inline void set_flow_mode(struct cc_hw_desc *pdesc,
+ enum cc_flow_mode mode)
+{
+ pdesc->word[4] |= FIELD_PREP(WORD4_DATA_FLOW_MODE, mode);
+}
+
+/*
+ * Set the cipher mode.
*
- * \param pDesc pointer HW descriptor struct
- * \param cipherConfig Any one of the modes defined in [CC7x-DESC]
-*/
-#define HW_DESC_SET_CIPHER_CONFIG0(pDesc, cipherConfig) \
- do { \
- CC_REG_FLD_SET(CRY_KERNEL, DSCRPTR_QUEUE_WORD4, CIPHER_CONF0, (pDesc)->word[4], (cipherConfig)); \
- } while (0)
-
-/*!
- * This macro sets the cipher configuration fields.
+ * @pdesc: pointer HW descriptor struct
+ * @mode: Any one of the modes defined in [CC7x-DESC]
+ */
+static inline void set_cipher_mode(struct cc_hw_desc *pdesc,
+ enum drv_cipher_mode mode)
+{
+ pdesc->word[4] |= FIELD_PREP(WORD4_CIPHER_MODE, mode);
+}
+
+/*
+ * Set the cipher configuration fields.
*
- * \param pDesc pointer HW descriptor struct
- * \param cipherConfig Any one of the modes defined in [CC7x-DESC]
-*/
-#define HW_DESC_SET_CIPHER_CONFIG1(pDesc, cipherConfig) \
- do { \
- CC_REG_FLD_SET(CRY_KERNEL, DSCRPTR_QUEUE_WORD4, CIPHER_CONF1, (pDesc)->word[4], (cipherConfig)); \
- } while (0)
-
-/*!
- * This macro sets HW key configuration fields.
+ * @pdesc: pointer HW descriptor struct
+ * @mode: Any one of the modes defined in [CC7x-DESC]
+ */
+static inline void set_cipher_config0(struct cc_hw_desc *pdesc,
+ enum drv_crypto_direction mode)
+{
+ pdesc->word[4] |= FIELD_PREP(WORD4_CIPHER_CONF0, mode);
+}
+
+/*
+ * Set the cipher configuration fields.
*
- * \param pDesc pointer HW descriptor struct
- * \param hwKey The hw key number as in enun HwCryptoKey
-*/
-#define HW_DESC_SET_HW_CRYPTO_KEY(pDesc, hwKey) \
- do { \
- CC_REG_FLD_SET(CRY_KERNEL, DSCRPTR_QUEUE_WORD4, CIPHER_DO, (pDesc)->word[4], (hwKey)&HW_KEY_MASK_CIPHER_DO); \
- CC_REG_FLD_SET(CRY_KERNEL, DSCRPTR_QUEUE_WORD4, CIPHER_CONF2, (pDesc)->word[4], (hwKey>>HW_KEY_SHIFT_CIPHER_CFG2)); \
- } while (0)
-
-/*!
- * This macro changes the bytes order of all setup-finalize descriptosets.
+ * @pdesc: pointer HW descriptor struct
+ * @config: Any one of the modes defined in [CC7x-DESC]
+ */
+static inline void set_cipher_config1(struct cc_hw_desc *pdesc,
+ enum cc_hash_conf_pad config)
+{
+ pdesc->word[4] |= FIELD_PREP(WORD4_CIPHER_CONF1, config);
+}
+
+/*
+ * Set HW key configuration fields.
*
- * \param pDesc pointer HW descriptor struct
- * \param swapConfig Any one of the modes defined in [CC7x-DESC]
-*/
-#define HW_DESC_SET_BYTES_SWAP(pDesc, swapConfig) \
- do { \
- CC_REG_FLD_SET(CRY_KERNEL, DSCRPTR_QUEUE_WORD4, BYTES_SWAP, (pDesc)->word[4], (swapConfig)); \
- } while (0)
-
-/*!
- * This macro sets the CMAC_SIZE0 mode.
+ * @pdesc: pointer HW descriptor struct
+ * @hw_key: The HW key slot asdefined in enum cc_hw_crypto_key
+ */
+static inline void set_hw_crypto_key(struct cc_hw_desc *pdesc,
+ enum cc_hw_crypto_key hw_key)
+{
+ pdesc->word[4] |= FIELD_PREP(WORD4_CIPHER_DO,
+ (hw_key & HW_KEY_MASK_CIPHER_DO)) |
+ FIELD_PREP(WORD4_CIPHER_CONF2,
+ (hw_key >> HW_KEY_SHIFT_CIPHER_CFG2));
+}
+
+/*
+ * Set byte order of all setup-finalize descriptors.
*
- * \param pDesc pointer HW descriptor struct
-*/
-#define HW_DESC_SET_CMAC_SIZE0_MODE(pDesc) \
- do { \
- CC_REG_FLD_SET(CRY_KERNEL, DSCRPTR_QUEUE_WORD4, CMAC_SIZE0, (pDesc)->word[4], 0x1); \
- } while (0)
-
-/*!
- * This macro sets the key size for AES engine.
+ * @pdesc: pointer HW descriptor struct
+ * @config: Any one of the modes defined in [CC7x-DESC]
+ */
+static inline void set_bytes_swap(struct cc_hw_desc *pdesc, bool config)
+{
+ pdesc->word[4] |= FIELD_PREP(WORD4_BYTES_SWAP, config);
+}
+
+/*
+ * Set CMAC_SIZE0 mode.
*
- * \param pDesc pointer HW descriptor struct
- * \param keySize key size in bytes (NOT size code)
-*/
-#define HW_DESC_SET_KEY_SIZE_AES(pDesc, keySize) \
- do { \
- CC_REG_FLD_SET(CRY_KERNEL, DSCRPTR_QUEUE_WORD4, KEY_SIZE, (pDesc)->word[4], ((keySize) >> 3) - 2); \
- } while (0)
-
-/*!
- * This macro sets the key size for DES engine.
+ * @pdesc: pointer HW descriptor struct
+ */
+static inline void set_cmac_size0_mode(struct cc_hw_desc *pdesc)
+{
+ pdesc->word[4] |= FIELD_PREP(WORD4_CMAC_SIZE0, 1);
+}
+
+/*
+ * Set key size descriptor field.
*
- * \param pDesc pointer HW descriptor struct
- * \param keySize key size in bytes (NOT size code)
-*/
-#define HW_DESC_SET_KEY_SIZE_DES(pDesc, keySize) \
- do { \
- CC_REG_FLD_SET(CRY_KERNEL, DSCRPTR_QUEUE_WORD4, KEY_SIZE, (pDesc)->word[4], ((keySize) >> 3) - 1); \
- } while (0)
-
-/*!
- * This macro sets the descriptor's setup mode
+ * @pdesc: pointer HW descriptor struct
+ * @size: key size in bytes (NOT size code)
+ */
+static inline void set_key_size(struct cc_hw_desc *pdesc, u32 size)
+{
+ pdesc->word[4] |= FIELD_PREP(WORD4_KEY_SIZE, size);
+}
+
+/*
+ * Set AES key size.
*
- * \param pDesc pointer HW descriptor struct
- * \param setupMode Any one of the setup modes defined in [CC7x-DESC]
-*/
-#define HW_DESC_SET_SETUP_MODE(pDesc, setupMode) \
- do { \
- CC_REG_FLD_SET(CRY_KERNEL, DSCRPTR_QUEUE_WORD4, SETUP_OPERATION, (pDesc)->word[4], (setupMode)); \
- } while (0)
-
-/*!
- * This macro sets the descriptor's cipher do
+ * @pdesc: pointer HW descriptor struct
+ * @size: key size in bytes (NOT size code)
+ */
+static inline void set_key_size_aes(struct cc_hw_desc *pdesc, u32 size)
+{
+ set_key_size(pdesc, ((size >> 3) - 2));
+}
+
+/*
+ * Set DES key size.
*
- * \param pDesc pointer HW descriptor struct
- * \param cipherDo Any one of the cipher do defined in [CC7x-DESC]
-*/
-#define HW_DESC_SET_CIPHER_DO(pDesc, cipherDo) \
- do { \
- CC_REG_FLD_SET(CRY_KERNEL, DSCRPTR_QUEUE_WORD4, CIPHER_DO, (pDesc)->word[4], (cipherDo)&HW_KEY_MASK_CIPHER_DO); \
- } while (0)
-
-/*!
- * This macro sets the DIN field of a HW descriptors to star/stop monitor descriptor.
- * Used for performance measurements and debug purposes.
- *
- * \param pDesc pointer HW descriptor struct
+ * @pdesc: pointer HW descriptor struct
+ * @size: key size in bytes (NOT size code)
*/
-#define HW_DESC_SET_DIN_MONITOR_CNTR(pDesc) \
- do { \
- CC_REG_FLD_SET(CRY_KERNEL, DSCRPTR_MEASURE_CNTR, VALUE, (pDesc)->word[1], _HW_DESC_MONITOR_KICK); \
- } while (0)
+static inline void set_key_size_des(struct cc_hw_desc *pdesc, u32 size)
+{
+ set_key_size(pdesc, ((size >> 3) - 1));
+}
+/*
+ * Set the descriptor setup mode
+ *
+ * @pdesc: pointer HW descriptor struct
+ * @mode: Any one of the setup modes defined in [CC7x-DESC]
+ */
+static inline void set_setup_mode(struct cc_hw_desc *pdesc,
+ enum cc_setup_op mode)
+{
+ pdesc->word[4] |= FIELD_PREP(WORD4_SETUP_OPERATION, mode);
+}
+/*
+ * Set the descriptor cipher DO
+ *
+ * @pdesc: pointer HW descriptor struct
+ * @config: Any one of the cipher do defined in [CC7x-DESC]
+ */
+static inline void set_cipher_do(struct cc_hw_desc *pdesc,
+ enum cc_hash_cipher_pad config)
+{
+ pdesc->word[4] |= FIELD_PREP(WORD4_CIPHER_DO,
+ (config & HW_KEY_MASK_CIPHER_DO));
+}
#endif /*__CC_HW_QUEUE_DEFS_H__*/
diff --git a/drivers/staging/ccree/cc_lli_defs.h b/drivers/staging/ccree/cc_lli_defs.h
index 697f1ed181e0..851d3907167e 100644
--- a/drivers/staging/ccree/cc_lli_defs.h
+++ b/drivers/staging/ccree/cc_lli_defs.h
@@ -1,46 +1,42 @@
/*
* Copyright (C) 2012-2017 ARM Limited or its affiliates.
- *
+ *
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
- *
+ *
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
- *
+ *
* You should have received a copy of the GNU General Public License
* along with this program; if not, see <http://www.gnu.org/licenses/>.
*/
-
#ifndef _CC_LLI_DEFS_H_
#define _CC_LLI_DEFS_H_
-#ifdef __KERNEL__
-#include <linux/types.h>
-#else
-#include <stdint.h>
-#endif
-#include "cc_bitops.h"
-/* Max DLLI size */
-#define DLLI_SIZE_BIT_SIZE 0x18 // DX_DSCRPTR_QUEUE_WORD1_DIN_SIZE_BIT_SIZE
-
-#define CC_MAX_MLLI_ENTRY_SIZE 0x10000
+#include <linux/types.h>
-#define MSB64(_addr) (sizeof(_addr) == 4 ? 0 : ((_addr) >> 32)&UINT16_MAX)
+/* Max DLLI size
+ * AKA DX_DSCRPTR_QUEUE_WORD1_DIN_SIZE_BIT_SIZE
+ */
+#define DLLI_SIZE_BIT_SIZE 0x18
-#define LLI_SET_ADDR(lli_p, addr) \
- BITFIELD_SET(((uint32_t *)(lli_p))[LLI_WORD0_OFFSET], LLI_LADDR_BIT_OFFSET, LLI_LADDR_BIT_SIZE, (addr & UINT32_MAX)); \
- BITFIELD_SET(((uint32_t *)(lli_p))[LLI_WORD1_OFFSET], LLI_HADDR_BIT_OFFSET, LLI_HADDR_BIT_SIZE, MSB64(addr));
+#define CC_MAX_MLLI_ENTRY_SIZE 0xFFFF
-#define LLI_SET_SIZE(lli_p, size) \
- BITFIELD_SET(((uint32_t *)(lli_p))[LLI_WORD1_OFFSET], LLI_SIZE_BIT_OFFSET, LLI_SIZE_BIT_SIZE, size)
+#define LLI_MAX_NUM_OF_DATA_ENTRIES 128
+#define LLI_MAX_NUM_OF_ASSOC_DATA_ENTRIES 4
+#define MLLI_TABLE_MIN_ALIGNMENT 4 /* 32 bit alignment */
+#define MAX_NUM_OF_BUFFERS_IN_MLLI 4
+#define MAX_NUM_OF_TOTAL_MLLI_ENTRIES \
+ (2 * LLI_MAX_NUM_OF_DATA_ENTRIES + \
+ LLI_MAX_NUM_OF_ASSOC_DATA_ENTRIES)
/* Size of entry */
#define LLI_ENTRY_WORD_SIZE 2
-#define LLI_ENTRY_BYTE_SIZE (LLI_ENTRY_WORD_SIZE * sizeof(uint32_t))
+#define LLI_ENTRY_BYTE_SIZE (LLI_ENTRY_WORD_SIZE * sizeof(u32))
/* Word0[31:0] = ADDR[31:0] */
#define LLI_WORD0_OFFSET 0
@@ -53,5 +49,24 @@
#define LLI_HADDR_BIT_OFFSET 16
#define LLI_HADDR_BIT_SIZE 16
+#define LLI_SIZE_MASK GENMASK((LLI_SIZE_BIT_SIZE - 1), LLI_SIZE_BIT_OFFSET)
+#define LLI_HADDR_MASK GENMASK( \
+ (LLI_HADDR_BIT_OFFSET + LLI_HADDR_BIT_SIZE - 1),\
+ LLI_HADDR_BIT_OFFSET)
+
+static inline void cc_lli_set_addr(u32 *lli_p, dma_addr_t addr)
+{
+ lli_p[LLI_WORD0_OFFSET] = (addr & U32_MAX);
+#ifdef CONFIG_ARCH_DMA_ADDR_T_64BIT
+ lli_p[LLI_WORD1_OFFSET] &= ~LLI_HADDR_MASK;
+ lli_p[LLI_WORD1_OFFSET] |= FIELD_PREP(LLI_HADDR_MASK, (addr >> 16));
+#endif /* CONFIG_ARCH_DMA_ADDR_T_64BIT */
+}
+
+static inline void cc_lli_set_size(u32 *lli_p, u16 size)
+{
+ lli_p[LLI_WORD1_OFFSET] &= ~LLI_SIZE_MASK;
+ lli_p[LLI_WORD1_OFFSET] |= FIELD_PREP(LLI_SIZE_MASK, size);
+}
#endif /*_CC_LLI_DEFS_H_*/
diff --git a/drivers/staging/ccree/cc_pal_log.h b/drivers/staging/ccree/cc_pal_log.h
deleted file mode 100644
index e5f5a8737833..000000000000
--- a/drivers/staging/ccree/cc_pal_log.h
+++ /dev/null
@@ -1,188 +0,0 @@
-/*
- * Copyright (C) 2012-2017 ARM Limited or its affiliates.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, see <http://www.gnu.org/licenses/>.
- */
-
-#ifndef _CC_PAL_LOG_H_
-#define _CC_PAL_LOG_H_
-
-#include "cc_pal_types.h"
-#include "cc_pal_log_plat.h"
-
-/*!
-@file
-@brief This file contains the PAL layer log definitions, by default the log is disabled.
-@defgroup cc_pal_log CryptoCell PAL logging APIs and definitions
-@{
-@ingroup cc_pal
-*/
-
-/* PAL log levels (to be used in CC_PAL_logLevel) */
-/*! PAL log level - disabled. */
-#define CC_PAL_LOG_LEVEL_NULL (-1) /*!< \internal Disable logging */
-/*! PAL log level - error. */
-#define CC_PAL_LOG_LEVEL_ERR 0
-/*! PAL log level - warning. */
-#define CC_PAL_LOG_LEVEL_WARN 1
-/*! PAL log level - info. */
-#define CC_PAL_LOG_LEVEL_INFO 2
-/*! PAL log level - debug. */
-#define CC_PAL_LOG_LEVEL_DEBUG 3
-/*! PAL log level - trace. */
-#define CC_PAL_LOG_LEVEL_TRACE 4
-/*! PAL log level - data. */
-#define CC_PAL_LOG_LEVEL_DATA 5
-
-#ifndef CC_PAL_LOG_CUR_COMPONENT
-/* Setting default component mask in case caller did not define */
-/* (a mask that is always on for every log mask value but full masking) */
-/*! Default log debugged component.*/
-#define CC_PAL_LOG_CUR_COMPONENT 0xFFFFFFFF
-#endif
-#ifndef CC_PAL_LOG_CUR_COMPONENT_NAME
-/*! Default log debugged component.*/
-#define CC_PAL_LOG_CUR_COMPONENT_NAME "CC"
-#endif
-
-/* Select compile time log level (default if not explicitly specified by caller) */
-#ifndef CC_PAL_MAX_LOG_LEVEL /* Can be overriden by external definition of this constant */
-#ifdef DEBUG
-/*! Default debug log level (when debug is set to on).*/
-#define CC_PAL_MAX_LOG_LEVEL CC_PAL_LOG_LEVEL_ERR /*CC_PAL_LOG_LEVEL_DEBUG*/
-#else /* Disable logging */
-/*! Default debug log level (when debug is set to on).*/
-#define CC_PAL_MAX_LOG_LEVEL CC_PAL_LOG_LEVEL_NULL
-#endif
-#endif /*CC_PAL_MAX_LOG_LEVEL*/
-/*! Evaluate CC_PAL_MAX_LOG_LEVEL in case provided by caller */
-#define __CC_PAL_LOG_LEVEL_EVAL(level) level
-/*! Maximal log level defintion.*/
-#define _CC_PAL_MAX_LOG_LEVEL __CC_PAL_LOG_LEVEL_EVAL(CC_PAL_MAX_LOG_LEVEL)
-
-
-#ifdef ARM_DSM
-/*! Log init function. */
-#define CC_PalLogInit() do {} while (0)
-/*! Log set level function - sets the level of logging in case of debug. */
-#define CC_PalLogLevelSet(setLevel) do {} while (0)
-/*! Log set mask function - sets the component masking in case of debug. */
-#define CC_PalLogMaskSet(setMask) do {} while (0)
-#else
-#if _CC_PAL_MAX_LOG_LEVEL > CC_PAL_LOG_LEVEL_NULL
-/*! Log init function. */
-void CC_PalLogInit(void);
-/*! Log set level function - sets the level of logging in case of debug. */
-void CC_PalLogLevelSet(int setLevel);
-/*! Log set mask function - sets the component masking in case of debug. */
-void CC_PalLogMaskSet(uint32_t setMask);
-/*! Global variable for log level */
-extern int CC_PAL_logLevel;
-/*! Global variable for log mask */
-extern uint32_t CC_PAL_logMask;
-#else /* No log */
-/*! Log init function. */
-static inline void CC_PalLogInit(void) {}
-/*! Log set level function - sets the level of logging in case of debug. */
-static inline void CC_PalLogLevelSet(int setLevel) {CC_UNUSED_PARAM(setLevel);}
-/*! Log set mask function - sets the component masking in case of debug. */
-static inline void CC_PalLogMaskSet(uint32_t setMask) {CC_UNUSED_PARAM(setMask);}
-#endif
-#endif
-
-/*! Filter logging based on logMask and dispatch to platform specific logging mechanism. */
-#define _CC_PAL_LOG(level, format, ...) \
- if (CC_PAL_logMask & CC_PAL_LOG_CUR_COMPONENT) \
- __CC_PAL_LOG_PLAT(CC_PAL_LOG_LEVEL_ ## level, "%s:%s: " format, CC_PAL_LOG_CUR_COMPONENT_NAME, __func__, ##__VA_ARGS__)
-
-#if (_CC_PAL_MAX_LOG_LEVEL >= CC_PAL_LOG_LEVEL_ERR)
-/*! Log messages according to log level.*/
-#define CC_PAL_LOG_ERR(format, ... ) \
- _CC_PAL_LOG(ERR, format, ##__VA_ARGS__)
-#else
-/*! Log messages according to log level.*/
-#define CC_PAL_LOG_ERR( ... ) do {} while (0)
-#endif
-
-#if (_CC_PAL_MAX_LOG_LEVEL >= CC_PAL_LOG_LEVEL_WARN)
-/*! Log messages according to log level.*/
-#define CC_PAL_LOG_WARN(format, ... ) \
- if (CC_PAL_logLevel >= CC_PAL_LOG_LEVEL_WARN) \
- _CC_PAL_LOG(WARN, format, ##__VA_ARGS__)
-#else
-/*! Log messages according to log level.*/
-#define CC_PAL_LOG_WARN( ... ) do {} while (0)
-#endif
-
-#if (_CC_PAL_MAX_LOG_LEVEL >= CC_PAL_LOG_LEVEL_INFO)
-/*! Log messages according to log level.*/
-#define CC_PAL_LOG_INFO(format, ... ) \
- if (CC_PAL_logLevel >= CC_PAL_LOG_LEVEL_INFO) \
- _CC_PAL_LOG(INFO, format, ##__VA_ARGS__)
-#else
-/*! Log messages according to log level.*/
-#define CC_PAL_LOG_INFO( ... ) do {} while (0)
-#endif
-
-#if (_CC_PAL_MAX_LOG_LEVEL >= CC_PAL_LOG_LEVEL_DEBUG)
-/*! Log messages according to log level.*/
-#define CC_PAL_LOG_DEBUG(format, ... ) \
- if (CC_PAL_logLevel >= CC_PAL_LOG_LEVEL_DEBUG) \
- _CC_PAL_LOG(DEBUG, format, ##__VA_ARGS__)
-
-/*! Log message buffer.*/
-#define CC_PAL_LOG_DUMP_BUF(msg, buf, size) \
- do { \
- int i; \
- uint8_t *pData = (uint8_t*)buf; \
- \
- PRINTF("%s (%d):\n", msg, size); \
- for (i = 0; i < size; i++) { \
- PRINTF("0x%02X ", pData[i]); \
- if ((i & 0xF) == 0xF) { \
- PRINTF("\n"); \
- } \
- } \
- PRINTF("\n"); \
- } while (0)
-#else
-/*! Log debug messages.*/
-#define CC_PAL_LOG_DEBUG( ... ) do {} while (0)
-/*! Log debug buffer.*/
-#define CC_PAL_LOG_DUMP_BUF(msg, buf, size) do {} while (0)
-#endif
-
-#if (_CC_PAL_MAX_LOG_LEVEL >= CC_PAL_LOG_LEVEL_TRACE)
-/*! Log debug trace.*/
-#define CC_PAL_LOG_TRACE(format, ... ) \
- if (CC_PAL_logLevel >= CC_PAL_LOG_LEVEL_TRACE) \
- _CC_PAL_LOG(TRACE, format, ##__VA_ARGS__)
-#else
-/*! Log debug trace.*/
-#define CC_PAL_LOG_TRACE(...) do {} while (0)
-#endif
-
-#if (_CC_PAL_MAX_LOG_LEVEL >= CC_PAL_LOG_LEVEL_TRACE)
-/*! Log debug data.*/
-#define CC_PAL_LOG_DATA(format, ...) \
- if (CC_PAL_logLevel >= CC_PAL_LOG_LEVEL_TRACE) \
- _CC_PAL_LOG(DATA, format, ##__VA_ARGS__)
-#else
-/*! Log debug data.*/
-#define CC_PAL_LOG_DATA( ...) do {} while (0)
-#endif
-/**
-@}
- */
-
-#endif /*_CC_PAL_LOG_H_*/
diff --git a/drivers/staging/ccree/cc_pal_log_plat.h b/drivers/staging/ccree/cc_pal_log_plat.h
deleted file mode 100644
index a05a200cf6eb..000000000000
--- a/drivers/staging/ccree/cc_pal_log_plat.h
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- * Copyright (C) 2012-2017 ARM Limited or its affiliates.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, see <http://www.gnu.org/licenses/>.
- */
-
-/* Dummy pal_log_plat for test driver in kernel */
-
-#ifndef _SSI_PAL_LOG_PLAT_H_
-#define _SSI_PAL_LOG_PLAT_H_
-
-#if defined(DEBUG)
-
-#define __CC_PAL_LOG_PLAT(level, format, ...) printk(level "cc7x_test::" format , ##__VA_ARGS__)
-
-#else /* Disable all prints */
-
-#define __CC_PAL_LOG_PLAT(...) do {} while (0)
-
-#endif
-
-#endif /*_SASI_PAL_LOG_PLAT_H_*/
-
diff --git a/drivers/staging/ccree/cc_pal_types.h b/drivers/staging/ccree/cc_pal_types.h
deleted file mode 100644
index 9b59bbb34515..000000000000
--- a/drivers/staging/ccree/cc_pal_types.h
+++ /dev/null
@@ -1,97 +0,0 @@
-/*
- * Copyright (C) 2012-2017 ARM Limited or its affiliates.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, see <http://www.gnu.org/licenses/>.
- */
-
-#ifndef CC_PAL_TYPES_H
-#define CC_PAL_TYPES_H
-
-/*!
-@file
-@brief This file contains platform-dependent definitions and types.
-@defgroup cc_pal_types CryptoCell PAL platform dependant types
-@{
-@ingroup cc_pal
-
-*/
-
-#include "cc_pal_types_plat.h"
-
-/*! Boolean definition.*/
-typedef enum {
- /*! Boolean false definition.*/
- CC_FALSE = 0,
- /*! Boolean true definition.*/
- CC_TRUE = 1
-} CCBool;
-
-/*! Success definition. */
-#define CC_SUCCESS 0UL
-/*! Failure definition. */
-#define CC_FAIL 1UL
-
-/*! Defintion of 1KB in bytes. */
-#define CC_1K_SIZE_IN_BYTES 1024
-/*! Defintion of number of bits in a byte. */
-#define CC_BITS_IN_BYTE 8
-/*! Defintion of number of bits in a 32bits word. */
-#define CC_BITS_IN_32BIT_WORD 32
-/*! Defintion of number of bytes in a 32bits word. */
-#define CC_32BIT_WORD_SIZE (sizeof(uint32_t))
-
-/*! Success (OK) defintion. */
-#define CC_OK 0
-
-/*! Macro that handles unused parameters in the code (to avoid compilation warnings). */
-#define CC_UNUSED_PARAM(prm) ((void)prm)
-
-/*! Maximal uint32 value.*/
-#define CC_MAX_UINT32_VAL (0xFFFFFFFF)
-
-
-/* Minimum and Maximum macros */
-#ifdef min
-/*! Definition for minimum. */
-#define CC_MIN(a,b) min( a , b )
-#else
-/*! Definition for minimum. */
-#define CC_MIN( a , b ) ( ( (a) < (b) ) ? (a) : (b) )
-#endif
-
-#ifdef max
-/*! Definition for maximum. */
-#define CC_MAX(a,b) max( a , b )
-#else
-/*! Definition for maximum. */
-#define CC_MAX( a , b ) ( ( (a) > (b) ) ? (a) : (b) )
-#endif
-
-/*! Macro that calculates number of full bytes from bits (i.e. 7 bits are 1 byte). */
-#define CALC_FULL_BYTES(numBits) ((numBits)/CC_BITS_IN_BYTE + (((numBits) & (CC_BITS_IN_BYTE-1)) > 0))
-/*! Macro that calculates number of full 32bits words from bits (i.e. 31 bits are 1 word). */
-#define CALC_FULL_32BIT_WORDS(numBits) ((numBits)/CC_BITS_IN_32BIT_WORD + (((numBits) & (CC_BITS_IN_32BIT_WORD-1)) > 0))
-/*! Macro that calculates number of full 32bits words from bytes (i.e. 3 bytes are 1 word). */
-#define CALC_32BIT_WORDS_FROM_BYTES(sizeBytes) ((sizeBytes)/CC_32BIT_WORD_SIZE + (((sizeBytes) & (CC_32BIT_WORD_SIZE-1)) > 0))
-/*! Macro that round up bits to 32bits words. */
-#define ROUNDUP_BITS_TO_32BIT_WORD(numBits) (CALC_FULL_32BIT_WORDS(numBits) * CC_BITS_IN_32BIT_WORD)
-/*! Macro that round up bits to bytes. */
-#define ROUNDUP_BITS_TO_BYTES(numBits) (CALC_FULL_BYTES(numBits) * CC_BITS_IN_BYTE)
-/*! Macro that round up bytes to 32bits words. */
-#define ROUNDUP_BYTES_TO_32BIT_WORD(sizeBytes) (CALC_32BIT_WORDS_FROM_BYTES(sizeBytes) * CC_32BIT_WORD_SIZE)
-
-
-/**
-@}
- */
-#endif
diff --git a/drivers/staging/ccree/cc_pal_types_plat.h b/drivers/staging/ccree/cc_pal_types_plat.h
deleted file mode 100644
index 6e4211262231..000000000000
--- a/drivers/staging/ccree/cc_pal_types_plat.h
+++ /dev/null
@@ -1,29 +0,0 @@
-/*
- * Copyright (C) 2012-2017 ARM Limited or its affiliates.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, see <http://www.gnu.org/licenses/>.
- */
-
-
-#ifndef SSI_PAL_TYPES_PLAT_H
-#define SSI_PAL_TYPES_PLAT_H
-/* Linux kernel types */
-
-#include <linux/types.h>
-
-#ifndef NULL /* Missing in Linux kernel */
-#define NULL (0x0L)
-#endif
-
-
-#endif /*SSI_PAL_TYPES_PLAT_H*/
diff --git a/drivers/staging/ccree/cc_regs.h b/drivers/staging/ccree/cc_regs.h
index 963f8148cd28..4a893a6ba6ef 100644
--- a/drivers/staging/ccree/cc_regs.h
+++ b/drivers/staging/ccree/cc_regs.h
@@ -1,106 +1,42 @@
/*
* Copyright (C) 2012-2017 ARM Limited or its affiliates.
- *
+ *
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
- *
+ *
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
- *
+ *
* You should have received a copy of the GNU General Public License
* along with this program; if not, see <http://www.gnu.org/licenses/>.
*/
-
/*!
- * @file
- * @brief This file contains macro definitions for accessing ARM TrustZone CryptoCell register space.
+ * @file
+ * @brief This file contains macro definitions for accessing ARM TrustZone
+ * CryptoCell register space.
*/
#ifndef _CC_REGS_H_
#define _CC_REGS_H_
-#include "cc_bitops.h"
+#include <linux/bitfield.h>
+
+#define AXIM_MON_BASE_OFFSET CC_REG_OFFSET(CRY_KERNEL, AXIM_MON_COMP)
+#define AXIM_MON_COMP_VALUE GENMASK(DX_AXIM_MON_COMP_VALUE_BIT_SIZE + \
+ DX_AXIM_MON_COMP_VALUE_BIT_SHIFT, \
+ DX_AXIM_MON_COMP_VALUE_BIT_SHIFT)
+
+#define AXIM_MON_BASE_OFFSET CC_REG_OFFSET(CRY_KERNEL, AXIM_MON_COMP)
+#define AXIM_MON_COMP_VALUE GENMASK(DX_AXIM_MON_COMP_VALUE_BIT_SIZE + \
+ DX_AXIM_MON_COMP_VALUE_BIT_SHIFT, \
+ DX_AXIM_MON_COMP_VALUE_BIT_SHIFT)
/* Register Offset macro */
#define CC_REG_OFFSET(unit_name, reg_name) \
(DX_BASE_ ## unit_name + DX_ ## reg_name ## _REG_OFFSET)
-#define CC_REG_BIT_SHIFT(reg_name, field_name) \
- (DX_ ## reg_name ## _ ## field_name ## _BIT_SHIFT)
-
-/* Register Offset macros (from registers base address in host) */
-#include "dx_reg_base_host.h"
-
-/* Read-Modify-Write a field of a register */
-#define MODIFY_REGISTER_FLD(unitName, regName, fldName, fldVal) \
-do { \
- uint32_t regVal; \
- regVal = READ_REGISTER(CC_REG_ADDR(unitName, regName)); \
- CC_REG_FLD_SET(unitName, regName, fldName, regVal, fldVal); \
- WRITE_REGISTER(CC_REG_ADDR(unitName, regName), regVal); \
-} while (0)
-
-/* Registers address macros for ENV registers (development FPGA only) */
-#ifdef DX_BASE_ENV_REGS
-
-/* This offset should be added to mapping address of DX_BASE_ENV_REGS */
-#define CC_ENV_REG_OFFSET(reg_name) (DX_ENV_ ## reg_name ## _REG_OFFSET)
-
-#endif /*DX_BASE_ENV_REGS*/
-
-/*! Bit fields get */
-#define CC_REG_FLD_GET(unit_name, reg_name, fld_name, reg_val) \
- (DX_ ## reg_name ## _ ## fld_name ## _BIT_SIZE == 0x20 ? \
- reg_val /*!< \internal Optimization for 32b fields */ : \
- BITFIELD_GET(reg_val, DX_ ## reg_name ## _ ## fld_name ## _BIT_SHIFT, \
- DX_ ## reg_name ## _ ## fld_name ## _BIT_SIZE))
-
-/*! Bit fields access */
-#define CC_REG_FLD_GET2(unit_name, reg_name, fld_name, reg_val) \
- (CC_ ## reg_name ## _ ## fld_name ## _BIT_SIZE == 0x20 ? \
- reg_val /*!< \internal Optimization for 32b fields */ : \
- BITFIELD_GET(reg_val, CC_ ## reg_name ## _ ## fld_name ## _BIT_SHIFT, \
- CC_ ## reg_name ## _ ## fld_name ## _BIT_SIZE))
-
-/* yael TBD !!! - *
-* all HW includes should start with CC_ and not DX_ !! */
-
-
-/*! Bit fields set */
-#define CC_REG_FLD_SET( \
- unit_name, reg_name, fld_name, reg_shadow_var, new_fld_val) \
-do { \
- if (DX_ ## reg_name ## _ ## fld_name ## _BIT_SIZE == 0x20) \
- reg_shadow_var = new_fld_val; /*!< \internal Optimization for 32b fields */\
- else \
- BITFIELD_SET(reg_shadow_var, \
- DX_ ## reg_name ## _ ## fld_name ## _BIT_SHIFT, \
- DX_ ## reg_name ## _ ## fld_name ## _BIT_SIZE, \
- new_fld_val); \
-} while (0)
-
-/*! Bit fields set */
-#define CC_REG_FLD_SET2( \
- unit_name, reg_name, fld_name, reg_shadow_var, new_fld_val) \
-do { \
- if (CC_ ## reg_name ## _ ## fld_name ## _BIT_SIZE == 0x20) \
- reg_shadow_var = new_fld_val; /*!< \internal Optimization for 32b fields */\
- else \
- BITFIELD_SET(reg_shadow_var, \
- CC_ ## reg_name ## _ ## fld_name ## _BIT_SHIFT, \
- CC_ ## reg_name ## _ ## fld_name ## _BIT_SIZE, \
- new_fld_val); \
-} while (0)
-
-/* Usage example:
- uint32_t reg_shadow = READ_REGISTER(CC_REG_ADDR(CRY_KERNEL,AES_CONTROL));
- CC_REG_FLD_SET(CRY_KERNEL,AES_CONTROL,NK_KEY0,reg_shadow, 3);
- CC_REG_FLD_SET(CRY_KERNEL,AES_CONTROL,NK_KEY1,reg_shadow, 1);
- WRITE_REGISTER(CC_REG_ADDR(CRY_KERNEL,AES_CONTROL), reg_shadow);
- */
-
#endif /*_CC_REGS_H_*/
diff --git a/drivers/staging/ccree/dx_crys_kernel.h b/drivers/staging/ccree/dx_crys_kernel.h
index 703469c4a828..219603030344 100644
--- a/drivers/staging/ccree/dx_crys_kernel.h
+++ b/drivers/staging/ccree/dx_crys_kernel.h
@@ -1,15 +1,15 @@
/*
* Copyright (C) 2012-2017 ARM Limited or its affiliates.
- *
+ *
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
- *
+ *
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
- *
+ *
* You should have received a copy of the GNU General Public License
* along with this program; if not, see <http://www.gnu.org/licenses/>.
*/
@@ -20,161 +20,161 @@
// --------------------------------------
// BLOCK: DSCRPTR
// --------------------------------------
-#define DX_DSCRPTR_COMPLETION_COUNTER_REG_OFFSET 0xE00UL
-#define DX_DSCRPTR_COMPLETION_COUNTER_COMPLETION_COUNTER_BIT_SHIFT 0x0UL
-#define DX_DSCRPTR_COMPLETION_COUNTER_COMPLETION_COUNTER_BIT_SIZE 0x6UL
-#define DX_DSCRPTR_COMPLETION_COUNTER_OVERFLOW_COUNTER_BIT_SHIFT 0x6UL
-#define DX_DSCRPTR_COMPLETION_COUNTER_OVERFLOW_COUNTER_BIT_SIZE 0x1UL
-#define DX_DSCRPTR_SW_RESET_REG_OFFSET 0xE40UL
-#define DX_DSCRPTR_SW_RESET_VALUE_BIT_SHIFT 0x0UL
-#define DX_DSCRPTR_SW_RESET_VALUE_BIT_SIZE 0x1UL
-#define DX_DSCRPTR_QUEUE_SRAM_SIZE_REG_OFFSET 0xE60UL
-#define DX_DSCRPTR_QUEUE_SRAM_SIZE_NUM_OF_DSCRPTR_BIT_SHIFT 0x0UL
-#define DX_DSCRPTR_QUEUE_SRAM_SIZE_NUM_OF_DSCRPTR_BIT_SIZE 0xAUL
-#define DX_DSCRPTR_QUEUE_SRAM_SIZE_DSCRPTR_SRAM_SIZE_BIT_SHIFT 0xAUL
-#define DX_DSCRPTR_QUEUE_SRAM_SIZE_DSCRPTR_SRAM_SIZE_BIT_SIZE 0xCUL
-#define DX_DSCRPTR_QUEUE_SRAM_SIZE_SRAM_SIZE_BIT_SHIFT 0x16UL
-#define DX_DSCRPTR_QUEUE_SRAM_SIZE_SRAM_SIZE_BIT_SIZE 0x3UL
-#define DX_DSCRPTR_SINGLE_ADDR_EN_REG_OFFSET 0xE64UL
-#define DX_DSCRPTR_SINGLE_ADDR_EN_VALUE_BIT_SHIFT 0x0UL
-#define DX_DSCRPTR_SINGLE_ADDR_EN_VALUE_BIT_SIZE 0x1UL
-#define DX_DSCRPTR_MEASURE_CNTR_REG_OFFSET 0xE68UL
-#define DX_DSCRPTR_MEASURE_CNTR_VALUE_BIT_SHIFT 0x0UL
-#define DX_DSCRPTR_MEASURE_CNTR_VALUE_BIT_SIZE 0x20UL
-#define DX_DSCRPTR_QUEUE_WORD0_REG_OFFSET 0xE80UL
-#define DX_DSCRPTR_QUEUE_WORD0_VALUE_BIT_SHIFT 0x0UL
-#define DX_DSCRPTR_QUEUE_WORD0_VALUE_BIT_SIZE 0x20UL
-#define DX_DSCRPTR_QUEUE_WORD1_REG_OFFSET 0xE84UL
-#define DX_DSCRPTR_QUEUE_WORD1_DIN_DMA_MODE_BIT_SHIFT 0x0UL
-#define DX_DSCRPTR_QUEUE_WORD1_DIN_DMA_MODE_BIT_SIZE 0x2UL
-#define DX_DSCRPTR_QUEUE_WORD1_DIN_SIZE_BIT_SHIFT 0x2UL
-#define DX_DSCRPTR_QUEUE_WORD1_DIN_SIZE_BIT_SIZE 0x18UL
-#define DX_DSCRPTR_QUEUE_WORD1_NS_BIT_BIT_SHIFT 0x1AUL
-#define DX_DSCRPTR_QUEUE_WORD1_NS_BIT_BIT_SIZE 0x1UL
-#define DX_DSCRPTR_QUEUE_WORD1_DIN_CONST_VALUE_BIT_SHIFT 0x1BUL
-#define DX_DSCRPTR_QUEUE_WORD1_DIN_CONST_VALUE_BIT_SIZE 0x1UL
-#define DX_DSCRPTR_QUEUE_WORD1_NOT_LAST_BIT_SHIFT 0x1CUL
-#define DX_DSCRPTR_QUEUE_WORD1_NOT_LAST_BIT_SIZE 0x1UL
-#define DX_DSCRPTR_QUEUE_WORD1_LOCK_QUEUE_BIT_SHIFT 0x1DUL
-#define DX_DSCRPTR_QUEUE_WORD1_LOCK_QUEUE_BIT_SIZE 0x1UL
-#define DX_DSCRPTR_QUEUE_WORD1_NOT_USED_BIT_SHIFT 0x1EUL
-#define DX_DSCRPTR_QUEUE_WORD1_NOT_USED_BIT_SIZE 0x2UL
-#define DX_DSCRPTR_QUEUE_WORD2_REG_OFFSET 0xE88UL
-#define DX_DSCRPTR_QUEUE_WORD2_VALUE_BIT_SHIFT 0x0UL
-#define DX_DSCRPTR_QUEUE_WORD2_VALUE_BIT_SIZE 0x20UL
-#define DX_DSCRPTR_QUEUE_WORD3_REG_OFFSET 0xE8CUL
-#define DX_DSCRPTR_QUEUE_WORD3_DOUT_DMA_MODE_BIT_SHIFT 0x0UL
-#define DX_DSCRPTR_QUEUE_WORD3_DOUT_DMA_MODE_BIT_SIZE 0x2UL
-#define DX_DSCRPTR_QUEUE_WORD3_DOUT_SIZE_BIT_SHIFT 0x2UL
-#define DX_DSCRPTR_QUEUE_WORD3_DOUT_SIZE_BIT_SIZE 0x18UL
-#define DX_DSCRPTR_QUEUE_WORD3_NS_BIT_BIT_SHIFT 0x1AUL
-#define DX_DSCRPTR_QUEUE_WORD3_NS_BIT_BIT_SIZE 0x1UL
-#define DX_DSCRPTR_QUEUE_WORD3_DOUT_LAST_IND_BIT_SHIFT 0x1BUL
-#define DX_DSCRPTR_QUEUE_WORD3_DOUT_LAST_IND_BIT_SIZE 0x1UL
-#define DX_DSCRPTR_QUEUE_WORD3_HASH_XOR_BIT_BIT_SHIFT 0x1DUL
-#define DX_DSCRPTR_QUEUE_WORD3_HASH_XOR_BIT_BIT_SIZE 0x1UL
-#define DX_DSCRPTR_QUEUE_WORD3_NOT_USED_BIT_SHIFT 0x1EUL
-#define DX_DSCRPTR_QUEUE_WORD3_NOT_USED_BIT_SIZE 0x1UL
-#define DX_DSCRPTR_QUEUE_WORD3_QUEUE_LAST_IND_BIT_SHIFT 0x1FUL
-#define DX_DSCRPTR_QUEUE_WORD3_QUEUE_LAST_IND_BIT_SIZE 0x1UL
-#define DX_DSCRPTR_QUEUE_WORD4_REG_OFFSET 0xE90UL
-#define DX_DSCRPTR_QUEUE_WORD4_DATA_FLOW_MODE_BIT_SHIFT 0x0UL
-#define DX_DSCRPTR_QUEUE_WORD4_DATA_FLOW_MODE_BIT_SIZE 0x6UL
-#define DX_DSCRPTR_QUEUE_WORD4_AES_SEL_N_HASH_BIT_SHIFT 0x6UL
-#define DX_DSCRPTR_QUEUE_WORD4_AES_SEL_N_HASH_BIT_SIZE 0x1UL
-#define DX_DSCRPTR_QUEUE_WORD4_AES_XOR_CRYPTO_KEY_BIT_SHIFT 0x7UL
-#define DX_DSCRPTR_QUEUE_WORD4_AES_XOR_CRYPTO_KEY_BIT_SIZE 0x1UL
-#define DX_DSCRPTR_QUEUE_WORD4_ACK_NEEDED_BIT_SHIFT 0x8UL
-#define DX_DSCRPTR_QUEUE_WORD4_ACK_NEEDED_BIT_SIZE 0x2UL
-#define DX_DSCRPTR_QUEUE_WORD4_CIPHER_MODE_BIT_SHIFT 0xAUL
-#define DX_DSCRPTR_QUEUE_WORD4_CIPHER_MODE_BIT_SIZE 0x4UL
-#define DX_DSCRPTR_QUEUE_WORD4_CMAC_SIZE0_BIT_SHIFT 0xEUL
-#define DX_DSCRPTR_QUEUE_WORD4_CMAC_SIZE0_BIT_SIZE 0x1UL
-#define DX_DSCRPTR_QUEUE_WORD4_CIPHER_DO_BIT_SHIFT 0xFUL
-#define DX_DSCRPTR_QUEUE_WORD4_CIPHER_DO_BIT_SIZE 0x2UL
-#define DX_DSCRPTR_QUEUE_WORD4_CIPHER_CONF0_BIT_SHIFT 0x11UL
-#define DX_DSCRPTR_QUEUE_WORD4_CIPHER_CONF0_BIT_SIZE 0x2UL
-#define DX_DSCRPTR_QUEUE_WORD4_CIPHER_CONF1_BIT_SHIFT 0x13UL
-#define DX_DSCRPTR_QUEUE_WORD4_CIPHER_CONF1_BIT_SIZE 0x1UL
-#define DX_DSCRPTR_QUEUE_WORD4_CIPHER_CONF2_BIT_SHIFT 0x14UL
-#define DX_DSCRPTR_QUEUE_WORD4_CIPHER_CONF2_BIT_SIZE 0x2UL
-#define DX_DSCRPTR_QUEUE_WORD4_KEY_SIZE_BIT_SHIFT 0x16UL
-#define DX_DSCRPTR_QUEUE_WORD4_KEY_SIZE_BIT_SIZE 0x2UL
-#define DX_DSCRPTR_QUEUE_WORD4_SETUP_OPERATION_BIT_SHIFT 0x18UL
-#define DX_DSCRPTR_QUEUE_WORD4_SETUP_OPERATION_BIT_SIZE 0x4UL
-#define DX_DSCRPTR_QUEUE_WORD4_DIN_SRAM_ENDIANNESS_BIT_SHIFT 0x1CUL
-#define DX_DSCRPTR_QUEUE_WORD4_DIN_SRAM_ENDIANNESS_BIT_SIZE 0x1UL
-#define DX_DSCRPTR_QUEUE_WORD4_DOUT_SRAM_ENDIANNESS_BIT_SHIFT 0x1DUL
-#define DX_DSCRPTR_QUEUE_WORD4_DOUT_SRAM_ENDIANNESS_BIT_SIZE 0x1UL
-#define DX_DSCRPTR_QUEUE_WORD4_WORD_SWAP_BIT_SHIFT 0x1EUL
-#define DX_DSCRPTR_QUEUE_WORD4_WORD_SWAP_BIT_SIZE 0x1UL
-#define DX_DSCRPTR_QUEUE_WORD4_BYTES_SWAP_BIT_SHIFT 0x1FUL
-#define DX_DSCRPTR_QUEUE_WORD4_BYTES_SWAP_BIT_SIZE 0x1UL
-#define DX_DSCRPTR_QUEUE_WORD5_REG_OFFSET 0xE94UL
-#define DX_DSCRPTR_QUEUE_WORD5_DIN_ADDR_HIGH_BIT_SHIFT 0x0UL
-#define DX_DSCRPTR_QUEUE_WORD5_DIN_ADDR_HIGH_BIT_SIZE 0x10UL
-#define DX_DSCRPTR_QUEUE_WORD5_DOUT_ADDR_HIGH_BIT_SHIFT 0x10UL
-#define DX_DSCRPTR_QUEUE_WORD5_DOUT_ADDR_HIGH_BIT_SIZE 0x10UL
-#define DX_DSCRPTR_QUEUE_WATERMARK_REG_OFFSET 0xE98UL
-#define DX_DSCRPTR_QUEUE_WATERMARK_VALUE_BIT_SHIFT 0x0UL
-#define DX_DSCRPTR_QUEUE_WATERMARK_VALUE_BIT_SIZE 0xAUL
-#define DX_DSCRPTR_QUEUE_CONTENT_REG_OFFSET 0xE9CUL
-#define DX_DSCRPTR_QUEUE_CONTENT_VALUE_BIT_SHIFT 0x0UL
-#define DX_DSCRPTR_QUEUE_CONTENT_VALUE_BIT_SIZE 0xAUL
+#define DX_DSCRPTR_COMPLETION_COUNTER_REG_OFFSET 0xE00UL
+#define DX_DSCRPTR_COMPLETION_COUNTER_COMPLETION_COUNTER_BIT_SHIFT 0x0UL
+#define DX_DSCRPTR_COMPLETION_COUNTER_COMPLETION_COUNTER_BIT_SIZE 0x6UL
+#define DX_DSCRPTR_COMPLETION_COUNTER_OVERFLOW_COUNTER_BIT_SHIFT 0x6UL
+#define DX_DSCRPTR_COMPLETION_COUNTER_OVERFLOW_COUNTER_BIT_SIZE 0x1UL
+#define DX_DSCRPTR_SW_RESET_REG_OFFSET 0xE40UL
+#define DX_DSCRPTR_SW_RESET_VALUE_BIT_SHIFT 0x0UL
+#define DX_DSCRPTR_SW_RESET_VALUE_BIT_SIZE 0x1UL
+#define DX_DSCRPTR_QUEUE_SRAM_SIZE_REG_OFFSET 0xE60UL
+#define DX_DSCRPTR_QUEUE_SRAM_SIZE_NUM_OF_DSCRPTR_BIT_SHIFT 0x0UL
+#define DX_DSCRPTR_QUEUE_SRAM_SIZE_NUM_OF_DSCRPTR_BIT_SIZE 0xAUL
+#define DX_DSCRPTR_QUEUE_SRAM_SIZE_DSCRPTR_SRAM_SIZE_BIT_SHIFT 0xAUL
+#define DX_DSCRPTR_QUEUE_SRAM_SIZE_DSCRPTR_SRAM_SIZE_BIT_SIZE 0xCUL
+#define DX_DSCRPTR_QUEUE_SRAM_SIZE_SRAM_SIZE_BIT_SHIFT 0x16UL
+#define DX_DSCRPTR_QUEUE_SRAM_SIZE_SRAM_SIZE_BIT_SIZE 0x3UL
+#define DX_DSCRPTR_SINGLE_ADDR_EN_REG_OFFSET 0xE64UL
+#define DX_DSCRPTR_SINGLE_ADDR_EN_VALUE_BIT_SHIFT 0x0UL
+#define DX_DSCRPTR_SINGLE_ADDR_EN_VALUE_BIT_SIZE 0x1UL
+#define DX_DSCRPTR_MEASURE_CNTR_REG_OFFSET 0xE68UL
+#define DX_DSCRPTR_MEASURE_CNTR_VALUE_BIT_SHIFT 0x0UL
+#define DX_DSCRPTR_MEASURE_CNTR_VALUE_BIT_SIZE 0x20UL
+#define DX_DSCRPTR_QUEUE_WORD0_REG_OFFSET 0xE80UL
+#define DX_DSCRPTR_QUEUE_WORD0_VALUE_BIT_SHIFT 0x0UL
+#define DX_DSCRPTR_QUEUE_WORD0_VALUE_BIT_SIZE 0x20UL
+#define DX_DSCRPTR_QUEUE_WORD1_REG_OFFSET 0xE84UL
+#define DX_DSCRPTR_QUEUE_WORD1_DIN_DMA_MODE_BIT_SHIFT 0x0UL
+#define DX_DSCRPTR_QUEUE_WORD1_DIN_DMA_MODE_BIT_SIZE 0x2UL
+#define DX_DSCRPTR_QUEUE_WORD1_DIN_SIZE_BIT_SHIFT 0x2UL
+#define DX_DSCRPTR_QUEUE_WORD1_DIN_SIZE_BIT_SIZE 0x18UL
+#define DX_DSCRPTR_QUEUE_WORD1_NS_BIT_BIT_SHIFT 0x1AUL
+#define DX_DSCRPTR_QUEUE_WORD1_NS_BIT_BIT_SIZE 0x1UL
+#define DX_DSCRPTR_QUEUE_WORD1_DIN_CONST_VALUE_BIT_SHIFT 0x1BUL
+#define DX_DSCRPTR_QUEUE_WORD1_DIN_CONST_VALUE_BIT_SIZE 0x1UL
+#define DX_DSCRPTR_QUEUE_WORD1_NOT_LAST_BIT_SHIFT 0x1CUL
+#define DX_DSCRPTR_QUEUE_WORD1_NOT_LAST_BIT_SIZE 0x1UL
+#define DX_DSCRPTR_QUEUE_WORD1_LOCK_QUEUE_BIT_SHIFT 0x1DUL
+#define DX_DSCRPTR_QUEUE_WORD1_LOCK_QUEUE_BIT_SIZE 0x1UL
+#define DX_DSCRPTR_QUEUE_WORD1_NOT_USED_BIT_SHIFT 0x1EUL
+#define DX_DSCRPTR_QUEUE_WORD1_NOT_USED_BIT_SIZE 0x2UL
+#define DX_DSCRPTR_QUEUE_WORD2_REG_OFFSET 0xE88UL
+#define DX_DSCRPTR_QUEUE_WORD2_VALUE_BIT_SHIFT 0x0UL
+#define DX_DSCRPTR_QUEUE_WORD2_VALUE_BIT_SIZE 0x20UL
+#define DX_DSCRPTR_QUEUE_WORD3_REG_OFFSET 0xE8CUL
+#define DX_DSCRPTR_QUEUE_WORD3_DOUT_DMA_MODE_BIT_SHIFT 0x0UL
+#define DX_DSCRPTR_QUEUE_WORD3_DOUT_DMA_MODE_BIT_SIZE 0x2UL
+#define DX_DSCRPTR_QUEUE_WORD3_DOUT_SIZE_BIT_SHIFT 0x2UL
+#define DX_DSCRPTR_QUEUE_WORD3_DOUT_SIZE_BIT_SIZE 0x18UL
+#define DX_DSCRPTR_QUEUE_WORD3_NS_BIT_BIT_SHIFT 0x1AUL
+#define DX_DSCRPTR_QUEUE_WORD3_NS_BIT_BIT_SIZE 0x1UL
+#define DX_DSCRPTR_QUEUE_WORD3_DOUT_LAST_IND_BIT_SHIFT 0x1BUL
+#define DX_DSCRPTR_QUEUE_WORD3_DOUT_LAST_IND_BIT_SIZE 0x1UL
+#define DX_DSCRPTR_QUEUE_WORD3_HASH_XOR_BIT_BIT_SHIFT 0x1DUL
+#define DX_DSCRPTR_QUEUE_WORD3_HASH_XOR_BIT_BIT_SIZE 0x1UL
+#define DX_DSCRPTR_QUEUE_WORD3_NOT_USED_BIT_SHIFT 0x1EUL
+#define DX_DSCRPTR_QUEUE_WORD3_NOT_USED_BIT_SIZE 0x1UL
+#define DX_DSCRPTR_QUEUE_WORD3_QUEUE_LAST_IND_BIT_SHIFT 0x1FUL
+#define DX_DSCRPTR_QUEUE_WORD3_QUEUE_LAST_IND_BIT_SIZE 0x1UL
+#define DX_DSCRPTR_QUEUE_WORD4_REG_OFFSET 0xE90UL
+#define DX_DSCRPTR_QUEUE_WORD4_DATA_FLOW_MODE_BIT_SHIFT 0x0UL
+#define DX_DSCRPTR_QUEUE_WORD4_DATA_FLOW_MODE_BIT_SIZE 0x6UL
+#define DX_DSCRPTR_QUEUE_WORD4_AES_SEL_N_HASH_BIT_SHIFT 0x6UL
+#define DX_DSCRPTR_QUEUE_WORD4_AES_SEL_N_HASH_BIT_SIZE 0x1UL
+#define DX_DSCRPTR_QUEUE_WORD4_AES_XOR_CRYPTO_KEY_BIT_SHIFT 0x7UL
+#define DX_DSCRPTR_QUEUE_WORD4_AES_XOR_CRYPTO_KEY_BIT_SIZE 0x1UL
+#define DX_DSCRPTR_QUEUE_WORD4_ACK_NEEDED_BIT_SHIFT 0x8UL
+#define DX_DSCRPTR_QUEUE_WORD4_ACK_NEEDED_BIT_SIZE 0x2UL
+#define DX_DSCRPTR_QUEUE_WORD4_CIPHER_MODE_BIT_SHIFT 0xAUL
+#define DX_DSCRPTR_QUEUE_WORD4_CIPHER_MODE_BIT_SIZE 0x4UL
+#define DX_DSCRPTR_QUEUE_WORD4_CMAC_SIZE0_BIT_SHIFT 0xEUL
+#define DX_DSCRPTR_QUEUE_WORD4_CMAC_SIZE0_BIT_SIZE 0x1UL
+#define DX_DSCRPTR_QUEUE_WORD4_CIPHER_DO_BIT_SHIFT 0xFUL
+#define DX_DSCRPTR_QUEUE_WORD4_CIPHER_DO_BIT_SIZE 0x2UL
+#define DX_DSCRPTR_QUEUE_WORD4_CIPHER_CONF0_BIT_SHIFT 0x11UL
+#define DX_DSCRPTR_QUEUE_WORD4_CIPHER_CONF0_BIT_SIZE 0x2UL
+#define DX_DSCRPTR_QUEUE_WORD4_CIPHER_CONF1_BIT_SHIFT 0x13UL
+#define DX_DSCRPTR_QUEUE_WORD4_CIPHER_CONF1_BIT_SIZE 0x1UL
+#define DX_DSCRPTR_QUEUE_WORD4_CIPHER_CONF2_BIT_SHIFT 0x14UL
+#define DX_DSCRPTR_QUEUE_WORD4_CIPHER_CONF2_BIT_SIZE 0x2UL
+#define DX_DSCRPTR_QUEUE_WORD4_KEY_SIZE_BIT_SHIFT 0x16UL
+#define DX_DSCRPTR_QUEUE_WORD4_KEY_SIZE_BIT_SIZE 0x2UL
+#define DX_DSCRPTR_QUEUE_WORD4_SETUP_OPERATION_BIT_SHIFT 0x18UL
+#define DX_DSCRPTR_QUEUE_WORD4_SETUP_OPERATION_BIT_SIZE 0x4UL
+#define DX_DSCRPTR_QUEUE_WORD4_DIN_SRAM_ENDIANNESS_BIT_SHIFT 0x1CUL
+#define DX_DSCRPTR_QUEUE_WORD4_DIN_SRAM_ENDIANNESS_BIT_SIZE 0x1UL
+#define DX_DSCRPTR_QUEUE_WORD4_DOUT_SRAM_ENDIANNESS_BIT_SHIFT 0x1DUL
+#define DX_DSCRPTR_QUEUE_WORD4_DOUT_SRAM_ENDIANNESS_BIT_SIZE 0x1UL
+#define DX_DSCRPTR_QUEUE_WORD4_WORD_SWAP_BIT_SHIFT 0x1EUL
+#define DX_DSCRPTR_QUEUE_WORD4_WORD_SWAP_BIT_SIZE 0x1UL
+#define DX_DSCRPTR_QUEUE_WORD4_BYTES_SWAP_BIT_SHIFT 0x1FUL
+#define DX_DSCRPTR_QUEUE_WORD4_BYTES_SWAP_BIT_SIZE 0x1UL
+#define DX_DSCRPTR_QUEUE_WORD5_REG_OFFSET 0xE94UL
+#define DX_DSCRPTR_QUEUE_WORD5_DIN_ADDR_HIGH_BIT_SHIFT 0x0UL
+#define DX_DSCRPTR_QUEUE_WORD5_DIN_ADDR_HIGH_BIT_SIZE 0x10UL
+#define DX_DSCRPTR_QUEUE_WORD5_DOUT_ADDR_HIGH_BIT_SHIFT 0x10UL
+#define DX_DSCRPTR_QUEUE_WORD5_DOUT_ADDR_HIGH_BIT_SIZE 0x10UL
+#define DX_DSCRPTR_QUEUE_WATERMARK_REG_OFFSET 0xE98UL
+#define DX_DSCRPTR_QUEUE_WATERMARK_VALUE_BIT_SHIFT 0x0UL
+#define DX_DSCRPTR_QUEUE_WATERMARK_VALUE_BIT_SIZE 0xAUL
+#define DX_DSCRPTR_QUEUE_CONTENT_REG_OFFSET 0xE9CUL
+#define DX_DSCRPTR_QUEUE_CONTENT_VALUE_BIT_SHIFT 0x0UL
+#define DX_DSCRPTR_QUEUE_CONTENT_VALUE_BIT_SIZE 0xAUL
// --------------------------------------
// BLOCK: AXI_P
// --------------------------------------
-#define DX_AXIM_MON_INFLIGHT_REG_OFFSET 0xB00UL
-#define DX_AXIM_MON_INFLIGHT_VALUE_BIT_SHIFT 0x0UL
-#define DX_AXIM_MON_INFLIGHT_VALUE_BIT_SIZE 0x8UL
-#define DX_AXIM_MON_INFLIGHTLAST_REG_OFFSET 0xB40UL
-#define DX_AXIM_MON_INFLIGHTLAST_VALUE_BIT_SHIFT 0x0UL
-#define DX_AXIM_MON_INFLIGHTLAST_VALUE_BIT_SIZE 0x8UL
-#define DX_AXIM_MON_COMP_REG_OFFSET 0xB80UL
-#define DX_AXIM_MON_COMP_VALUE_BIT_SHIFT 0x0UL
-#define DX_AXIM_MON_COMP_VALUE_BIT_SIZE 0x10UL
-#define DX_AXIM_MON_ERR_REG_OFFSET 0xBC4UL
-#define DX_AXIM_MON_ERR_BRESP_BIT_SHIFT 0x0UL
-#define DX_AXIM_MON_ERR_BRESP_BIT_SIZE 0x2UL
-#define DX_AXIM_MON_ERR_BID_BIT_SHIFT 0x2UL
-#define DX_AXIM_MON_ERR_BID_BIT_SIZE 0x4UL
-#define DX_AXIM_MON_ERR_RRESP_BIT_SHIFT 0x10UL
-#define DX_AXIM_MON_ERR_RRESP_BIT_SIZE 0x2UL
-#define DX_AXIM_MON_ERR_RID_BIT_SHIFT 0x12UL
-#define DX_AXIM_MON_ERR_RID_BIT_SIZE 0x4UL
-#define DX_AXIM_CFG_REG_OFFSET 0xBE8UL
-#define DX_AXIM_CFG_BRESPMASK_BIT_SHIFT 0x4UL
-#define DX_AXIM_CFG_BRESPMASK_BIT_SIZE 0x1UL
-#define DX_AXIM_CFG_RRESPMASK_BIT_SHIFT 0x5UL
-#define DX_AXIM_CFG_RRESPMASK_BIT_SIZE 0x1UL
-#define DX_AXIM_CFG_INFLTMASK_BIT_SHIFT 0x6UL
-#define DX_AXIM_CFG_INFLTMASK_BIT_SIZE 0x1UL
-#define DX_AXIM_CFG_COMPMASK_BIT_SHIFT 0x7UL
-#define DX_AXIM_CFG_COMPMASK_BIT_SIZE 0x1UL
-#define DX_AXIM_ACE_CONST_REG_OFFSET 0xBECUL
-#define DX_AXIM_ACE_CONST_ARDOMAIN_BIT_SHIFT 0x0UL
-#define DX_AXIM_ACE_CONST_ARDOMAIN_BIT_SIZE 0x2UL
-#define DX_AXIM_ACE_CONST_AWDOMAIN_BIT_SHIFT 0x2UL
-#define DX_AXIM_ACE_CONST_AWDOMAIN_BIT_SIZE 0x2UL
-#define DX_AXIM_ACE_CONST_ARBAR_BIT_SHIFT 0x4UL
-#define DX_AXIM_ACE_CONST_ARBAR_BIT_SIZE 0x2UL
-#define DX_AXIM_ACE_CONST_AWBAR_BIT_SHIFT 0x6UL
-#define DX_AXIM_ACE_CONST_AWBAR_BIT_SIZE 0x2UL
-#define DX_AXIM_ACE_CONST_ARSNOOP_BIT_SHIFT 0x8UL
-#define DX_AXIM_ACE_CONST_ARSNOOP_BIT_SIZE 0x4UL
-#define DX_AXIM_ACE_CONST_AWSNOOP_NOT_ALIGNED_BIT_SHIFT 0xCUL
-#define DX_AXIM_ACE_CONST_AWSNOOP_NOT_ALIGNED_BIT_SIZE 0x3UL
-#define DX_AXIM_ACE_CONST_AWSNOOP_ALIGNED_BIT_SHIFT 0xFUL
-#define DX_AXIM_ACE_CONST_AWSNOOP_ALIGNED_BIT_SIZE 0x3UL
-#define DX_AXIM_ACE_CONST_AWADDR_NOT_MASKED_BIT_SHIFT 0x12UL
-#define DX_AXIM_ACE_CONST_AWADDR_NOT_MASKED_BIT_SIZE 0x7UL
-#define DX_AXIM_ACE_CONST_AWLEN_VAL_BIT_SHIFT 0x19UL
-#define DX_AXIM_ACE_CONST_AWLEN_VAL_BIT_SIZE 0x4UL
-#define DX_AXIM_CACHE_PARAMS_REG_OFFSET 0xBF0UL
-#define DX_AXIM_CACHE_PARAMS_AWCACHE_LAST_BIT_SHIFT 0x0UL
-#define DX_AXIM_CACHE_PARAMS_AWCACHE_LAST_BIT_SIZE 0x4UL
-#define DX_AXIM_CACHE_PARAMS_AWCACHE_BIT_SHIFT 0x4UL
-#define DX_AXIM_CACHE_PARAMS_AWCACHE_BIT_SIZE 0x4UL
-#define DX_AXIM_CACHE_PARAMS_ARCACHE_BIT_SHIFT 0x8UL
-#define DX_AXIM_CACHE_PARAMS_ARCACHE_BIT_SIZE 0x4UL
+#define DX_AXIM_MON_INFLIGHT_REG_OFFSET 0xB00UL
+#define DX_AXIM_MON_INFLIGHT_VALUE_BIT_SHIFT 0x0UL
+#define DX_AXIM_MON_INFLIGHT_VALUE_BIT_SIZE 0x8UL
+#define DX_AXIM_MON_INFLIGHTLAST_REG_OFFSET 0xB40UL
+#define DX_AXIM_MON_INFLIGHTLAST_VALUE_BIT_SHIFT 0x0UL
+#define DX_AXIM_MON_INFLIGHTLAST_VALUE_BIT_SIZE 0x8UL
+#define DX_AXIM_MON_COMP_REG_OFFSET 0xB80UL
+#define DX_AXIM_MON_COMP_VALUE_BIT_SHIFT 0x0UL
+#define DX_AXIM_MON_COMP_VALUE_BIT_SIZE 0x10UL
+#define DX_AXIM_MON_ERR_REG_OFFSET 0xBC4UL
+#define DX_AXIM_MON_ERR_BRESP_BIT_SHIFT 0x0UL
+#define DX_AXIM_MON_ERR_BRESP_BIT_SIZE 0x2UL
+#define DX_AXIM_MON_ERR_BID_BIT_SHIFT 0x2UL
+#define DX_AXIM_MON_ERR_BID_BIT_SIZE 0x4UL
+#define DX_AXIM_MON_ERR_RRESP_BIT_SHIFT 0x10UL
+#define DX_AXIM_MON_ERR_RRESP_BIT_SIZE 0x2UL
+#define DX_AXIM_MON_ERR_RID_BIT_SHIFT 0x12UL
+#define DX_AXIM_MON_ERR_RID_BIT_SIZE 0x4UL
+#define DX_AXIM_CFG_REG_OFFSET 0xBE8UL
+#define DX_AXIM_CFG_BRESPMASK_BIT_SHIFT 0x4UL
+#define DX_AXIM_CFG_BRESPMASK_BIT_SIZE 0x1UL
+#define DX_AXIM_CFG_RRESPMASK_BIT_SHIFT 0x5UL
+#define DX_AXIM_CFG_RRESPMASK_BIT_SIZE 0x1UL
+#define DX_AXIM_CFG_INFLTMASK_BIT_SHIFT 0x6UL
+#define DX_AXIM_CFG_INFLTMASK_BIT_SIZE 0x1UL
+#define DX_AXIM_CFG_COMPMASK_BIT_SHIFT 0x7UL
+#define DX_AXIM_CFG_COMPMASK_BIT_SIZE 0x1UL
+#define DX_AXIM_ACE_CONST_REG_OFFSET 0xBECUL
+#define DX_AXIM_ACE_CONST_ARDOMAIN_BIT_SHIFT 0x0UL
+#define DX_AXIM_ACE_CONST_ARDOMAIN_BIT_SIZE 0x2UL
+#define DX_AXIM_ACE_CONST_AWDOMAIN_BIT_SHIFT 0x2UL
+#define DX_AXIM_ACE_CONST_AWDOMAIN_BIT_SIZE 0x2UL
+#define DX_AXIM_ACE_CONST_ARBAR_BIT_SHIFT 0x4UL
+#define DX_AXIM_ACE_CONST_ARBAR_BIT_SIZE 0x2UL
+#define DX_AXIM_ACE_CONST_AWBAR_BIT_SHIFT 0x6UL
+#define DX_AXIM_ACE_CONST_AWBAR_BIT_SIZE 0x2UL
+#define DX_AXIM_ACE_CONST_ARSNOOP_BIT_SHIFT 0x8UL
+#define DX_AXIM_ACE_CONST_ARSNOOP_BIT_SIZE 0x4UL
+#define DX_AXIM_ACE_CONST_AWSNOOP_NOT_ALIGNED_BIT_SHIFT 0xCUL
+#define DX_AXIM_ACE_CONST_AWSNOOP_NOT_ALIGNED_BIT_SIZE 0x3UL
+#define DX_AXIM_ACE_CONST_AWSNOOP_ALIGNED_BIT_SHIFT 0xFUL
+#define DX_AXIM_ACE_CONST_AWSNOOP_ALIGNED_BIT_SIZE 0x3UL
+#define DX_AXIM_ACE_CONST_AWADDR_NOT_MASKED_BIT_SHIFT 0x12UL
+#define DX_AXIM_ACE_CONST_AWADDR_NOT_MASKED_BIT_SIZE 0x7UL
+#define DX_AXIM_ACE_CONST_AWLEN_VAL_BIT_SHIFT 0x19UL
+#define DX_AXIM_ACE_CONST_AWLEN_VAL_BIT_SIZE 0x4UL
+#define DX_AXIM_CACHE_PARAMS_REG_OFFSET 0xBF0UL
+#define DX_AXIM_CACHE_PARAMS_AWCACHE_LAST_BIT_SHIFT 0x0UL
+#define DX_AXIM_CACHE_PARAMS_AWCACHE_LAST_BIT_SIZE 0x4UL
+#define DX_AXIM_CACHE_PARAMS_AWCACHE_BIT_SHIFT 0x4UL
+#define DX_AXIM_CACHE_PARAMS_AWCACHE_BIT_SIZE 0x4UL
+#define DX_AXIM_CACHE_PARAMS_ARCACHE_BIT_SHIFT 0x8UL
+#define DX_AXIM_CACHE_PARAMS_ARCACHE_BIT_SIZE 0x4UL
#endif // __DX_CRYS_KERNEL_H__
diff --git a/drivers/staging/ccree/dx_env.h b/drivers/staging/ccree/dx_env.h
deleted file mode 100644
index 08040604b6da..000000000000
--- a/drivers/staging/ccree/dx_env.h
+++ /dev/null
@@ -1,224 +0,0 @@
-/*
- * Copyright (C) 2012-2017 ARM Limited or its affiliates.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, see <http://www.gnu.org/licenses/>.
- */
-
-#ifndef __DX_ENV_H__
-#define __DX_ENV_H__
-
-// --------------------------------------
-// BLOCK: FPGA_ENV_REGS
-// --------------------------------------
-#define DX_ENV_PKA_DEBUG_MODE_REG_OFFSET 0x024UL
-#define DX_ENV_PKA_DEBUG_MODE_VALUE_BIT_SHIFT 0x0UL
-#define DX_ENV_PKA_DEBUG_MODE_VALUE_BIT_SIZE 0x1UL
-#define DX_ENV_SCAN_MODE_REG_OFFSET 0x030UL
-#define DX_ENV_SCAN_MODE_VALUE_BIT_SHIFT 0x0UL
-#define DX_ENV_SCAN_MODE_VALUE_BIT_SIZE 0x1UL
-#define DX_ENV_CC_ALLOW_SCAN_REG_OFFSET 0x034UL
-#define DX_ENV_CC_ALLOW_SCAN_VALUE_BIT_SHIFT 0x0UL
-#define DX_ENV_CC_ALLOW_SCAN_VALUE_BIT_SIZE 0x1UL
-#define DX_ENV_CC_HOST_INT_REG_OFFSET 0x0A0UL
-#define DX_ENV_CC_HOST_INT_VALUE_BIT_SHIFT 0x0UL
-#define DX_ENV_CC_HOST_INT_VALUE_BIT_SIZE 0x1UL
-#define DX_ENV_CC_PUB_HOST_INT_REG_OFFSET 0x0A4UL
-#define DX_ENV_CC_PUB_HOST_INT_VALUE_BIT_SHIFT 0x0UL
-#define DX_ENV_CC_PUB_HOST_INT_VALUE_BIT_SIZE 0x1UL
-#define DX_ENV_CC_RST_N_REG_OFFSET 0x0A8UL
-#define DX_ENV_CC_RST_N_VALUE_BIT_SHIFT 0x0UL
-#define DX_ENV_CC_RST_N_VALUE_BIT_SIZE 0x1UL
-#define DX_ENV_RST_OVERRIDE_REG_OFFSET 0x0ACUL
-#define DX_ENV_RST_OVERRIDE_VALUE_BIT_SHIFT 0x0UL
-#define DX_ENV_RST_OVERRIDE_VALUE_BIT_SIZE 0x1UL
-#define DX_ENV_CC_POR_N_ADDR_REG_OFFSET 0x0E0UL
-#define DX_ENV_CC_POR_N_ADDR_VALUE_BIT_SHIFT 0x0UL
-#define DX_ENV_CC_POR_N_ADDR_VALUE_BIT_SIZE 0x1UL
-#define DX_ENV_CC_COLD_RST_REG_OFFSET 0x0FCUL
-#define DX_ENV_CC_COLD_RST_VALUE_BIT_SHIFT 0x0UL
-#define DX_ENV_CC_COLD_RST_VALUE_BIT_SIZE 0x1UL
-#define DX_ENV_DUMMY_ADDR_REG_OFFSET 0x108UL
-#define DX_ENV_DUMMY_ADDR_VALUE_BIT_SHIFT 0x0UL
-#define DX_ENV_DUMMY_ADDR_VALUE_BIT_SIZE 0x20UL
-#define DX_ENV_COUNTER_CLR_REG_OFFSET 0x118UL
-#define DX_ENV_COUNTER_CLR_VALUE_BIT_SHIFT 0x0UL
-#define DX_ENV_COUNTER_CLR_VALUE_BIT_SIZE 0x1UL
-#define DX_ENV_COUNTER_RD_REG_OFFSET 0x11CUL
-#define DX_ENV_COUNTER_RD_VALUE_BIT_SHIFT 0x0UL
-#define DX_ENV_COUNTER_RD_VALUE_BIT_SIZE 0x20UL
-#define DX_ENV_RNG_DEBUG_ENABLE_REG_OFFSET 0x430UL
-#define DX_ENV_RNG_DEBUG_ENABLE_VALUE_BIT_SHIFT 0x0UL
-#define DX_ENV_RNG_DEBUG_ENABLE_VALUE_BIT_SIZE 0x1UL
-#define DX_ENV_CC_LCS_REG_OFFSET 0x43CUL
-#define DX_ENV_CC_LCS_VALUE_BIT_SHIFT 0x0UL
-#define DX_ENV_CC_LCS_VALUE_BIT_SIZE 0x8UL
-#define DX_ENV_CC_IS_CM_DM_SECURE_RMA_REG_OFFSET 0x440UL
-#define DX_ENV_CC_IS_CM_DM_SECURE_RMA_IS_CM_BIT_SHIFT 0x0UL
-#define DX_ENV_CC_IS_CM_DM_SECURE_RMA_IS_CM_BIT_SIZE 0x1UL
-#define DX_ENV_CC_IS_CM_DM_SECURE_RMA_IS_DM_BIT_SHIFT 0x1UL
-#define DX_ENV_CC_IS_CM_DM_SECURE_RMA_IS_DM_BIT_SIZE 0x1UL
-#define DX_ENV_CC_IS_CM_DM_SECURE_RMA_IS_SECURE_BIT_SHIFT 0x2UL
-#define DX_ENV_CC_IS_CM_DM_SECURE_RMA_IS_SECURE_BIT_SIZE 0x1UL
-#define DX_ENV_CC_IS_CM_DM_SECURE_RMA_IS_RMA_BIT_SHIFT 0x3UL
-#define DX_ENV_CC_IS_CM_DM_SECURE_RMA_IS_RMA_BIT_SIZE 0x1UL
-#define DX_ENV_DCU_EN_REG_OFFSET 0x444UL
-#define DX_ENV_DCU_EN_VALUE_BIT_SHIFT 0x0UL
-#define DX_ENV_DCU_EN_VALUE_BIT_SIZE 0x20UL
-#define DX_ENV_CC_LCS_IS_VALID_REG_OFFSET 0x448UL
-#define DX_ENV_CC_LCS_IS_VALID_VALUE_BIT_SHIFT 0x0UL
-#define DX_ENV_CC_LCS_IS_VALID_VALUE_BIT_SIZE 0x1UL
-#define DX_ENV_POWER_DOWN_REG_OFFSET 0x478UL
-#define DX_ENV_POWER_DOWN_VALUE_BIT_SHIFT 0x0UL
-#define DX_ENV_POWER_DOWN_VALUE_BIT_SIZE 0x20UL
-#define DX_ENV_DCU_H_EN_REG_OFFSET 0x484UL
-#define DX_ENV_DCU_H_EN_VALUE_BIT_SHIFT 0x0UL
-#define DX_ENV_DCU_H_EN_VALUE_BIT_SIZE 0x20UL
-#define DX_ENV_VERSION_REG_OFFSET 0x488UL
-#define DX_ENV_VERSION_VALUE_BIT_SHIFT 0x0UL
-#define DX_ENV_VERSION_VALUE_BIT_SIZE 0x20UL
-#define DX_ENV_ROSC_WRITE_REG_OFFSET 0x48CUL
-#define DX_ENV_ROSC_WRITE_VALUE_BIT_SHIFT 0x0UL
-#define DX_ENV_ROSC_WRITE_VALUE_BIT_SIZE 0x1UL
-#define DX_ENV_ROSC_ADDR_REG_OFFSET 0x490UL
-#define DX_ENV_ROSC_ADDR_VALUE_BIT_SHIFT 0x0UL
-#define DX_ENV_ROSC_ADDR_VALUE_BIT_SIZE 0x8UL
-#define DX_ENV_RESET_SESSION_KEY_REG_OFFSET 0x494UL
-#define DX_ENV_RESET_SESSION_KEY_VALUE_BIT_SHIFT 0x0UL
-#define DX_ENV_RESET_SESSION_KEY_VALUE_BIT_SIZE 0x1UL
-#define DX_ENV_SESSION_KEY_0_REG_OFFSET 0x4A0UL
-#define DX_ENV_SESSION_KEY_0_VALUE_BIT_SHIFT 0x0UL
-#define DX_ENV_SESSION_KEY_0_VALUE_BIT_SIZE 0x20UL
-#define DX_ENV_SESSION_KEY_1_REG_OFFSET 0x4A4UL
-#define DX_ENV_SESSION_KEY_1_VALUE_BIT_SHIFT 0x0UL
-#define DX_ENV_SESSION_KEY_1_VALUE_BIT_SIZE 0x20UL
-#define DX_ENV_SESSION_KEY_2_REG_OFFSET 0x4A8UL
-#define DX_ENV_SESSION_KEY_2_VALUE_BIT_SHIFT 0x0UL
-#define DX_ENV_SESSION_KEY_2_VALUE_BIT_SIZE 0x20UL
-#define DX_ENV_SESSION_KEY_3_REG_OFFSET 0x4ACUL
-#define DX_ENV_SESSION_KEY_3_VALUE_BIT_SHIFT 0x0UL
-#define DX_ENV_SESSION_KEY_3_VALUE_BIT_SIZE 0x20UL
-#define DX_ENV_SESSION_KEY_VALID_REG_OFFSET 0x4B0UL
-#define DX_ENV_SESSION_KEY_VALID_VALUE_BIT_SHIFT 0x0UL
-#define DX_ENV_SESSION_KEY_VALID_VALUE_BIT_SIZE 0x1UL
-#define DX_ENV_SPIDEN_REG_OFFSET 0x4D0UL
-#define DX_ENV_SPIDEN_VALUE_BIT_SHIFT 0x0UL
-#define DX_ENV_SPIDEN_VALUE_BIT_SIZE 0x1UL
-#define DX_ENV_AXIM_USER_PARAMS_REG_OFFSET 0x600UL
-#define DX_ENV_AXIM_USER_PARAMS_ARUSER_BIT_SHIFT 0x0UL
-#define DX_ENV_AXIM_USER_PARAMS_ARUSER_BIT_SIZE 0x5UL
-#define DX_ENV_AXIM_USER_PARAMS_AWUSER_BIT_SHIFT 0x5UL
-#define DX_ENV_AXIM_USER_PARAMS_AWUSER_BIT_SIZE 0x5UL
-#define DX_ENV_SECURITY_MODE_OVERRIDE_REG_OFFSET 0x604UL
-#define DX_ENV_SECURITY_MODE_OVERRIDE_AWPROT_NS_BIT_BIT_SHIFT 0x0UL
-#define DX_ENV_SECURITY_MODE_OVERRIDE_AWPROT_NS_BIT_BIT_SIZE 0x1UL
-#define DX_ENV_SECURITY_MODE_OVERRIDE_AWPROT_NS_OVERRIDE_BIT_SHIFT 0x1UL
-#define DX_ENV_SECURITY_MODE_OVERRIDE_AWPROT_NS_OVERRIDE_BIT_SIZE 0x1UL
-#define DX_ENV_SECURITY_MODE_OVERRIDE_ARPROT_NS_BIT_BIT_SHIFT 0x2UL
-#define DX_ENV_SECURITY_MODE_OVERRIDE_ARPROT_NS_BIT_BIT_SIZE 0x1UL
-#define DX_ENV_SECURITY_MODE_OVERRIDE_ARPROT_NS_OVERRIDE_BIT_SHIFT 0x3UL
-#define DX_ENV_SECURITY_MODE_OVERRIDE_ARPROT_NS_OVERRIDE_BIT_SIZE 0x1UL
-#define DX_ENV_AO_CC_KPLT_0_REG_OFFSET 0x620UL
-#define DX_ENV_AO_CC_KPLT_0_VALUE_BIT_SHIFT 0x0UL
-#define DX_ENV_AO_CC_KPLT_0_VALUE_BIT_SIZE 0x20UL
-#define DX_ENV_AO_CC_KPLT_1_REG_OFFSET 0x624UL
-#define DX_ENV_AO_CC_KPLT_1_VALUE_BIT_SHIFT 0x0UL
-#define DX_ENV_AO_CC_KPLT_1_VALUE_BIT_SIZE 0x20UL
-#define DX_ENV_AO_CC_KPLT_2_REG_OFFSET 0x628UL
-#define DX_ENV_AO_CC_KPLT_2_VALUE_BIT_SHIFT 0x0UL
-#define DX_ENV_AO_CC_KPLT_2_VALUE_BIT_SIZE 0x20UL
-#define DX_ENV_AO_CC_KPLT_3_REG_OFFSET 0x62CUL
-#define DX_ENV_AO_CC_KPLT_3_VALUE_BIT_SHIFT 0x0UL
-#define DX_ENV_AO_CC_KPLT_3_VALUE_BIT_SIZE 0x20UL
-#define DX_ENV_AO_CC_KCST_0_REG_OFFSET 0x630UL
-#define DX_ENV_AO_CC_KCST_0_VALUE_BIT_SHIFT 0x0UL
-#define DX_ENV_AO_CC_KCST_0_VALUE_BIT_SIZE 0x20UL
-#define DX_ENV_AO_CC_KCST_1_REG_OFFSET 0x634UL
-#define DX_ENV_AO_CC_KCST_1_VALUE_BIT_SHIFT 0x0UL
-#define DX_ENV_AO_CC_KCST_1_VALUE_BIT_SIZE 0x20UL
-#define DX_ENV_AO_CC_KCST_2_REG_OFFSET 0x638UL
-#define DX_ENV_AO_CC_KCST_2_VALUE_BIT_SHIFT 0x0UL
-#define DX_ENV_AO_CC_KCST_2_VALUE_BIT_SIZE 0x20UL
-#define DX_ENV_AO_CC_KCST_3_REG_OFFSET 0x63CUL
-#define DX_ENV_AO_CC_KCST_3_VALUE_BIT_SHIFT 0x0UL
-#define DX_ENV_AO_CC_KCST_3_VALUE_BIT_SIZE 0x20UL
-#define DX_ENV_APB_FIPS_ADDR_REG_OFFSET 0x650UL
-#define DX_ENV_APB_FIPS_ADDR_VALUE_BIT_SHIFT 0x0UL
-#define DX_ENV_APB_FIPS_ADDR_VALUE_BIT_SIZE 0xCUL
-#define DX_ENV_APB_FIPS_VAL_REG_OFFSET 0x654UL
-#define DX_ENV_APB_FIPS_VAL_VALUE_BIT_SHIFT 0x0UL
-#define DX_ENV_APB_FIPS_VAL_VALUE_BIT_SIZE 0x20UL
-#define DX_ENV_APB_FIPS_MASK_REG_OFFSET 0x658UL
-#define DX_ENV_APB_FIPS_MASK_VALUE_BIT_SHIFT 0x0UL
-#define DX_ENV_APB_FIPS_MASK_VALUE_BIT_SIZE 0x20UL
-#define DX_ENV_APB_FIPS_CNT_REG_OFFSET 0x65CUL
-#define DX_ENV_APB_FIPS_CNT_VALUE_BIT_SHIFT 0x0UL
-#define DX_ENV_APB_FIPS_CNT_VALUE_BIT_SIZE 0x20UL
-#define DX_ENV_APB_FIPS_NEW_ADDR_REG_OFFSET 0x660UL
-#define DX_ENV_APB_FIPS_NEW_ADDR_VALUE_BIT_SHIFT 0x0UL
-#define DX_ENV_APB_FIPS_NEW_ADDR_VALUE_BIT_SIZE 0xCUL
-#define DX_ENV_APB_FIPS_NEW_VAL_REG_OFFSET 0x664UL
-#define DX_ENV_APB_FIPS_NEW_VAL_VALUE_BIT_SHIFT 0x0UL
-#define DX_ENV_APB_FIPS_NEW_VAL_VALUE_BIT_SIZE 0x20UL
-#define DX_ENV_APBP_FIPS_ADDR_REG_OFFSET 0x670UL
-#define DX_ENV_APBP_FIPS_ADDR_VALUE_BIT_SHIFT 0x0UL
-#define DX_ENV_APBP_FIPS_ADDR_VALUE_BIT_SIZE 0xCUL
-#define DX_ENV_APBP_FIPS_VAL_REG_OFFSET 0x674UL
-#define DX_ENV_APBP_FIPS_VAL_VALUE_BIT_SHIFT 0x0UL
-#define DX_ENV_APBP_FIPS_VAL_VALUE_BIT_SIZE 0x20UL
-#define DX_ENV_APBP_FIPS_MASK_REG_OFFSET 0x678UL
-#define DX_ENV_APBP_FIPS_MASK_VALUE_BIT_SHIFT 0x0UL
-#define DX_ENV_APBP_FIPS_MASK_VALUE_BIT_SIZE 0x20UL
-#define DX_ENV_APBP_FIPS_CNT_REG_OFFSET 0x67CUL
-#define DX_ENV_APBP_FIPS_CNT_VALUE_BIT_SHIFT 0x0UL
-#define DX_ENV_APBP_FIPS_CNT_VALUE_BIT_SIZE 0x20UL
-#define DX_ENV_APBP_FIPS_NEW_ADDR_REG_OFFSET 0x680UL
-#define DX_ENV_APBP_FIPS_NEW_ADDR_VALUE_BIT_SHIFT 0x0UL
-#define DX_ENV_APBP_FIPS_NEW_ADDR_VALUE_BIT_SIZE 0xCUL
-#define DX_ENV_APBP_FIPS_NEW_VAL_REG_OFFSET 0x684UL
-#define DX_ENV_APBP_FIPS_NEW_VAL_VALUE_BIT_SHIFT 0x0UL
-#define DX_ENV_APBP_FIPS_NEW_VAL_VALUE_BIT_SIZE 0x20UL
-#define DX_ENV_CC_POWERDOWN_EN_REG_OFFSET 0x690UL
-#define DX_ENV_CC_POWERDOWN_EN_VALUE_BIT_SHIFT 0x0UL
-#define DX_ENV_CC_POWERDOWN_EN_VALUE_BIT_SIZE 0x1UL
-#define DX_ENV_CC_POWERDOWN_RST_EN_REG_OFFSET 0x694UL
-#define DX_ENV_CC_POWERDOWN_RST_EN_VALUE_BIT_SHIFT 0x0UL
-#define DX_ENV_CC_POWERDOWN_RST_EN_VALUE_BIT_SIZE 0x1UL
-#define DX_ENV_POWERDOWN_RST_CNTR_REG_OFFSET 0x698UL
-#define DX_ENV_POWERDOWN_RST_CNTR_VALUE_BIT_SHIFT 0x0UL
-#define DX_ENV_POWERDOWN_RST_CNTR_VALUE_BIT_SIZE 0x20UL
-#define DX_ENV_POWERDOWN_EN_DEBUG_REG_OFFSET 0x69CUL
-#define DX_ENV_POWERDOWN_EN_DEBUG_VALUE_BIT_SHIFT 0x0UL
-#define DX_ENV_POWERDOWN_EN_DEBUG_VALUE_BIT_SIZE 0x1UL
-// --------------------------------------
-// BLOCK: ENV_CC_MEMORIES
-// --------------------------------------
-#define DX_ENV_FUSE_READY_REG_OFFSET 0x000UL
-#define DX_ENV_FUSE_READY_VALUE_BIT_SHIFT 0x0UL
-#define DX_ENV_FUSE_READY_VALUE_BIT_SIZE 0x1UL
-#define DX_ENV_PERF_RAM_MASTER_REG_OFFSET 0x0ECUL
-#define DX_ENV_PERF_RAM_MASTER_VALUE_BIT_SHIFT 0x0UL
-#define DX_ENV_PERF_RAM_MASTER_VALUE_BIT_SIZE 0x1UL
-#define DX_ENV_PERF_RAM_ADDR_HIGH4_REG_OFFSET 0x0F0UL
-#define DX_ENV_PERF_RAM_ADDR_HIGH4_VALUE_BIT_SHIFT 0x0UL
-#define DX_ENV_PERF_RAM_ADDR_HIGH4_VALUE_BIT_SIZE 0x2UL
-#define DX_ENV_FUSES_RAM_REG_OFFSET 0x3ECUL
-#define DX_ENV_FUSES_RAM_VALUE_BIT_SHIFT 0x0UL
-#define DX_ENV_FUSES_RAM_VALUE_BIT_SIZE 0x20UL
-// --------------------------------------
-// BLOCK: ENV_PERF_RAM_BASE
-// --------------------------------------
-#define DX_ENV_PERF_RAM_BASE_REG_OFFSET 0x000UL
-#define DX_ENV_PERF_RAM_BASE_VALUE_BIT_SHIFT 0x0UL
-#define DX_ENV_PERF_RAM_BASE_VALUE_BIT_SIZE 0x20UL
-
-#endif /*__DX_ENV_H__*/
diff --git a/drivers/staging/ccree/dx_host.h b/drivers/staging/ccree/dx_host.h
index 4e42e748dc5f..863c2670d826 100644
--- a/drivers/staging/ccree/dx_host.h
+++ b/drivers/staging/ccree/dx_host.h
@@ -1,15 +1,15 @@
/*
* Copyright (C) 2012-2017 ARM Limited or its affiliates.
- *
+ *
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
- *
+ *
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
- *
+ *
* You should have received a copy of the GNU General Public License
* along with this program; if not, see <http://www.gnu.org/licenses/>.
*/
@@ -20,136 +20,136 @@
// --------------------------------------
// BLOCK: HOST_P
// --------------------------------------
-#define DX_HOST_IRR_REG_OFFSET 0xA00UL
-#define DX_HOST_IRR_DSCRPTR_COMPLETION_LOW_INT_BIT_SHIFT 0x2UL
-#define DX_HOST_IRR_DSCRPTR_COMPLETION_LOW_INT_BIT_SIZE 0x1UL
-#define DX_HOST_IRR_AXI_ERR_INT_BIT_SHIFT 0x8UL
-#define DX_HOST_IRR_AXI_ERR_INT_BIT_SIZE 0x1UL
-#define DX_HOST_IRR_GPR0_BIT_SHIFT 0xBUL
-#define DX_HOST_IRR_GPR0_BIT_SIZE 0x1UL
-#define DX_HOST_IRR_DSCRPTR_WATERMARK_INT_BIT_SHIFT 0x13UL
-#define DX_HOST_IRR_DSCRPTR_WATERMARK_INT_BIT_SIZE 0x1UL
-#define DX_HOST_IRR_AXIM_COMP_INT_BIT_SHIFT 0x17UL
-#define DX_HOST_IRR_AXIM_COMP_INT_BIT_SIZE 0x1UL
-#define DX_HOST_IMR_REG_OFFSET 0xA04UL
-#define DX_HOST_IMR_NOT_USED_MASK_BIT_SHIFT 0x1UL
-#define DX_HOST_IMR_NOT_USED_MASK_BIT_SIZE 0x1UL
-#define DX_HOST_IMR_DSCRPTR_COMPLETION_MASK_BIT_SHIFT 0x2UL
-#define DX_HOST_IMR_DSCRPTR_COMPLETION_MASK_BIT_SIZE 0x1UL
-#define DX_HOST_IMR_AXI_ERR_MASK_BIT_SHIFT 0x8UL
-#define DX_HOST_IMR_AXI_ERR_MASK_BIT_SIZE 0x1UL
-#define DX_HOST_IMR_GPR0_BIT_SHIFT 0xBUL
-#define DX_HOST_IMR_GPR0_BIT_SIZE 0x1UL
-#define DX_HOST_IMR_DSCRPTR_WATERMARK_MASK0_BIT_SHIFT 0x13UL
-#define DX_HOST_IMR_DSCRPTR_WATERMARK_MASK0_BIT_SIZE 0x1UL
-#define DX_HOST_IMR_AXIM_COMP_INT_MASK_BIT_SHIFT 0x17UL
-#define DX_HOST_IMR_AXIM_COMP_INT_MASK_BIT_SIZE 0x1UL
-#define DX_HOST_ICR_REG_OFFSET 0xA08UL
-#define DX_HOST_ICR_DSCRPTR_COMPLETION_BIT_SHIFT 0x2UL
-#define DX_HOST_ICR_DSCRPTR_COMPLETION_BIT_SIZE 0x1UL
-#define DX_HOST_ICR_AXI_ERR_CLEAR_BIT_SHIFT 0x8UL
-#define DX_HOST_ICR_AXI_ERR_CLEAR_BIT_SIZE 0x1UL
-#define DX_HOST_ICR_GPR_INT_CLEAR_BIT_SHIFT 0xBUL
-#define DX_HOST_ICR_GPR_INT_CLEAR_BIT_SIZE 0x1UL
-#define DX_HOST_ICR_DSCRPTR_WATERMARK_QUEUE0_CLEAR_BIT_SHIFT 0x13UL
-#define DX_HOST_ICR_DSCRPTR_WATERMARK_QUEUE0_CLEAR_BIT_SIZE 0x1UL
-#define DX_HOST_ICR_AXIM_COMP_INT_CLEAR_BIT_SHIFT 0x17UL
-#define DX_HOST_ICR_AXIM_COMP_INT_CLEAR_BIT_SIZE 0x1UL
-#define DX_HOST_SIGNATURE_REG_OFFSET 0xA24UL
-#define DX_HOST_SIGNATURE_VALUE_BIT_SHIFT 0x0UL
-#define DX_HOST_SIGNATURE_VALUE_BIT_SIZE 0x20UL
-#define DX_HOST_BOOT_REG_OFFSET 0xA28UL
-#define DX_HOST_BOOT_SYNTHESIS_CONFIG_BIT_SHIFT 0x0UL
-#define DX_HOST_BOOT_SYNTHESIS_CONFIG_BIT_SIZE 0x1UL
-#define DX_HOST_BOOT_LARGE_RKEK_LOCAL_BIT_SHIFT 0x1UL
-#define DX_HOST_BOOT_LARGE_RKEK_LOCAL_BIT_SIZE 0x1UL
-#define DX_HOST_BOOT_HASH_IN_FUSES_LOCAL_BIT_SHIFT 0x2UL
-#define DX_HOST_BOOT_HASH_IN_FUSES_LOCAL_BIT_SIZE 0x1UL
-#define DX_HOST_BOOT_EXT_MEM_SECURED_LOCAL_BIT_SHIFT 0x3UL
-#define DX_HOST_BOOT_EXT_MEM_SECURED_LOCAL_BIT_SIZE 0x1UL
-#define DX_HOST_BOOT_RKEK_ECC_EXISTS_LOCAL_N_BIT_SHIFT 0x5UL
-#define DX_HOST_BOOT_RKEK_ECC_EXISTS_LOCAL_N_BIT_SIZE 0x1UL
-#define DX_HOST_BOOT_SRAM_SIZE_LOCAL_BIT_SHIFT 0x6UL
-#define DX_HOST_BOOT_SRAM_SIZE_LOCAL_BIT_SIZE 0x3UL
-#define DX_HOST_BOOT_DSCRPTR_EXISTS_LOCAL_BIT_SHIFT 0x9UL
-#define DX_HOST_BOOT_DSCRPTR_EXISTS_LOCAL_BIT_SIZE 0x1UL
-#define DX_HOST_BOOT_PAU_EXISTS_LOCAL_BIT_SHIFT 0xAUL
-#define DX_HOST_BOOT_PAU_EXISTS_LOCAL_BIT_SIZE 0x1UL
-#define DX_HOST_BOOT_RNG_EXISTS_LOCAL_BIT_SHIFT 0xBUL
-#define DX_HOST_BOOT_RNG_EXISTS_LOCAL_BIT_SIZE 0x1UL
-#define DX_HOST_BOOT_PKA_EXISTS_LOCAL_BIT_SHIFT 0xCUL
-#define DX_HOST_BOOT_PKA_EXISTS_LOCAL_BIT_SIZE 0x1UL
-#define DX_HOST_BOOT_RC4_EXISTS_LOCAL_BIT_SHIFT 0xDUL
-#define DX_HOST_BOOT_RC4_EXISTS_LOCAL_BIT_SIZE 0x1UL
-#define DX_HOST_BOOT_SHA_512_PRSNT_LOCAL_BIT_SHIFT 0xEUL
-#define DX_HOST_BOOT_SHA_512_PRSNT_LOCAL_BIT_SIZE 0x1UL
-#define DX_HOST_BOOT_SHA_256_PRSNT_LOCAL_BIT_SHIFT 0xFUL
-#define DX_HOST_BOOT_SHA_256_PRSNT_LOCAL_BIT_SIZE 0x1UL
-#define DX_HOST_BOOT_MD5_PRSNT_LOCAL_BIT_SHIFT 0x10UL
-#define DX_HOST_BOOT_MD5_PRSNT_LOCAL_BIT_SIZE 0x1UL
-#define DX_HOST_BOOT_HASH_EXISTS_LOCAL_BIT_SHIFT 0x11UL
-#define DX_HOST_BOOT_HASH_EXISTS_LOCAL_BIT_SIZE 0x1UL
-#define DX_HOST_BOOT_C2_EXISTS_LOCAL_BIT_SHIFT 0x12UL
-#define DX_HOST_BOOT_C2_EXISTS_LOCAL_BIT_SIZE 0x1UL
-#define DX_HOST_BOOT_DES_EXISTS_LOCAL_BIT_SHIFT 0x13UL
-#define DX_HOST_BOOT_DES_EXISTS_LOCAL_BIT_SIZE 0x1UL
-#define DX_HOST_BOOT_AES_XCBC_MAC_EXISTS_LOCAL_BIT_SHIFT 0x14UL
-#define DX_HOST_BOOT_AES_XCBC_MAC_EXISTS_LOCAL_BIT_SIZE 0x1UL
-#define DX_HOST_BOOT_AES_CMAC_EXISTS_LOCAL_BIT_SHIFT 0x15UL
-#define DX_HOST_BOOT_AES_CMAC_EXISTS_LOCAL_BIT_SIZE 0x1UL
-#define DX_HOST_BOOT_AES_CCM_EXISTS_LOCAL_BIT_SHIFT 0x16UL
-#define DX_HOST_BOOT_AES_CCM_EXISTS_LOCAL_BIT_SIZE 0x1UL
-#define DX_HOST_BOOT_AES_XEX_HW_T_CALC_LOCAL_BIT_SHIFT 0x17UL
-#define DX_HOST_BOOT_AES_XEX_HW_T_CALC_LOCAL_BIT_SIZE 0x1UL
-#define DX_HOST_BOOT_AES_XEX_EXISTS_LOCAL_BIT_SHIFT 0x18UL
-#define DX_HOST_BOOT_AES_XEX_EXISTS_LOCAL_BIT_SIZE 0x1UL
-#define DX_HOST_BOOT_CTR_EXISTS_LOCAL_BIT_SHIFT 0x19UL
-#define DX_HOST_BOOT_CTR_EXISTS_LOCAL_BIT_SIZE 0x1UL
-#define DX_HOST_BOOT_AES_DIN_BYTE_RESOLUTION_LOCAL_BIT_SHIFT 0x1AUL
-#define DX_HOST_BOOT_AES_DIN_BYTE_RESOLUTION_LOCAL_BIT_SIZE 0x1UL
-#define DX_HOST_BOOT_TUNNELING_ENB_LOCAL_BIT_SHIFT 0x1BUL
-#define DX_HOST_BOOT_TUNNELING_ENB_LOCAL_BIT_SIZE 0x1UL
-#define DX_HOST_BOOT_SUPPORT_256_192_KEY_LOCAL_BIT_SHIFT 0x1CUL
-#define DX_HOST_BOOT_SUPPORT_256_192_KEY_LOCAL_BIT_SIZE 0x1UL
-#define DX_HOST_BOOT_ONLY_ENCRYPT_LOCAL_BIT_SHIFT 0x1DUL
-#define DX_HOST_BOOT_ONLY_ENCRYPT_LOCAL_BIT_SIZE 0x1UL
-#define DX_HOST_BOOT_AES_EXISTS_LOCAL_BIT_SHIFT 0x1EUL
-#define DX_HOST_BOOT_AES_EXISTS_LOCAL_BIT_SIZE 0x1UL
-#define DX_HOST_VERSION_REG_OFFSET 0xA40UL
-#define DX_HOST_VERSION_VALUE_BIT_SHIFT 0x0UL
-#define DX_HOST_VERSION_VALUE_BIT_SIZE 0x20UL
-#define DX_HOST_KFDE0_VALID_REG_OFFSET 0xA60UL
-#define DX_HOST_KFDE0_VALID_VALUE_BIT_SHIFT 0x0UL
-#define DX_HOST_KFDE0_VALID_VALUE_BIT_SIZE 0x1UL
-#define DX_HOST_KFDE1_VALID_REG_OFFSET 0xA64UL
-#define DX_HOST_KFDE1_VALID_VALUE_BIT_SHIFT 0x0UL
-#define DX_HOST_KFDE1_VALID_VALUE_BIT_SIZE 0x1UL
-#define DX_HOST_KFDE2_VALID_REG_OFFSET 0xA68UL
-#define DX_HOST_KFDE2_VALID_VALUE_BIT_SHIFT 0x0UL
-#define DX_HOST_KFDE2_VALID_VALUE_BIT_SIZE 0x1UL
-#define DX_HOST_KFDE3_VALID_REG_OFFSET 0xA6CUL
-#define DX_HOST_KFDE3_VALID_VALUE_BIT_SHIFT 0x0UL
-#define DX_HOST_KFDE3_VALID_VALUE_BIT_SIZE 0x1UL
-#define DX_HOST_GPR0_REG_OFFSET 0xA70UL
-#define DX_HOST_GPR0_VALUE_BIT_SHIFT 0x0UL
-#define DX_HOST_GPR0_VALUE_BIT_SIZE 0x20UL
-#define DX_GPR_HOST_REG_OFFSET 0xA74UL
-#define DX_GPR_HOST_VALUE_BIT_SHIFT 0x0UL
-#define DX_GPR_HOST_VALUE_BIT_SIZE 0x20UL
-#define DX_HOST_POWER_DOWN_EN_REG_OFFSET 0xA78UL
-#define DX_HOST_POWER_DOWN_EN_VALUE_BIT_SHIFT 0x0UL
-#define DX_HOST_POWER_DOWN_EN_VALUE_BIT_SIZE 0x1UL
+#define DX_HOST_IRR_REG_OFFSET 0xA00UL
+#define DX_HOST_IRR_DSCRPTR_COMPLETION_LOW_INT_BIT_SHIFT 0x2UL
+#define DX_HOST_IRR_DSCRPTR_COMPLETION_LOW_INT_BIT_SIZE 0x1UL
+#define DX_HOST_IRR_AXI_ERR_INT_BIT_SHIFT 0x8UL
+#define DX_HOST_IRR_AXI_ERR_INT_BIT_SIZE 0x1UL
+#define DX_HOST_IRR_GPR0_BIT_SHIFT 0xBUL
+#define DX_HOST_IRR_GPR0_BIT_SIZE 0x1UL
+#define DX_HOST_IRR_DSCRPTR_WATERMARK_INT_BIT_SHIFT 0x13UL
+#define DX_HOST_IRR_DSCRPTR_WATERMARK_INT_BIT_SIZE 0x1UL
+#define DX_HOST_IRR_AXIM_COMP_INT_BIT_SHIFT 0x17UL
+#define DX_HOST_IRR_AXIM_COMP_INT_BIT_SIZE 0x1UL
+#define DX_HOST_IMR_REG_OFFSET 0xA04UL
+#define DX_HOST_IMR_NOT_USED_MASK_BIT_SHIFT 0x1UL
+#define DX_HOST_IMR_NOT_USED_MASK_BIT_SIZE 0x1UL
+#define DX_HOST_IMR_DSCRPTR_COMPLETION_MASK_BIT_SHIFT 0x2UL
+#define DX_HOST_IMR_DSCRPTR_COMPLETION_MASK_BIT_SIZE 0x1UL
+#define DX_HOST_IMR_AXI_ERR_MASK_BIT_SHIFT 0x8UL
+#define DX_HOST_IMR_AXI_ERR_MASK_BIT_SIZE 0x1UL
+#define DX_HOST_IMR_GPR0_BIT_SHIFT 0xBUL
+#define DX_HOST_IMR_GPR0_BIT_SIZE 0x1UL
+#define DX_HOST_IMR_DSCRPTR_WATERMARK_MASK0_BIT_SHIFT 0x13UL
+#define DX_HOST_IMR_DSCRPTR_WATERMARK_MASK0_BIT_SIZE 0x1UL
+#define DX_HOST_IMR_AXIM_COMP_INT_MASK_BIT_SHIFT 0x17UL
+#define DX_HOST_IMR_AXIM_COMP_INT_MASK_BIT_SIZE 0x1UL
+#define DX_HOST_ICR_REG_OFFSET 0xA08UL
+#define DX_HOST_ICR_DSCRPTR_COMPLETION_BIT_SHIFT 0x2UL
+#define DX_HOST_ICR_DSCRPTR_COMPLETION_BIT_SIZE 0x1UL
+#define DX_HOST_ICR_AXI_ERR_CLEAR_BIT_SHIFT 0x8UL
+#define DX_HOST_ICR_AXI_ERR_CLEAR_BIT_SIZE 0x1UL
+#define DX_HOST_ICR_GPR_INT_CLEAR_BIT_SHIFT 0xBUL
+#define DX_HOST_ICR_GPR_INT_CLEAR_BIT_SIZE 0x1UL
+#define DX_HOST_ICR_DSCRPTR_WATERMARK_QUEUE0_CLEAR_BIT_SHIFT 0x13UL
+#define DX_HOST_ICR_DSCRPTR_WATERMARK_QUEUE0_CLEAR_BIT_SIZE 0x1UL
+#define DX_HOST_ICR_AXIM_COMP_INT_CLEAR_BIT_SHIFT 0x17UL
+#define DX_HOST_ICR_AXIM_COMP_INT_CLEAR_BIT_SIZE 0x1UL
+#define DX_HOST_SIGNATURE_REG_OFFSET 0xA24UL
+#define DX_HOST_SIGNATURE_VALUE_BIT_SHIFT 0x0UL
+#define DX_HOST_SIGNATURE_VALUE_BIT_SIZE 0x20UL
+#define DX_HOST_BOOT_REG_OFFSET 0xA28UL
+#define DX_HOST_BOOT_SYNTHESIS_CONFIG_BIT_SHIFT 0x0UL
+#define DX_HOST_BOOT_SYNTHESIS_CONFIG_BIT_SIZE 0x1UL
+#define DX_HOST_BOOT_LARGE_RKEK_LOCAL_BIT_SHIFT 0x1UL
+#define DX_HOST_BOOT_LARGE_RKEK_LOCAL_BIT_SIZE 0x1UL
+#define DX_HOST_BOOT_HASH_IN_FUSES_LOCAL_BIT_SHIFT 0x2UL
+#define DX_HOST_BOOT_HASH_IN_FUSES_LOCAL_BIT_SIZE 0x1UL
+#define DX_HOST_BOOT_EXT_MEM_SECURED_LOCAL_BIT_SHIFT 0x3UL
+#define DX_HOST_BOOT_EXT_MEM_SECURED_LOCAL_BIT_SIZE 0x1UL
+#define DX_HOST_BOOT_RKEK_ECC_EXISTS_LOCAL_N_BIT_SHIFT 0x5UL
+#define DX_HOST_BOOT_RKEK_ECC_EXISTS_LOCAL_N_BIT_SIZE 0x1UL
+#define DX_HOST_BOOT_SRAM_SIZE_LOCAL_BIT_SHIFT 0x6UL
+#define DX_HOST_BOOT_SRAM_SIZE_LOCAL_BIT_SIZE 0x3UL
+#define DX_HOST_BOOT_DSCRPTR_EXISTS_LOCAL_BIT_SHIFT 0x9UL
+#define DX_HOST_BOOT_DSCRPTR_EXISTS_LOCAL_BIT_SIZE 0x1UL
+#define DX_HOST_BOOT_PAU_EXISTS_LOCAL_BIT_SHIFT 0xAUL
+#define DX_HOST_BOOT_PAU_EXISTS_LOCAL_BIT_SIZE 0x1UL
+#define DX_HOST_BOOT_RNG_EXISTS_LOCAL_BIT_SHIFT 0xBUL
+#define DX_HOST_BOOT_RNG_EXISTS_LOCAL_BIT_SIZE 0x1UL
+#define DX_HOST_BOOT_PKA_EXISTS_LOCAL_BIT_SHIFT 0xCUL
+#define DX_HOST_BOOT_PKA_EXISTS_LOCAL_BIT_SIZE 0x1UL
+#define DX_HOST_BOOT_RC4_EXISTS_LOCAL_BIT_SHIFT 0xDUL
+#define DX_HOST_BOOT_RC4_EXISTS_LOCAL_BIT_SIZE 0x1UL
+#define DX_HOST_BOOT_SHA_512_PRSNT_LOCAL_BIT_SHIFT 0xEUL
+#define DX_HOST_BOOT_SHA_512_PRSNT_LOCAL_BIT_SIZE 0x1UL
+#define DX_HOST_BOOT_SHA_256_PRSNT_LOCAL_BIT_SHIFT 0xFUL
+#define DX_HOST_BOOT_SHA_256_PRSNT_LOCAL_BIT_SIZE 0x1UL
+#define DX_HOST_BOOT_MD5_PRSNT_LOCAL_BIT_SHIFT 0x10UL
+#define DX_HOST_BOOT_MD5_PRSNT_LOCAL_BIT_SIZE 0x1UL
+#define DX_HOST_BOOT_HASH_EXISTS_LOCAL_BIT_SHIFT 0x11UL
+#define DX_HOST_BOOT_HASH_EXISTS_LOCAL_BIT_SIZE 0x1UL
+#define DX_HOST_BOOT_C2_EXISTS_LOCAL_BIT_SHIFT 0x12UL
+#define DX_HOST_BOOT_C2_EXISTS_LOCAL_BIT_SIZE 0x1UL
+#define DX_HOST_BOOT_DES_EXISTS_LOCAL_BIT_SHIFT 0x13UL
+#define DX_HOST_BOOT_DES_EXISTS_LOCAL_BIT_SIZE 0x1UL
+#define DX_HOST_BOOT_AES_XCBC_MAC_EXISTS_LOCAL_BIT_SHIFT 0x14UL
+#define DX_HOST_BOOT_AES_XCBC_MAC_EXISTS_LOCAL_BIT_SIZE 0x1UL
+#define DX_HOST_BOOT_AES_CMAC_EXISTS_LOCAL_BIT_SHIFT 0x15UL
+#define DX_HOST_BOOT_AES_CMAC_EXISTS_LOCAL_BIT_SIZE 0x1UL
+#define DX_HOST_BOOT_AES_CCM_EXISTS_LOCAL_BIT_SHIFT 0x16UL
+#define DX_HOST_BOOT_AES_CCM_EXISTS_LOCAL_BIT_SIZE 0x1UL
+#define DX_HOST_BOOT_AES_XEX_HW_T_CALC_LOCAL_BIT_SHIFT 0x17UL
+#define DX_HOST_BOOT_AES_XEX_HW_T_CALC_LOCAL_BIT_SIZE 0x1UL
+#define DX_HOST_BOOT_AES_XEX_EXISTS_LOCAL_BIT_SHIFT 0x18UL
+#define DX_HOST_BOOT_AES_XEX_EXISTS_LOCAL_BIT_SIZE 0x1UL
+#define DX_HOST_BOOT_CTR_EXISTS_LOCAL_BIT_SHIFT 0x19UL
+#define DX_HOST_BOOT_CTR_EXISTS_LOCAL_BIT_SIZE 0x1UL
+#define DX_HOST_BOOT_AES_DIN_BYTE_RESOLUTION_LOCAL_BIT_SHIFT 0x1AUL
+#define DX_HOST_BOOT_AES_DIN_BYTE_RESOLUTION_LOCAL_BIT_SIZE 0x1UL
+#define DX_HOST_BOOT_TUNNELING_ENB_LOCAL_BIT_SHIFT 0x1BUL
+#define DX_HOST_BOOT_TUNNELING_ENB_LOCAL_BIT_SIZE 0x1UL
+#define DX_HOST_BOOT_SUPPORT_256_192_KEY_LOCAL_BIT_SHIFT 0x1CUL
+#define DX_HOST_BOOT_SUPPORT_256_192_KEY_LOCAL_BIT_SIZE 0x1UL
+#define DX_HOST_BOOT_ONLY_ENCRYPT_LOCAL_BIT_SHIFT 0x1DUL
+#define DX_HOST_BOOT_ONLY_ENCRYPT_LOCAL_BIT_SIZE 0x1UL
+#define DX_HOST_BOOT_AES_EXISTS_LOCAL_BIT_SHIFT 0x1EUL
+#define DX_HOST_BOOT_AES_EXISTS_LOCAL_BIT_SIZE 0x1UL
+#define DX_HOST_VERSION_REG_OFFSET 0xA40UL
+#define DX_HOST_VERSION_VALUE_BIT_SHIFT 0x0UL
+#define DX_HOST_VERSION_VALUE_BIT_SIZE 0x20UL
+#define DX_HOST_KFDE0_VALID_REG_OFFSET 0xA60UL
+#define DX_HOST_KFDE0_VALID_VALUE_BIT_SHIFT 0x0UL
+#define DX_HOST_KFDE0_VALID_VALUE_BIT_SIZE 0x1UL
+#define DX_HOST_KFDE1_VALID_REG_OFFSET 0xA64UL
+#define DX_HOST_KFDE1_VALID_VALUE_BIT_SHIFT 0x0UL
+#define DX_HOST_KFDE1_VALID_VALUE_BIT_SIZE 0x1UL
+#define DX_HOST_KFDE2_VALID_REG_OFFSET 0xA68UL
+#define DX_HOST_KFDE2_VALID_VALUE_BIT_SHIFT 0x0UL
+#define DX_HOST_KFDE2_VALID_VALUE_BIT_SIZE 0x1UL
+#define DX_HOST_KFDE3_VALID_REG_OFFSET 0xA6CUL
+#define DX_HOST_KFDE3_VALID_VALUE_BIT_SHIFT 0x0UL
+#define DX_HOST_KFDE3_VALID_VALUE_BIT_SIZE 0x1UL
+#define DX_HOST_GPR0_REG_OFFSET 0xA70UL
+#define DX_HOST_GPR0_VALUE_BIT_SHIFT 0x0UL
+#define DX_HOST_GPR0_VALUE_BIT_SIZE 0x20UL
+#define DX_GPR_HOST_REG_OFFSET 0xA74UL
+#define DX_GPR_HOST_VALUE_BIT_SHIFT 0x0UL
+#define DX_GPR_HOST_VALUE_BIT_SIZE 0x20UL
+#define DX_HOST_POWER_DOWN_EN_REG_OFFSET 0xA78UL
+#define DX_HOST_POWER_DOWN_EN_VALUE_BIT_SHIFT 0x0UL
+#define DX_HOST_POWER_DOWN_EN_VALUE_BIT_SIZE 0x1UL
// --------------------------------------
// BLOCK: HOST_SRAM
// --------------------------------------
-#define DX_SRAM_DATA_REG_OFFSET 0xF00UL
-#define DX_SRAM_DATA_VALUE_BIT_SHIFT 0x0UL
-#define DX_SRAM_DATA_VALUE_BIT_SIZE 0x20UL
-#define DX_SRAM_ADDR_REG_OFFSET 0xF04UL
-#define DX_SRAM_ADDR_VALUE_BIT_SHIFT 0x0UL
-#define DX_SRAM_ADDR_VALUE_BIT_SIZE 0xFUL
-#define DX_SRAM_DATA_READY_REG_OFFSET 0xF08UL
-#define DX_SRAM_DATA_READY_VALUE_BIT_SHIFT 0x0UL
-#define DX_SRAM_DATA_READY_VALUE_BIT_SIZE 0x1UL
+#define DX_SRAM_DATA_REG_OFFSET 0xF00UL
+#define DX_SRAM_DATA_VALUE_BIT_SHIFT 0x0UL
+#define DX_SRAM_DATA_VALUE_BIT_SIZE 0x20UL
+#define DX_SRAM_ADDR_REG_OFFSET 0xF04UL
+#define DX_SRAM_ADDR_VALUE_BIT_SHIFT 0x0UL
+#define DX_SRAM_ADDR_VALUE_BIT_SIZE 0xFUL
+#define DX_SRAM_DATA_READY_REG_OFFSET 0xF08UL
+#define DX_SRAM_DATA_READY_VALUE_BIT_SHIFT 0x0UL
+#define DX_SRAM_DATA_READY_VALUE_BIT_SIZE 0x1UL
#endif //__DX_HOST_H__
diff --git a/drivers/staging/ccree/dx_reg_base_host.h b/drivers/staging/ccree/dx_reg_base_host.h
index 58dafe05fbeb..47bbadbcd1df 100644
--- a/drivers/staging/ccree/dx_reg_base_host.h
+++ b/drivers/staging/ccree/dx_reg_base_host.h
@@ -1,15 +1,15 @@
/*
* Copyright (C) 2012-2017 ARM Limited or its affiliates.
- *
+ *
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
- *
+ *
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
- *
+ *
* You should have received a copy of the GNU General Public License
* along with this program; if not, see <http://www.gnu.org/licenses/>.
*/
@@ -17,16 +17,7 @@
#ifndef __DX_REG_BASE_HOST_H__
#define __DX_REG_BASE_HOST_H__
-/* Identify platform: Xilinx Zynq7000 ZC706 */
-#define DX_PLAT_ZYNQ7000 1
-#define DX_PLAT_ZYNQ7000_ZC706 1
-
#define DX_BASE_CC 0x80000000
-
-#define DX_BASE_ENV_REGS 0x40008000
-#define DX_BASE_ENV_CC_MEMORIES 0x40008000
-#define DX_BASE_ENV_PERF_RAM 0x40009000
-
#define DX_BASE_HOST_RGF 0x0UL
#define DX_BASE_CRY_KERNEL 0x0UL
#define DX_BASE_ROM 0x40000000
diff --git a/drivers/staging/ccree/dx_reg_common.h b/drivers/staging/ccree/dx_reg_common.h
index 4ffed386521c..d5132ffaf6e6 100644
--- a/drivers/staging/ccree/dx_reg_common.h
+++ b/drivers/staging/ccree/dx_reg_common.h
@@ -1,15 +1,15 @@
/*
* Copyright (C) 2012-2017 ARM Limited or its affiliates.
- *
+ *
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
- *
+ *
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
- *
+ *
* You should have received a copy of the GNU General Public License
* along with this program; if not, see <http://www.gnu.org/licenses/>.
*/
@@ -19,7 +19,7 @@
#define DX_DEV_SIGNATURE 0xDCC71200UL
-#define CC_HW_VERSION 0xef840015UL
+#define CC_HW_VERSION 0xef840015UL
#define DX_DEV_SHA_MAX 512
diff --git a/drivers/staging/ccree/hash_defs.h b/drivers/staging/ccree/hash_defs.h
index 5ab0861fd1bb..f52656f5a3ea 100644
--- a/drivers/staging/ccree/hash_defs.h
+++ b/drivers/staging/ccree/hash_defs.h
@@ -1,78 +1,36 @@
/*
* Copyright (C) 2012-2017 ARM Limited or its affiliates.
- *
+ *
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
- *
+ *
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
- *
+ *
* You should have received a copy of the GNU General Public License
* along with this program; if not, see <http://www.gnu.org/licenses/>.
*/
-#ifndef _HASH_DEFS_H__
-#define _HASH_DEFS_H__
+#ifndef _HASH_DEFS_H_
+#define _HASH_DEFS_H_
#include "cc_crypto_ctx.h"
-/* this files provides definitions required for hash engine drivers */
-#ifndef CC_CONFIG_HASH_SHA_512_SUPPORTED
-#define SEP_HASH_LENGTH_WORDS 2
-#else
-#define SEP_HASH_LENGTH_WORDS 4
-#endif
-
-#ifdef BIG__ENDIAN
-#define OPAD_CURRENT_LENGTH 0x40000000, 0x00000000 , 0x00000000, 0x00000000
-#define HASH_LARVAL_MD5 0x76543210, 0xFEDCBA98, 0x89ABCDEF, 0x01234567
-#define HASH_LARVAL_SHA1 0xF0E1D2C3, 0x76543210, 0xFEDCBA98, 0x89ABCDEF, 0x01234567
-#define HASH_LARVAL_SHA224 0XA44FFABE, 0XA78FF964, 0X11155868, 0X310BC0FF, 0X39590EF7, 0X17DD7030, 0X07D57C36, 0XD89E05C1
-#define HASH_LARVAL_SHA256 0X19CDE05B, 0XABD9831F, 0X8C68059B, 0X7F520E51, 0X3AF54FA5, 0X72F36E3C, 0X85AE67BB, 0X67E6096A
-#define HASH_LARVAL_SHA384 0X1D48B547, 0XA44FFABE, 0X0D2E0CDB, 0XA78FF964, 0X874AB48E, 0X11155868, 0X67263367, 0X310BC0FF, 0XD8EC2F15, 0X39590EF7, 0X5A015991, 0X17DD7030, 0X2A299A62, 0X07D57C36, 0X5D9DBBCB, 0XD89E05C1
-#define HASH_LARVAL_SHA512 0X19CDE05B, 0X79217E13, 0XABD9831F, 0X6BBD41FB, 0X8C68059B, 0X1F6C3E2B, 0X7F520E51, 0XD182E6AD, 0X3AF54FA5, 0XF1361D5F, 0X72F36E3C, 0X2BF894FE, 0X85AE67BB, 0X3BA7CA84, 0X67E6096A, 0X08C9BCF3
-#else
-#define OPAD_CURRENT_LENGTH 0x00000040, 0x00000000, 0x00000000, 0x00000000
-#define HASH_LARVAL_MD5 0x10325476, 0x98BADCFE, 0xEFCDAB89, 0x67452301
-#define HASH_LARVAL_SHA1 0xC3D2E1F0, 0x10325476, 0x98BADCFE, 0xEFCDAB89, 0x67452301
-#define HASH_LARVAL_SHA224 0xbefa4fa4, 0x64f98fa7, 0x68581511, 0xffc00b31, 0xf70e5939, 0x3070dd17, 0x367cd507, 0xc1059ed8
-#define HASH_LARVAL_SHA256 0x5be0cd19, 0x1f83d9ab, 0x9b05688c, 0x510e527f, 0xa54ff53a, 0x3c6ef372, 0xbb67ae85, 0x6a09e667
-#define HASH_LARVAL_SHA384 0X47B5481D, 0XBEFA4FA4, 0XDB0C2E0D, 0X64F98FA7, 0X8EB44A87, 0X68581511, 0X67332667, 0XFFC00B31, 0X152FECD8, 0XF70E5939, 0X9159015A, 0X3070DD17, 0X629A292A, 0X367CD507, 0XCBBB9D5D, 0XC1059ED8
-#define HASH_LARVAL_SHA512 0x5be0cd19, 0x137e2179, 0x1f83d9ab, 0xfb41bd6b, 0x9b05688c, 0x2b3e6c1f, 0x510e527f, 0xade682d1, 0xa54ff53a, 0x5f1d36f1, 0x3c6ef372, 0xfe94f82b, 0xbb67ae85, 0x84caa73b, 0x6a09e667, 0xf3bcc908
-#endif
-
-enum HashConfig1Padding {
+enum cc_hash_conf_pad {
HASH_PADDING_DISABLED = 0,
HASH_PADDING_ENABLED = 1,
HASH_DIGEST_RESULT_LITTLE_ENDIAN = 2,
- HASH_CONFIG1_PADDING_RESERVE32 = INT32_MAX,
+ HASH_CONFIG1_PADDING_RESERVE32 = S32_MAX,
};
-enum HashCipherDoPadding {
+enum cc_hash_cipher_pad {
DO_NOT_PAD = 0,
DO_PAD = 1,
- HASH_CIPHER_DO_PADDING_RESERVE32 = INT32_MAX,
+ HASH_CIPHER_DO_PADDING_RESERVE32 = S32_MAX,
};
-typedef struct SepHashPrivateContext {
- /* The current length is placed at the end of the context buffer because the hash
- context is used for all HMAC operations as well. HMAC context includes a 64 bytes
- K0 field. The size of struct drv_ctx_hash reserved field is 88/184 bytes depend if t
- he SHA512 is supported ( in this case teh context size is 256 bytes).
- The size of struct drv_ctx_hash reseved field is 20 or 52 depend if the SHA512 is supported.
- This means that this structure size (without the reserved field can be up to 20 bytes ,
- in case sha512 is not suppported it is 20 bytes (SEP_HASH_LENGTH_WORDS define to 2 ) and in the other
- case it is 28 (SEP_HASH_LENGTH_WORDS define to 4) */
- uint32_t reserved[(sizeof(struct drv_ctx_hash)/sizeof(uint32_t)) - SEP_HASH_LENGTH_WORDS - 3];
- uint32_t CurrentDigestedLength[SEP_HASH_LENGTH_WORDS];
- uint32_t KeyType;
- uint32_t dataCompleted;
- uint32_t hmacFinalization;
- /* no space left */
-} SepHashPrivateContext_s;
-
-#endif /*_HASH_DEFS_H__*/
+#endif /*_HASH_DEFS_H_*/
diff --git a/drivers/staging/ccree/hw_queue_defs_plat.h b/drivers/staging/ccree/hw_queue_defs_plat.h
deleted file mode 100644
index aee02cc7588a..000000000000
--- a/drivers/staging/ccree/hw_queue_defs_plat.h
+++ /dev/null
@@ -1,43 +0,0 @@
-/*
- * Copyright (C) 2012-2017 ARM Limited or its affiliates.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, see <http://www.gnu.org/licenses/>.
- */
-
-#ifndef __HW_QUEUE_DEFS_PLAT_H__
-#define __HW_QUEUE_DEFS_PLAT_H__
-
-
-/*****************************/
-/* Descriptor packing macros */
-/*****************************/
-
-#define HW_QUEUE_FREE_SLOTS_GET() (CC_HAL_READ_REGISTER(CC_REG_OFFSET(CRY_KERNEL, DSCRPTR_QUEUE_CONTENT)) & HW_QUEUE_SLOTS_MAX)
-
-#define HW_QUEUE_POLL_QUEUE_UNTIL_FREE_SLOTS(seqLen) \
- do { \
- } while (HW_QUEUE_FREE_SLOTS_GET() < (seqLen))
-
-#define HW_DESC_PUSH_TO_QUEUE(pDesc) do { \
- LOG_HW_DESC(pDesc); \
- HW_DESC_DUMP(pDesc); \
- CC_HAL_WRITE_REGISTER(GET_HW_Q_DESC_WORD_IDX(0), (pDesc)->word[0]); \
- CC_HAL_WRITE_REGISTER(GET_HW_Q_DESC_WORD_IDX(1), (pDesc)->word[1]); \
- CC_HAL_WRITE_REGISTER(GET_HW_Q_DESC_WORD_IDX(2), (pDesc)->word[2]); \
- CC_HAL_WRITE_REGISTER(GET_HW_Q_DESC_WORD_IDX(3), (pDesc)->word[3]); \
- CC_HAL_WRITE_REGISTER(GET_HW_Q_DESC_WORD_IDX(4), (pDesc)->word[4]); \
- wmb(); \
- CC_HAL_WRITE_REGISTER(GET_HW_Q_DESC_WORD_IDX(5), (pDesc)->word[5]); \
-} while (0)
-
-#endif /*__HW_QUEUE_DEFS_PLAT_H__*/
diff --git a/drivers/staging/ccree/ssi_aead.c b/drivers/staging/ccree/ssi_aead.c
index 038291773b59..1fc0b05ea0d5 100644
--- a/drivers/staging/ccree/ssi_aead.c
+++ b/drivers/staging/ccree/ssi_aead.c
@@ -1,15 +1,15 @@
/*
* Copyright (C) 2012-2017 ARM Limited or its affiliates.
- *
+ *
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
- *
+ *
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
- *
+ *
* You should have received a copy of the GNU General Public License
* along with this program; if not, see <http://www.gnu.org/licenses/>.
*/
@@ -49,9 +49,8 @@
#define AES_CCM_RFC4309_NONCE_SIZE 3
#define MAX_NONCE_SIZE CTR_RFC3686_NONCE_SIZE
-
/* Value of each ICV_CMP byte (of 8) in case of success */
-#define ICV_VERIF_OK 0x01
+#define ICV_VERIF_OK 0x01
struct ssi_aead_handle {
ssi_sram_addr_t sram_workspace_addr;
@@ -60,18 +59,18 @@ struct ssi_aead_handle {
struct ssi_aead_ctx {
struct ssi_drvdata *drvdata;
- uint8_t ctr_nonce[MAX_NONCE_SIZE]; /* used for ctr3686 iv and aes ccm */
- uint8_t *enckey;
+ u8 ctr_nonce[MAX_NONCE_SIZE]; /* used for ctr3686 iv and aes ccm */
+ u8 *enckey;
dma_addr_t enckey_dma_addr;
union {
struct {
- uint8_t *padded_authkey;
- uint8_t *ipad_opad; /* IPAD, OPAD*/
+ u8 *padded_authkey;
+ u8 *ipad_opad; /* IPAD, OPAD*/
dma_addr_t padded_authkey_dma_addr;
dma_addr_t ipad_opad_dma_addr;
} hmac;
struct {
- uint8_t *xcbc_keys; /* K1,K2,K3 */
+ u8 *xcbc_keys; /* K1,K2,K3 */
dma_addr_t xcbc_keys_dma_addr;
} xcbc;
} auth_state;
@@ -79,7 +78,7 @@ struct ssi_aead_ctx {
unsigned int auth_keylen;
unsigned int authsize; /* Actual (reduced?) size of the MAC/ICv */
enum drv_cipher_mode cipher_mode;
- enum FlowMode flow_mode;
+ enum cc_flow_mode flow_mode;
enum drv_hash_mode auth_mode;
};
@@ -96,23 +95,20 @@ static void ssi_aead_exit(struct crypto_aead *tfm)
SSI_LOG_DEBUG("Clearing context @%p for %s\n",
crypto_aead_ctx(tfm), crypto_tfm_alg_name(&(tfm->base)));
- dev = &ctx->drvdata->plat_dev->dev;
+ dev = &ctx->drvdata->plat_dev->dev;
/* Unmap enckey buffer */
- if (ctx->enckey != NULL) {
- SSI_RESTORE_DMA_ADDR_TO_48BIT(ctx->enckey_dma_addr);
+ if (ctx->enckey) {
dma_free_coherent(dev, AES_MAX_KEY_SIZE, ctx->enckey, ctx->enckey_dma_addr);
SSI_LOG_DEBUG("Freed enckey DMA buffer enckey_dma_addr=0x%llX\n",
(unsigned long long)ctx->enckey_dma_addr);
ctx->enckey_dma_addr = 0;
ctx->enckey = NULL;
}
-
+
if (ctx->auth_mode == DRV_HASH_XCBC_MAC) { /* XCBC authetication */
- if (ctx->auth_state.xcbc.xcbc_keys != NULL) {
- SSI_RESTORE_DMA_ADDR_TO_48BIT(
- ctx->auth_state.xcbc.xcbc_keys_dma_addr);
+ if (ctx->auth_state.xcbc.xcbc_keys) {
dma_free_coherent(dev, CC_AES_128_BIT_KEY_SIZE * 3,
- ctx->auth_state.xcbc.xcbc_keys,
+ ctx->auth_state.xcbc.xcbc_keys,
ctx->auth_state.xcbc.xcbc_keys_dma_addr);
}
SSI_LOG_DEBUG("Freed xcbc_keys DMA buffer xcbc_keys_dma_addr=0x%llX\n",
@@ -120,9 +116,7 @@ static void ssi_aead_exit(struct crypto_aead *tfm)
ctx->auth_state.xcbc.xcbc_keys_dma_addr = 0;
ctx->auth_state.xcbc.xcbc_keys = NULL;
} else if (ctx->auth_mode != DRV_HASH_NULL) { /* HMAC auth. */
- if (ctx->auth_state.hmac.ipad_opad != NULL) {
- SSI_RESTORE_DMA_ADDR_TO_48BIT(
- ctx->auth_state.hmac.ipad_opad_dma_addr);
+ if (ctx->auth_state.hmac.ipad_opad) {
dma_free_coherent(dev, 2 * MAX_HMAC_DIGEST_SIZE,
ctx->auth_state.hmac.ipad_opad,
ctx->auth_state.hmac.ipad_opad_dma_addr);
@@ -131,9 +125,7 @@ static void ssi_aead_exit(struct crypto_aead *tfm)
ctx->auth_state.hmac.ipad_opad_dma_addr = 0;
ctx->auth_state.hmac.ipad_opad = NULL;
}
- if (ctx->auth_state.hmac.padded_authkey != NULL) {
- SSI_RESTORE_DMA_ADDR_TO_48BIT(
- ctx->auth_state.hmac.padded_authkey_dma_addr);
+ if (ctx->auth_state.hmac.padded_authkey) {
dma_free_coherent(dev, MAX_HMAC_BLOCK_SIZE,
ctx->auth_state.hmac.padded_authkey,
ctx->auth_state.hmac.padded_authkey_dma_addr);
@@ -162,16 +154,15 @@ static int ssi_aead_init(struct crypto_aead *tfm)
ctx->auth_mode = ssi_alg->auth_mode;
ctx->drvdata = ssi_alg->drvdata;
dev = &ctx->drvdata->plat_dev->dev;
- crypto_aead_set_reqsize(tfm,sizeof(struct aead_req_ctx));
+ crypto_aead_set_reqsize(tfm, sizeof(struct aead_req_ctx));
/* Allocate key buffer, cache line aligned */
ctx->enckey = dma_alloc_coherent(dev, AES_MAX_KEY_SIZE,
&ctx->enckey_dma_addr, GFP_KERNEL);
- if (ctx->enckey == NULL) {
+ if (!ctx->enckey) {
SSI_LOG_ERR("Failed allocating key buffer\n");
goto init_failed;
}
- SSI_UPDATE_DMA_ADDR_TO_48BIT(ctx->enckey_dma_addr, AES_MAX_KEY_SIZE);
SSI_LOG_DEBUG("Allocated enckey buffer in context ctx->enckey=@%p\n", ctx->enckey);
/* Set default authlen value */
@@ -182,38 +173,29 @@ static int ssi_aead_init(struct crypto_aead *tfm)
ctx->auth_state.xcbc.xcbc_keys = dma_alloc_coherent(dev,
CC_AES_128_BIT_KEY_SIZE * 3,
&ctx->auth_state.xcbc.xcbc_keys_dma_addr, GFP_KERNEL);
- if (ctx->auth_state.xcbc.xcbc_keys == NULL) {
+ if (!ctx->auth_state.xcbc.xcbc_keys) {
SSI_LOG_ERR("Failed allocating buffer for XCBC keys\n");
goto init_failed;
}
- SSI_UPDATE_DMA_ADDR_TO_48BIT(
- ctx->auth_state.xcbc.xcbc_keys_dma_addr,
- CC_AES_128_BIT_KEY_SIZE * 3);
} else if (ctx->auth_mode != DRV_HASH_NULL) { /* HMAC authentication */
/* Allocate dma-coherent buffer for IPAD + OPAD */
ctx->auth_state.hmac.ipad_opad = dma_alloc_coherent(dev,
2 * MAX_HMAC_DIGEST_SIZE,
&ctx->auth_state.hmac.ipad_opad_dma_addr, GFP_KERNEL);
- if (ctx->auth_state.hmac.ipad_opad == NULL) {
+ if (!ctx->auth_state.hmac.ipad_opad) {
SSI_LOG_ERR("Failed allocating IPAD/OPAD buffer\n");
goto init_failed;
}
- SSI_UPDATE_DMA_ADDR_TO_48BIT(
- ctx->auth_state.hmac.ipad_opad_dma_addr,
- 2 * MAX_HMAC_DIGEST_SIZE);
SSI_LOG_DEBUG("Allocated authkey buffer in context ctx->authkey=@%p\n",
ctx->auth_state.hmac.ipad_opad);
-
+
ctx->auth_state.hmac.padded_authkey = dma_alloc_coherent(dev,
MAX_HMAC_BLOCK_SIZE,
&ctx->auth_state.hmac.padded_authkey_dma_addr, GFP_KERNEL);
- if (ctx->auth_state.hmac.padded_authkey == NULL) {
+ if (!ctx->auth_state.hmac.padded_authkey) {
SSI_LOG_ERR("failed to allocate padded_authkey\n");
goto init_failed;
- }
- SSI_UPDATE_DMA_ADDR_TO_48BIT(
- ctx->auth_state.hmac.padded_authkey_dma_addr,
- MAX_HMAC_BLOCK_SIZE);
+ }
} else {
ctx->auth_state.hmac.ipad_opad = NULL;
ctx->auth_state.hmac.padded_authkey = NULL;
@@ -225,7 +207,6 @@ init_failed:
ssi_aead_exit(tfm);
return -ENOMEM;
}
-
static void ssi_aead_complete(struct device *dev, void *ssi_req, void __iomem *cc_base)
{
@@ -234,9 +215,6 @@ static void ssi_aead_complete(struct device *dev, void *ssi_req, void __iomem *c
struct crypto_aead *tfm = crypto_aead_reqtfm(ssi_req);
struct ssi_aead_ctx *ctx = crypto_aead_ctx(tfm);
int err = 0;
- DECL_CYCLE_COUNT_RESOURCES;
-
- START_CYCLE_COUNT();
ssi_buffer_mgr_unmap_aead_request(dev, areq);
@@ -250,72 +228,75 @@ static void ssi_aead_complete(struct device *dev, void *ssi_req, void __iomem *c
"(auth-size=%d, cipher=%d).\n",
ctx->authsize, ctx->cipher_mode);
/* In case of payload authentication failure, MUST NOT
- revealed the decrypted message --> zero its memory. */
+ * revealed the decrypted message --> zero its memory.
+ */
ssi_buffer_mgr_zero_sgl(areq->dst, areq_ctx->cryptlen);
err = -EBADMSG;
}
} else { /*ENCRYPT*/
- if (unlikely(areq_ctx->is_icv_fragmented == true))
+ if (unlikely(areq_ctx->is_icv_fragmented))
ssi_buffer_mgr_copy_scatterlist_portion(
- areq_ctx->mac_buf, areq_ctx->dstSgl, areq->cryptlen+areq_ctx->dstOffset,
- areq->cryptlen+areq_ctx->dstOffset + ctx->authsize, SSI_SG_FROM_BUF);
+ areq_ctx->mac_buf, areq_ctx->dstSgl, areq->cryptlen + areq_ctx->dstOffset,
+ areq->cryptlen + areq_ctx->dstOffset + ctx->authsize, SSI_SG_FROM_BUF);
/* If an IV was generated, copy it back to the user provided buffer. */
- if (areq_ctx->backup_giv != NULL) {
- if (ctx->cipher_mode == DRV_CIPHER_CTR) {
+ if (areq_ctx->backup_giv) {
+ if (ctx->cipher_mode == DRV_CIPHER_CTR)
memcpy(areq_ctx->backup_giv, areq_ctx->ctr_iv + CTR_RFC3686_NONCE_SIZE, CTR_RFC3686_IV_SIZE);
- } else if (ctx->cipher_mode == DRV_CIPHER_CCM) {
+ else if (ctx->cipher_mode == DRV_CIPHER_CCM)
memcpy(areq_ctx->backup_giv, areq_ctx->ctr_iv + CCM_BLOCK_IV_OFFSET, CCM_BLOCK_IV_SIZE);
- }
}
}
- END_CYCLE_COUNT(STAT_OP_TYPE_GENERIC, STAT_PHASE_4);
aead_request_complete(areq, err);
}
-static int xcbc_setkey(HwDesc_s *desc, struct ssi_aead_ctx *ctx)
+static int xcbc_setkey(struct cc_hw_desc *desc, struct ssi_aead_ctx *ctx)
{
/* Load the AES key */
- HW_DESC_INIT(&desc[0]);
+ hw_desc_init(&desc[0]);
/* We are using for the source/user key the same buffer as for the output keys,
- because after this key loading it is not needed anymore */
- HW_DESC_SET_DIN_TYPE(&desc[0], DMA_DLLI, ctx->auth_state.xcbc.xcbc_keys_dma_addr, ctx->auth_keylen, NS_BIT);
- HW_DESC_SET_CIPHER_MODE(&desc[0], DRV_CIPHER_ECB);
- HW_DESC_SET_CIPHER_CONFIG0(&desc[0], DRV_CRYPTO_DIRECTION_ENCRYPT);
- HW_DESC_SET_KEY_SIZE_AES(&desc[0], ctx->auth_keylen);
- HW_DESC_SET_FLOW_MODE(&desc[0], S_DIN_to_AES);
- HW_DESC_SET_SETUP_MODE(&desc[0], SETUP_LOAD_KEY0);
-
- HW_DESC_INIT(&desc[1]);
- HW_DESC_SET_DIN_CONST(&desc[1], 0x01010101, CC_AES_128_BIT_KEY_SIZE);
- HW_DESC_SET_FLOW_MODE(&desc[1], DIN_AES_DOUT);
- HW_DESC_SET_DOUT_DLLI(&desc[1], ctx->auth_state.xcbc.xcbc_keys_dma_addr, AES_KEYSIZE_128, NS_BIT, 0);
-
- HW_DESC_INIT(&desc[2]);
- HW_DESC_SET_DIN_CONST(&desc[2], 0x02020202, CC_AES_128_BIT_KEY_SIZE);
- HW_DESC_SET_FLOW_MODE(&desc[2], DIN_AES_DOUT);
- HW_DESC_SET_DOUT_DLLI(&desc[2], (ctx->auth_state.xcbc.xcbc_keys_dma_addr
+ * because after this key loading it is not needed anymore
+ */
+ set_din_type(&desc[0], DMA_DLLI,
+ ctx->auth_state.xcbc.xcbc_keys_dma_addr, ctx->auth_keylen,
+ NS_BIT);
+ set_cipher_mode(&desc[0], DRV_CIPHER_ECB);
+ set_cipher_config0(&desc[0], DRV_CRYPTO_DIRECTION_ENCRYPT);
+ set_key_size_aes(&desc[0], ctx->auth_keylen);
+ set_flow_mode(&desc[0], S_DIN_to_AES);
+ set_setup_mode(&desc[0], SETUP_LOAD_KEY0);
+
+ hw_desc_init(&desc[1]);
+ set_din_const(&desc[1], 0x01010101, CC_AES_128_BIT_KEY_SIZE);
+ set_flow_mode(&desc[1], DIN_AES_DOUT);
+ set_dout_dlli(&desc[1], ctx->auth_state.xcbc.xcbc_keys_dma_addr,
+ AES_KEYSIZE_128, NS_BIT, 0);
+
+ hw_desc_init(&desc[2]);
+ set_din_const(&desc[2], 0x02020202, CC_AES_128_BIT_KEY_SIZE);
+ set_flow_mode(&desc[2], DIN_AES_DOUT);
+ set_dout_dlli(&desc[2], (ctx->auth_state.xcbc.xcbc_keys_dma_addr
+ AES_KEYSIZE_128),
AES_KEYSIZE_128, NS_BIT, 0);
- HW_DESC_INIT(&desc[3]);
- HW_DESC_SET_DIN_CONST(&desc[3], 0x03030303, CC_AES_128_BIT_KEY_SIZE);
- HW_DESC_SET_FLOW_MODE(&desc[3], DIN_AES_DOUT);
- HW_DESC_SET_DOUT_DLLI(&desc[3], (ctx->auth_state.xcbc.xcbc_keys_dma_addr
+ hw_desc_init(&desc[3]);
+ set_din_const(&desc[3], 0x03030303, CC_AES_128_BIT_KEY_SIZE);
+ set_flow_mode(&desc[3], DIN_AES_DOUT);
+ set_dout_dlli(&desc[3], (ctx->auth_state.xcbc.xcbc_keys_dma_addr
+ 2 * AES_KEYSIZE_128),
AES_KEYSIZE_128, NS_BIT, 0);
return 4;
}
-static int hmac_setkey(HwDesc_s *desc, struct ssi_aead_ctx *ctx)
+static int hmac_setkey(struct cc_hw_desc *desc, struct ssi_aead_ctx *ctx)
{
unsigned int hmacPadConst[2] = { HMAC_IPAD_CONST, HMAC_OPAD_CONST };
unsigned int digest_ofs = 0;
- unsigned int hash_mode = (ctx->auth_mode == DRV_HASH_SHA1) ?
+ unsigned int hash_mode = (ctx->auth_mode == DRV_HASH_SHA1) ?
DRV_HASH_HW_SHA1 : DRV_HASH_HW_SHA256;
- unsigned int digest_size = (ctx->auth_mode == DRV_HASH_SHA1) ?
+ unsigned int digest_size = (ctx->auth_mode == DRV_HASH_SHA1) ?
CC_SHA1_DIGEST_SIZE : CC_SHA256_DIGEST_SIZE;
int idx = 0;
@@ -324,52 +305,51 @@ static int hmac_setkey(HwDesc_s *desc, struct ssi_aead_ctx *ctx)
/* calc derived HMAC key */
for (i = 0; i < 2; i++) {
/* Load hash initial state */
- HW_DESC_INIT(&desc[idx]);
- HW_DESC_SET_CIPHER_MODE(&desc[idx], hash_mode);
- HW_DESC_SET_DIN_SRAM(&desc[idx],
- ssi_ahash_get_larval_digest_sram_addr(
+ hw_desc_init(&desc[idx]);
+ set_cipher_mode(&desc[idx], hash_mode);
+ set_din_sram(&desc[idx],
+ ssi_ahash_get_larval_digest_sram_addr(
ctx->drvdata, ctx->auth_mode),
- digest_size);
- HW_DESC_SET_FLOW_MODE(&desc[idx], S_DIN_to_HASH);
- HW_DESC_SET_SETUP_MODE(&desc[idx], SETUP_LOAD_STATE0);
+ digest_size);
+ set_flow_mode(&desc[idx], S_DIN_to_HASH);
+ set_setup_mode(&desc[idx], SETUP_LOAD_STATE0);
idx++;
/* Load the hash current length*/
- HW_DESC_INIT(&desc[idx]);
- HW_DESC_SET_CIPHER_MODE(&desc[idx], hash_mode);
- HW_DESC_SET_DIN_CONST(&desc[idx], 0, HASH_LEN_SIZE);
- HW_DESC_SET_FLOW_MODE(&desc[idx], S_DIN_to_HASH);
- HW_DESC_SET_SETUP_MODE(&desc[idx], SETUP_LOAD_KEY0);
+ hw_desc_init(&desc[idx]);
+ set_cipher_mode(&desc[idx], hash_mode);
+ set_din_const(&desc[idx], 0, HASH_LEN_SIZE);
+ set_flow_mode(&desc[idx], S_DIN_to_HASH);
+ set_setup_mode(&desc[idx], SETUP_LOAD_KEY0);
idx++;
/* Prepare ipad key */
- HW_DESC_INIT(&desc[idx]);
- HW_DESC_SET_XOR_VAL(&desc[idx], hmacPadConst[i]);
- HW_DESC_SET_CIPHER_MODE(&desc[idx], hash_mode);
- HW_DESC_SET_FLOW_MODE(&desc[idx], S_DIN_to_HASH);
- HW_DESC_SET_SETUP_MODE(&desc[idx], SETUP_LOAD_STATE1);
+ hw_desc_init(&desc[idx]);
+ set_xor_val(&desc[idx], hmacPadConst[i]);
+ set_cipher_mode(&desc[idx], hash_mode);
+ set_flow_mode(&desc[idx], S_DIN_to_HASH);
+ set_setup_mode(&desc[idx], SETUP_LOAD_STATE1);
idx++;
/* Perform HASH update */
- HW_DESC_INIT(&desc[idx]);
- HW_DESC_SET_DIN_TYPE(&desc[idx], DMA_DLLI,
- ctx->auth_state.hmac.padded_authkey_dma_addr,
- SHA256_BLOCK_SIZE, NS_BIT);
- HW_DESC_SET_CIPHER_MODE(&desc[idx], hash_mode);
- HW_DESC_SET_XOR_ACTIVE(&desc[idx]);
- HW_DESC_SET_FLOW_MODE(&desc[idx], DIN_HASH);
+ hw_desc_init(&desc[idx]);
+ set_din_type(&desc[idx], DMA_DLLI,
+ ctx->auth_state.hmac.padded_authkey_dma_addr,
+ SHA256_BLOCK_SIZE, NS_BIT);
+ set_cipher_mode(&desc[idx], hash_mode);
+ set_xor_active(&desc[idx]);
+ set_flow_mode(&desc[idx], DIN_HASH);
idx++;
/* Get the digset */
- HW_DESC_INIT(&desc[idx]);
- HW_DESC_SET_CIPHER_MODE(&desc[idx], hash_mode);
- HW_DESC_SET_DOUT_DLLI(&desc[idx],
- (ctx->auth_state.hmac.ipad_opad_dma_addr +
- digest_ofs),
- digest_size, NS_BIT, 0);
- HW_DESC_SET_FLOW_MODE(&desc[idx], S_HASH_to_DOUT);
- HW_DESC_SET_SETUP_MODE(&desc[idx], SETUP_WRITE_STATE0);
- HW_DESC_SET_CIPHER_CONFIG1(&desc[idx], HASH_PADDING_DISABLED);
+ hw_desc_init(&desc[idx]);
+ set_cipher_mode(&desc[idx], hash_mode);
+ set_dout_dlli(&desc[idx],
+ (ctx->auth_state.hmac.ipad_opad_dma_addr +
+ digest_ofs), digest_size, NS_BIT, 0);
+ set_flow_mode(&desc[idx], S_HASH_to_DOUT);
+ set_setup_mode(&desc[idx], SETUP_WRITE_STATE0);
+ set_cipher_config1(&desc[idx], HASH_PADDING_DISABLED);
idx++;
digest_ofs += digest_size;
@@ -420,15 +400,17 @@ static int validate_keys_sizes(struct ssi_aead_ctx *ctx)
return 0; /* All tests of keys sizes passed */
}
-/*This function prepers the user key so it can pass to the hmac processing
- (copy to intenral buffer or hash in case of key longer than block */
+
+/* This function prepers the user key so it can pass to the hmac processing
+ * (copy to intenral buffer or hash in case of key longer than block
+ */
static int
ssi_get_plain_hmac_key(struct crypto_aead *tfm, const u8 *key, unsigned int keylen)
{
dma_addr_t key_dma_addr = 0;
struct ssi_aead_ctx *ctx = crypto_aead_ctx(tfm);
struct device *dev = &ctx->drvdata->plat_dev->dev;
- uint32_t larval_addr = ssi_ahash_get_larval_digest_sram_addr(
+ u32 larval_addr = ssi_ahash_get_larval_digest_sram_addr(
ctx->drvdata, ctx->auth_mode);
struct ssi_crypto_req ssi_req = {};
unsigned int blocksize;
@@ -436,8 +418,8 @@ ssi_get_plain_hmac_key(struct crypto_aead *tfm, const u8 *key, unsigned int keyl
unsigned int hashmode;
unsigned int idx = 0;
int rc = 0;
- HwDesc_s desc[MAX_AEAD_SETKEY_SEQ];
- dma_addr_t padded_authkey_dma_addr =
+ struct cc_hw_desc desc[MAX_AEAD_SETKEY_SEQ];
+ dma_addr_t padded_authkey_dma_addr =
ctx->auth_state.hmac.padded_authkey_dma_addr;
switch (ctx->auth_mode) { /* auth_key required and >0 */
@@ -460,107 +442,89 @@ ssi_get_plain_hmac_key(struct crypto_aead *tfm, const u8 *key, unsigned int keyl
" DMA failed\n", key, keylen);
return -ENOMEM;
}
- SSI_UPDATE_DMA_ADDR_TO_48BIT(key_dma_addr, keylen);
if (keylen > blocksize) {
/* Load hash initial state */
- HW_DESC_INIT(&desc[idx]);
- HW_DESC_SET_CIPHER_MODE(&desc[idx], hashmode);
- HW_DESC_SET_DIN_SRAM(&desc[idx], larval_addr, digestsize);
- HW_DESC_SET_FLOW_MODE(&desc[idx], S_DIN_to_HASH);
- HW_DESC_SET_SETUP_MODE(&desc[idx], SETUP_LOAD_STATE0);
+ hw_desc_init(&desc[idx]);
+ set_cipher_mode(&desc[idx], hashmode);
+ set_din_sram(&desc[idx], larval_addr, digestsize);
+ set_flow_mode(&desc[idx], S_DIN_to_HASH);
+ set_setup_mode(&desc[idx], SETUP_LOAD_STATE0);
idx++;
-
+
/* Load the hash current length*/
- HW_DESC_INIT(&desc[idx]);
- HW_DESC_SET_CIPHER_MODE(&desc[idx], hashmode);
- HW_DESC_SET_DIN_CONST(&desc[idx], 0, HASH_LEN_SIZE);
- HW_DESC_SET_CIPHER_CONFIG1(&desc[idx], HASH_PADDING_ENABLED);
- HW_DESC_SET_FLOW_MODE(&desc[idx], S_DIN_to_HASH);
- HW_DESC_SET_SETUP_MODE(&desc[idx], SETUP_LOAD_KEY0);
+ hw_desc_init(&desc[idx]);
+ set_cipher_mode(&desc[idx], hashmode);
+ set_din_const(&desc[idx], 0, HASH_LEN_SIZE);
+ set_cipher_config1(&desc[idx], HASH_PADDING_ENABLED);
+ set_flow_mode(&desc[idx], S_DIN_to_HASH);
+ set_setup_mode(&desc[idx], SETUP_LOAD_KEY0);
idx++;
-
- HW_DESC_INIT(&desc[idx]);
- HW_DESC_SET_DIN_TYPE(&desc[idx], DMA_DLLI,
- key_dma_addr,
- keylen, NS_BIT);
- HW_DESC_SET_FLOW_MODE(&desc[idx], DIN_HASH);
+
+ hw_desc_init(&desc[idx]);
+ set_din_type(&desc[idx], DMA_DLLI,
+ key_dma_addr, keylen, NS_BIT);
+ set_flow_mode(&desc[idx], DIN_HASH);
idx++;
-
+
/* Get hashed key */
- HW_DESC_INIT(&desc[idx]);
- HW_DESC_SET_CIPHER_MODE(&desc[idx], hashmode);
- HW_DESC_SET_DOUT_DLLI(&desc[idx],
- padded_authkey_dma_addr,
- digestsize,
- NS_BIT, 0);
- HW_DESC_SET_FLOW_MODE(&desc[idx], S_HASH_to_DOUT);
- HW_DESC_SET_SETUP_MODE(&desc[idx], SETUP_WRITE_STATE0);
- HW_DESC_SET_CIPHER_CONFIG1(&desc[idx],
- HASH_PADDING_DISABLED);
- HW_DESC_SET_CIPHER_CONFIG0(&desc[idx],
- HASH_DIGEST_RESULT_LITTLE_ENDIAN);
+ hw_desc_init(&desc[idx]);
+ set_cipher_mode(&desc[idx], hashmode);
+ set_dout_dlli(&desc[idx], padded_authkey_dma_addr,
+ digestsize, NS_BIT, 0);
+ set_flow_mode(&desc[idx], S_HASH_to_DOUT);
+ set_setup_mode(&desc[idx], SETUP_WRITE_STATE0);
+ set_cipher_config1(&desc[idx], HASH_PADDING_DISABLED);
+ set_cipher_config0(&desc[idx],
+ HASH_DIGEST_RESULT_LITTLE_ENDIAN);
idx++;
-
- HW_DESC_INIT(&desc[idx]);
- HW_DESC_SET_DIN_CONST(&desc[idx], 0, (blocksize - digestsize));
- HW_DESC_SET_FLOW_MODE(&desc[idx], BYPASS);
- HW_DESC_SET_DOUT_DLLI(&desc[idx],
- (padded_authkey_dma_addr + digestsize),
- (blocksize - digestsize),
- NS_BIT, 0);
+
+ hw_desc_init(&desc[idx]);
+ set_din_const(&desc[idx], 0, (blocksize - digestsize));
+ set_flow_mode(&desc[idx], BYPASS);
+ set_dout_dlli(&desc[idx], (padded_authkey_dma_addr +
+ digestsize), (blocksize - digestsize),
+ NS_BIT, 0);
idx++;
} else {
- HW_DESC_INIT(&desc[idx]);
- HW_DESC_SET_DIN_TYPE(&desc[idx], DMA_DLLI,
- key_dma_addr,
- keylen, NS_BIT);
- HW_DESC_SET_FLOW_MODE(&desc[idx], BYPASS);
- HW_DESC_SET_DOUT_DLLI(&desc[idx],
- (padded_authkey_dma_addr),
- keylen, NS_BIT, 0);
+ hw_desc_init(&desc[idx]);
+ set_din_type(&desc[idx], DMA_DLLI, key_dma_addr,
+ keylen, NS_BIT);
+ set_flow_mode(&desc[idx], BYPASS);
+ set_dout_dlli(&desc[idx], padded_authkey_dma_addr,
+ keylen, NS_BIT, 0);
idx++;
-
+
if ((blocksize - keylen) != 0) {
- HW_DESC_INIT(&desc[idx]);
- HW_DESC_SET_DIN_CONST(&desc[idx], 0,
- (blocksize - keylen));
- HW_DESC_SET_FLOW_MODE(&desc[idx], BYPASS);
- HW_DESC_SET_DOUT_DLLI(&desc[idx],
- (padded_authkey_dma_addr + keylen),
- (blocksize - keylen),
- NS_BIT, 0);
+ hw_desc_init(&desc[idx]);
+ set_din_const(&desc[idx], 0,
+ (blocksize - keylen));
+ set_flow_mode(&desc[idx], BYPASS);
+ set_dout_dlli(&desc[idx],
+ (padded_authkey_dma_addr +
+ keylen),
+ (blocksize - keylen), NS_BIT, 0);
idx++;
}
}
} else {
- HW_DESC_INIT(&desc[idx]);
- HW_DESC_SET_DIN_CONST(&desc[idx], 0,
- (blocksize - keylen));
- HW_DESC_SET_FLOW_MODE(&desc[idx], BYPASS);
- HW_DESC_SET_DOUT_DLLI(&desc[idx],
- padded_authkey_dma_addr,
- blocksize,
- NS_BIT, 0);
+ hw_desc_init(&desc[idx]);
+ set_din_const(&desc[idx], 0, (blocksize - keylen));
+ set_flow_mode(&desc[idx], BYPASS);
+ set_dout_dlli(&desc[idx], padded_authkey_dma_addr,
+ blocksize, NS_BIT, 0);
idx++;
}
-#ifdef ENABLE_CYCLE_COUNT
- ssi_req.op_type = STAT_OP_TYPE_SETKEY;
-#endif
-
rc = send_request(ctx->drvdata, &ssi_req, desc, idx, 0);
if (unlikely(rc != 0))
SSI_LOG_ERR("send_request() failed (rc=%d)\n", rc);
- if (likely(key_dma_addr != 0)) {
- SSI_RESTORE_DMA_ADDR_TO_48BIT(key_dma_addr);
+ if (likely(key_dma_addr != 0))
dma_unmap_single(dev, key_dma_addr, keylen, DMA_TO_DEVICE);
- }
return rc;
}
-
static int
ssi_aead_setkey(struct crypto_aead *tfm, const u8 *key, unsigned int keylen)
{
@@ -568,16 +532,14 @@ ssi_aead_setkey(struct crypto_aead *tfm, const u8 *key, unsigned int keylen)
struct rtattr *rta = (struct rtattr *)key;
struct ssi_crypto_req ssi_req = {};
struct crypto_authenc_key_param *param;
- HwDesc_s desc[MAX_AEAD_SETKEY_SEQ];
+ struct cc_hw_desc desc[MAX_AEAD_SETKEY_SEQ];
int seq_len = 0, rc = -EINVAL;
- DECL_CYCLE_COUNT_RESOURCES;
SSI_LOG_DEBUG("Setting key in context @%p for %s. key=%p keylen=%u\n",
ctx, crypto_tfm_alg_name(crypto_aead_tfm(tfm)), key, keylen);
CHECK_AND_RETURN_UPON_FIPS_ERROR();
/* STAT_PHASE_0: Init and sanity checks */
- START_CYCLE_COUNT();
if (ctx->auth_mode != DRV_HASH_NULL) { /* authenc() alg. */
if (!RTA_OK(rta, keylen))
@@ -600,7 +562,8 @@ ssi_aead_setkey(struct crypto_aead *tfm, const u8 *key, unsigned int keylen)
(AES_MIN_KEY_SIZE + CTR_RFC3686_NONCE_SIZE))
goto badkey;
/* Copy nonce from last 4 bytes in CTR key to
- * first 4 bytes in CTR IV */
+ * first 4 bytes in CTR IV
+ */
memcpy(ctx->ctr_nonce, key + ctx->auth_keylen + ctx->enc_keylen -
CTR_RFC3686_NONCE_SIZE, CTR_RFC3686_NONCE_SIZE);
/* Set CTR key size */
@@ -615,9 +578,7 @@ ssi_aead_setkey(struct crypto_aead *tfm, const u8 *key, unsigned int keylen)
if (unlikely(rc != 0))
goto badkey;
- END_CYCLE_COUNT(STAT_OP_TYPE_SETKEY, STAT_PHASE_0);
/* STAT_PHASE_1: Copy key to ctx */
- START_CYCLE_COUNT();
/* Get key material */
memcpy(ctx->enckey, key + ctx->auth_keylen, ctx->enc_keylen);
@@ -631,10 +592,7 @@ ssi_aead_setkey(struct crypto_aead *tfm, const u8 *key, unsigned int keylen)
goto badkey;
}
- END_CYCLE_COUNT(STAT_OP_TYPE_SETKEY, STAT_PHASE_1);
-
/* STAT_PHASE_2: Create sequence */
- START_CYCLE_COUNT();
switch (ctx->auth_mode) {
case DRV_HASH_SHA1:
@@ -652,15 +610,9 @@ ssi_aead_setkey(struct crypto_aead *tfm, const u8 *key, unsigned int keylen)
goto badkey;
}
- END_CYCLE_COUNT(STAT_OP_TYPE_SETKEY, STAT_PHASE_2);
-
/* STAT_PHASE_3: Submit sequence to HW */
- START_CYCLE_COUNT();
-
+
if (seq_len > 0) { /* For CCM there is no sequence to setup the key */
-#ifdef ENABLE_CYCLE_COUNT
- ssi_req.op_type = STAT_OP_TYPE_SETKEY;
-#endif
rc = send_request(ctx->drvdata, &ssi_req, desc, seq_len, 0);
if (unlikely(rc != 0)) {
SSI_LOG_ERR("send_request() failed (rc=%d)\n", rc);
@@ -669,7 +621,6 @@ ssi_aead_setkey(struct crypto_aead *tfm, const u8 *key, unsigned int keylen)
}
/* Update STAT_PHASE_3 */
- END_CYCLE_COUNT(STAT_OP_TYPE_SETKEY, STAT_PHASE_3);
return rc;
badkey:
@@ -684,7 +635,7 @@ static int ssi_rfc4309_ccm_setkey(struct crypto_aead *tfm, const u8 *key, unsign
{
struct ssi_aead_ctx *ctx = crypto_aead_ctx(tfm);
int rc = 0;
-
+
if (keylen < 3)
return -EINVAL;
@@ -702,11 +653,11 @@ static int ssi_aead_setauthsize(
unsigned int authsize)
{
struct ssi_aead_ctx *ctx = crypto_aead_ctx(authenc);
-
+
CHECK_AND_RETURN_UPON_FIPS_ERROR();
/* Unsupported auth. sizes */
if ((authsize == 0) ||
- (authsize >crypto_aead_maxauthsize(authenc))) {
+ (authsize > crypto_aead_maxauthsize(authenc))) {
return -ENOTSUPP;
}
@@ -752,11 +703,11 @@ static int ssi_ccm_setauthsize(struct crypto_aead *authenc,
}
#endif /*SSI_CC_HAS_AES_CCM*/
-static inline void
+static inline void
ssi_aead_create_assoc_desc(
- struct aead_request *areq,
+ struct aead_request *areq,
unsigned int flow_mode,
- HwDesc_s desc[],
+ struct cc_hw_desc desc[],
unsigned int *seq_size)
{
struct crypto_aead *tfm = crypto_aead_reqtfm(areq);
@@ -768,24 +719,23 @@ ssi_aead_create_assoc_desc(
switch (assoc_dma_type) {
case SSI_DMA_BUF_DLLI:
SSI_LOG_DEBUG("ASSOC buffer type DLLI\n");
- HW_DESC_INIT(&desc[idx]);
- HW_DESC_SET_DIN_TYPE(&desc[idx], DMA_DLLI,
- sg_dma_address(areq->src),
- areq->assoclen, NS_BIT);
- HW_DESC_SET_FLOW_MODE(&desc[idx], flow_mode);
- if (ctx->auth_mode == DRV_HASH_XCBC_MAC && (areq_ctx->cryptlen > 0) )
- HW_DESC_SET_DIN_NOT_LAST_INDICATION(&desc[idx]);
+ hw_desc_init(&desc[idx]);
+ set_din_type(&desc[idx], DMA_DLLI, sg_dma_address(areq->src),
+ areq->assoclen, NS_BIT); set_flow_mode(&desc[idx],
+ flow_mode);
+ if ((ctx->auth_mode == DRV_HASH_XCBC_MAC) &&
+ (areq_ctx->cryptlen > 0))
+ set_din_not_last_indication(&desc[idx]);
break;
case SSI_DMA_BUF_MLLI:
SSI_LOG_DEBUG("ASSOC buffer type MLLI\n");
- HW_DESC_INIT(&desc[idx]);
- HW_DESC_SET_DIN_TYPE(&desc[idx], DMA_MLLI,
- areq_ctx->assoc.sram_addr,
- areq_ctx->assoc.mlli_nents,
- NS_BIT);
- HW_DESC_SET_FLOW_MODE(&desc[idx], flow_mode);
- if (ctx->auth_mode == DRV_HASH_XCBC_MAC && (areq_ctx->cryptlen > 0) )
- HW_DESC_SET_DIN_NOT_LAST_INDICATION(&desc[idx]);
+ hw_desc_init(&desc[idx]);
+ set_din_type(&desc[idx], DMA_MLLI, areq_ctx->assoc.sram_addr,
+ areq_ctx->assoc.mlli_nents, NS_BIT);
+ set_flow_mode(&desc[idx], flow_mode);
+ if ((ctx->auth_mode == DRV_HASH_XCBC_MAC) &&
+ (areq_ctx->cryptlen > 0))
+ set_din_not_last_indication(&desc[idx]);
break;
case SSI_DMA_BUF_NULL:
default:
@@ -797,9 +747,9 @@ ssi_aead_create_assoc_desc(
static inline void
ssi_aead_process_authenc_data_desc(
- struct aead_request *areq,
+ struct aead_request *areq,
unsigned int flow_mode,
- HwDesc_s desc[],
+ struct cc_hw_desc desc[],
unsigned int *seq_size,
int direct)
{
@@ -814,27 +764,28 @@ ssi_aead_process_authenc_data_desc(
(direct == DRV_CRYPTO_DIRECTION_ENCRYPT) ?
areq_ctx->dstSgl : areq_ctx->srcSgl;
- unsigned int offset =
+ unsigned int offset =
(direct == DRV_CRYPTO_DIRECTION_ENCRYPT) ?
areq_ctx->dstOffset : areq_ctx->srcOffset;
SSI_LOG_DEBUG("AUTHENC: SRC/DST buffer type DLLI\n");
- HW_DESC_INIT(&desc[idx]);
- HW_DESC_SET_DIN_TYPE(&desc[idx], DMA_DLLI,
- (sg_dma_address(cipher)+ offset), areq_ctx->cryptlen,
- NS_BIT);
- HW_DESC_SET_FLOW_MODE(&desc[idx], flow_mode);
+ hw_desc_init(&desc[idx]);
+ set_din_type(&desc[idx], DMA_DLLI,
+ (sg_dma_address(cipher) + offset),
+ areq_ctx->cryptlen, NS_BIT);
+ set_flow_mode(&desc[idx], flow_mode);
break;
}
case SSI_DMA_BUF_MLLI:
{
/* DOUBLE-PASS flow (as default)
* assoc. + iv + data -compact in one table
- * if assoclen is ZERO only IV perform */
+ * if assoclen is ZERO only IV perform
+ */
ssi_sram_addr_t mlli_addr = areq_ctx->assoc.sram_addr;
- uint32_t mlli_nents = areq_ctx->assoc.mlli_nents;
+ u32 mlli_nents = areq_ctx->assoc.mlli_nents;
- if (likely(areq_ctx->is_single_pass == true)) {
- if (direct == DRV_CRYPTO_DIRECTION_ENCRYPT){
+ if (likely(areq_ctx->is_single_pass)) {
+ if (direct == DRV_CRYPTO_DIRECTION_ENCRYPT) {
mlli_addr = areq_ctx->dst.sram_addr;
mlli_nents = areq_ctx->dst.mlli_nents;
} else {
@@ -844,10 +795,10 @@ ssi_aead_process_authenc_data_desc(
}
SSI_LOG_DEBUG("AUTHENC: SRC/DST buffer type MLLI\n");
- HW_DESC_INIT(&desc[idx]);
- HW_DESC_SET_DIN_TYPE(&desc[idx], DMA_MLLI,
- mlli_addr, mlli_nents, NS_BIT);
- HW_DESC_SET_FLOW_MODE(&desc[idx], flow_mode);
+ hw_desc_init(&desc[idx]);
+ set_din_type(&desc[idx], DMA_MLLI, mlli_addr, mlli_nents,
+ NS_BIT);
+ set_flow_mode(&desc[idx], flow_mode);
break;
}
case SSI_DMA_BUF_NULL:
@@ -860,9 +811,9 @@ ssi_aead_process_authenc_data_desc(
static inline void
ssi_aead_process_cipher_data_desc(
- struct aead_request *areq,
+ struct aead_request *areq,
unsigned int flow_mode,
- HwDesc_s desc[],
+ struct cc_hw_desc desc[],
unsigned int *seq_size)
{
unsigned int idx = *seq_size;
@@ -875,25 +826,24 @@ ssi_aead_process_cipher_data_desc(
switch (data_dma_type) {
case SSI_DMA_BUF_DLLI:
SSI_LOG_DEBUG("CIPHER: SRC/DST buffer type DLLI\n");
- HW_DESC_INIT(&desc[idx]);
- HW_DESC_SET_DIN_TYPE(&desc[idx], DMA_DLLI,
- (sg_dma_address(areq_ctx->srcSgl)+areq_ctx->srcOffset),
- areq_ctx->cryptlen, NS_BIT);
- HW_DESC_SET_DOUT_DLLI(&desc[idx],
- (sg_dma_address(areq_ctx->dstSgl)+areq_ctx->dstOffset),
- areq_ctx->cryptlen, NS_BIT, 0);
- HW_DESC_SET_FLOW_MODE(&desc[idx], flow_mode);
+ hw_desc_init(&desc[idx]);
+ set_din_type(&desc[idx], DMA_DLLI,
+ (sg_dma_address(areq_ctx->srcSgl) +
+ areq_ctx->srcOffset), areq_ctx->cryptlen, NS_BIT);
+ set_dout_dlli(&desc[idx],
+ (sg_dma_address(areq_ctx->dstSgl) +
+ areq_ctx->dstOffset),
+ areq_ctx->cryptlen, NS_BIT, 0);
+ set_flow_mode(&desc[idx], flow_mode);
break;
case SSI_DMA_BUF_MLLI:
SSI_LOG_DEBUG("CIPHER: SRC/DST buffer type MLLI\n");
- HW_DESC_INIT(&desc[idx]);
- HW_DESC_SET_DIN_TYPE(&desc[idx], DMA_MLLI,
- areq_ctx->src.sram_addr,
- areq_ctx->src.mlli_nents, NS_BIT);
- HW_DESC_SET_DOUT_MLLI(&desc[idx],
- areq_ctx->dst.sram_addr,
- areq_ctx->dst.mlli_nents, NS_BIT, 0);
- HW_DESC_SET_FLOW_MODE(&desc[idx], flow_mode);
+ hw_desc_init(&desc[idx]);
+ set_din_type(&desc[idx], DMA_MLLI, areq_ctx->src.sram_addr,
+ areq_ctx->src.mlli_nents, NS_BIT);
+ set_dout_mlli(&desc[idx], areq_ctx->dst.sram_addr,
+ areq_ctx->dst.mlli_nents, NS_BIT, 0);
+ set_flow_mode(&desc[idx], flow_mode);
break;
case SSI_DMA_BUF_NULL:
default:
@@ -905,7 +855,7 @@ ssi_aead_process_cipher_data_desc(
static inline void ssi_aead_process_digest_result_desc(
struct aead_request *req,
- HwDesc_s desc[],
+ struct cc_hw_desc desc[],
unsigned int *seq_size)
{
struct crypto_aead *tfm = crypto_aead_reqtfm(req);
@@ -918,35 +868,36 @@ static inline void ssi_aead_process_digest_result_desc(
/* Get final ICV result */
if (direct == DRV_CRYPTO_DIRECTION_ENCRYPT) {
- HW_DESC_INIT(&desc[idx]);
- HW_DESC_SET_FLOW_MODE(&desc[idx], S_HASH_to_DOUT);
- HW_DESC_SET_SETUP_MODE(&desc[idx], SETUP_WRITE_STATE0);
- HW_DESC_SET_DOUT_DLLI(&desc[idx], req_ctx->icv_dma_addr,
- ctx->authsize, NS_BIT, 1);
- HW_DESC_SET_QUEUE_LAST_IND(&desc[idx]);
+ hw_desc_init(&desc[idx]);
+ set_flow_mode(&desc[idx], S_HASH_to_DOUT);
+ set_setup_mode(&desc[idx], SETUP_WRITE_STATE0);
+ set_dout_dlli(&desc[idx], req_ctx->icv_dma_addr, ctx->authsize,
+ NS_BIT, 1);
+ set_queue_last_ind(&desc[idx]);
if (ctx->auth_mode == DRV_HASH_XCBC_MAC) {
- HW_DESC_SET_AES_NOT_HASH_MODE(&desc[idx]);
- HW_DESC_SET_CIPHER_MODE(&desc[idx], DRV_CIPHER_XCBC_MAC);
+ set_aes_not_hash_mode(&desc[idx]);
+ set_cipher_mode(&desc[idx], DRV_CIPHER_XCBC_MAC);
} else {
- HW_DESC_SET_CIPHER_CONFIG0(&desc[idx],
- HASH_DIGEST_RESULT_LITTLE_ENDIAN);
- HW_DESC_SET_CIPHER_MODE(&desc[idx], hash_mode);
+ set_cipher_config0(&desc[idx],
+ HASH_DIGEST_RESULT_LITTLE_ENDIAN);
+ set_cipher_mode(&desc[idx], hash_mode);
}
} else { /*Decrypt*/
/* Get ICV out from hardware */
- HW_DESC_INIT(&desc[idx]);
- HW_DESC_SET_SETUP_MODE(&desc[idx], SETUP_WRITE_STATE0);
- HW_DESC_SET_FLOW_MODE(&desc[idx], S_HASH_to_DOUT);
- HW_DESC_SET_DOUT_DLLI(&desc[idx], req_ctx->mac_buf_dma_addr,
- ctx->authsize, NS_BIT, 1);
- HW_DESC_SET_QUEUE_LAST_IND(&desc[idx]);
- HW_DESC_SET_CIPHER_CONFIG0(&desc[idx], HASH_DIGEST_RESULT_LITTLE_ENDIAN);
- HW_DESC_SET_CIPHER_CONFIG1(&desc[idx], HASH_PADDING_DISABLED);
+ hw_desc_init(&desc[idx]);
+ set_setup_mode(&desc[idx], SETUP_WRITE_STATE0);
+ set_flow_mode(&desc[idx], S_HASH_to_DOUT);
+ set_dout_dlli(&desc[idx], req_ctx->mac_buf_dma_addr,
+ ctx->authsize, NS_BIT, 1);
+ set_queue_last_ind(&desc[idx]);
+ set_cipher_config0(&desc[idx],
+ HASH_DIGEST_RESULT_LITTLE_ENDIAN);
+ set_cipher_config1(&desc[idx], HASH_PADDING_DISABLED);
if (ctx->auth_mode == DRV_HASH_XCBC_MAC) {
- HW_DESC_SET_CIPHER_MODE(&desc[idx], DRV_CIPHER_XCBC_MAC);
- HW_DESC_SET_AES_NOT_HASH_MODE(&desc[idx]);
+ set_cipher_mode(&desc[idx], DRV_CIPHER_XCBC_MAC);
+ set_aes_not_hash_mode(&desc[idx]);
} else {
- HW_DESC_SET_CIPHER_MODE(&desc[idx], hash_mode);
+ set_cipher_mode(&desc[idx], hash_mode);
}
}
@@ -955,7 +906,7 @@ static inline void ssi_aead_process_digest_result_desc(
static inline void ssi_aead_setup_cipher_desc(
struct aead_request *req,
- HwDesc_s desc[],
+ struct cc_hw_desc desc[],
unsigned int *seq_size)
{
struct crypto_aead *tfm = crypto_aead_reqtfm(req);
@@ -966,35 +917,34 @@ static inline void ssi_aead_setup_cipher_desc(
int direct = req_ctx->gen_ctx.op_type;
/* Setup cipher state */
- HW_DESC_INIT(&desc[idx]);
- HW_DESC_SET_CIPHER_CONFIG0(&desc[idx], direct);
- HW_DESC_SET_FLOW_MODE(&desc[idx], ctx->flow_mode);
- HW_DESC_SET_DIN_TYPE(&desc[idx], DMA_DLLI,
- req_ctx->gen_ctx.iv_dma_addr, hw_iv_size, NS_BIT);
- if (ctx->cipher_mode == DRV_CIPHER_CTR) {
- HW_DESC_SET_SETUP_MODE(&desc[idx], SETUP_LOAD_STATE1);
- } else {
- HW_DESC_SET_SETUP_MODE(&desc[idx], SETUP_LOAD_STATE0);
- }
- HW_DESC_SET_CIPHER_MODE(&desc[idx], ctx->cipher_mode);
+ hw_desc_init(&desc[idx]);
+ set_cipher_config0(&desc[idx], direct);
+ set_flow_mode(&desc[idx], ctx->flow_mode);
+ set_din_type(&desc[idx], DMA_DLLI, req_ctx->gen_ctx.iv_dma_addr,
+ hw_iv_size, NS_BIT);
+ if (ctx->cipher_mode == DRV_CIPHER_CTR)
+ set_setup_mode(&desc[idx], SETUP_LOAD_STATE1);
+ else
+ set_setup_mode(&desc[idx], SETUP_LOAD_STATE0);
+ set_cipher_mode(&desc[idx], ctx->cipher_mode);
idx++;
/* Setup enc. key */
- HW_DESC_INIT(&desc[idx]);
- HW_DESC_SET_CIPHER_CONFIG0(&desc[idx], direct);
- HW_DESC_SET_SETUP_MODE(&desc[idx], SETUP_LOAD_KEY0);
- HW_DESC_SET_FLOW_MODE(&desc[idx], ctx->flow_mode);
+ hw_desc_init(&desc[idx]);
+ set_cipher_config0(&desc[idx], direct);
+ set_setup_mode(&desc[idx], SETUP_LOAD_KEY0);
+ set_flow_mode(&desc[idx], ctx->flow_mode);
if (ctx->flow_mode == S_DIN_to_AES) {
- HW_DESC_SET_DIN_TYPE(&desc[idx], DMA_DLLI, ctx->enckey_dma_addr,
- ((ctx->enc_keylen == 24) ?
- CC_AES_KEY_SIZE_MAX : ctx->enc_keylen), NS_BIT);
- HW_DESC_SET_KEY_SIZE_AES(&desc[idx], ctx->enc_keylen);
+ set_din_type(&desc[idx], DMA_DLLI, ctx->enckey_dma_addr,
+ ((ctx->enc_keylen == 24) ? CC_AES_KEY_SIZE_MAX :
+ ctx->enc_keylen), NS_BIT);
+ set_key_size_aes(&desc[idx], ctx->enc_keylen);
} else {
- HW_DESC_SET_DIN_TYPE(&desc[idx], DMA_DLLI, ctx->enckey_dma_addr,
- ctx->enc_keylen, NS_BIT);
- HW_DESC_SET_KEY_SIZE_DES(&desc[idx], ctx->enc_keylen);
+ set_din_type(&desc[idx], DMA_DLLI, ctx->enckey_dma_addr,
+ ctx->enc_keylen, NS_BIT);
+ set_key_size_des(&desc[idx], ctx->enc_keylen);
}
- HW_DESC_SET_CIPHER_MODE(&desc[idx], ctx->cipher_mode);
+ set_cipher_mode(&desc[idx], ctx->cipher_mode);
idx++;
*seq_size = idx;
@@ -1002,7 +952,7 @@ static inline void ssi_aead_setup_cipher_desc(
static inline void ssi_aead_process_cipher(
struct aead_request *req,
- HwDesc_s desc[],
+ struct cc_hw_desc desc[],
unsigned int *seq_size,
unsigned int data_flow_mode)
{
@@ -1017,9 +967,9 @@ static inline void ssi_aead_process_cipher(
ssi_aead_process_cipher_data_desc(req, data_flow_mode, desc, &idx);
if (direct == DRV_CRYPTO_DIRECTION_ENCRYPT) {
/* We must wait for DMA to write all cipher */
- HW_DESC_INIT(&desc[idx]);
- HW_DESC_SET_DIN_NO_DMA(&desc[idx], 0, 0xfffff0);
- HW_DESC_SET_DOUT_NO_DMA(&desc[idx], 0, 0, 1);
+ hw_desc_init(&desc[idx]);
+ set_din_no_dma(&desc[idx], 0, 0xfffff0);
+ set_dout_no_dma(&desc[idx], 0, 0, 1);
idx++;
}
@@ -1028,35 +978,36 @@ static inline void ssi_aead_process_cipher(
static inline void ssi_aead_hmac_setup_digest_desc(
struct aead_request *req,
- HwDesc_s desc[],
+ struct cc_hw_desc desc[],
unsigned int *seq_size)
{
struct crypto_aead *tfm = crypto_aead_reqtfm(req);
struct ssi_aead_ctx *ctx = crypto_aead_ctx(tfm);
unsigned int hash_mode = (ctx->auth_mode == DRV_HASH_SHA1) ?
DRV_HASH_HW_SHA1 : DRV_HASH_HW_SHA256;
- unsigned int digest_size = (ctx->auth_mode == DRV_HASH_SHA1) ?
+ unsigned int digest_size = (ctx->auth_mode == DRV_HASH_SHA1) ?
CC_SHA1_DIGEST_SIZE : CC_SHA256_DIGEST_SIZE;
unsigned int idx = *seq_size;
/* Loading hash ipad xor key state */
- HW_DESC_INIT(&desc[idx]);
- HW_DESC_SET_CIPHER_MODE(&desc[idx], hash_mode);
- HW_DESC_SET_DIN_TYPE(&desc[idx], DMA_DLLI,
- ctx->auth_state.hmac.ipad_opad_dma_addr,
- digest_size, NS_BIT);
- HW_DESC_SET_FLOW_MODE(&desc[idx], S_DIN_to_HASH);
- HW_DESC_SET_SETUP_MODE(&desc[idx], SETUP_LOAD_STATE0);
+ hw_desc_init(&desc[idx]);
+ set_cipher_mode(&desc[idx], hash_mode);
+ set_din_type(&desc[idx], DMA_DLLI,
+ ctx->auth_state.hmac.ipad_opad_dma_addr, digest_size,
+ NS_BIT);
+ set_flow_mode(&desc[idx], S_DIN_to_HASH);
+ set_setup_mode(&desc[idx], SETUP_LOAD_STATE0);
idx++;
/* Load init. digest len (64 bytes) */
- HW_DESC_INIT(&desc[idx]);
- HW_DESC_SET_CIPHER_MODE(&desc[idx], hash_mode);
- HW_DESC_SET_DIN_SRAM(&desc[idx],
- ssi_ahash_get_initial_digest_len_sram_addr(ctx->drvdata, hash_mode),
- HASH_LEN_SIZE);
- HW_DESC_SET_FLOW_MODE(&desc[idx], S_DIN_to_HASH);
- HW_DESC_SET_SETUP_MODE(&desc[idx], SETUP_LOAD_KEY0);
+ hw_desc_init(&desc[idx]);
+ set_cipher_mode(&desc[idx], hash_mode);
+ set_din_sram(&desc[idx],
+ ssi_ahash_get_initial_digest_len_sram_addr(ctx->drvdata,
+ hash_mode),
+ HASH_LEN_SIZE);
+ set_flow_mode(&desc[idx], S_DIN_to_HASH);
+ set_setup_mode(&desc[idx], SETUP_LOAD_KEY0);
idx++;
*seq_size = idx;
@@ -1064,7 +1015,7 @@ static inline void ssi_aead_hmac_setup_digest_desc(
static inline void ssi_aead_xcbc_setup_digest_desc(
struct aead_request *req,
- HwDesc_s desc[],
+ struct cc_hw_desc desc[],
unsigned int *seq_size)
{
struct crypto_aead *tfm = crypto_aead_reqtfm(req);
@@ -1072,55 +1023,53 @@ static inline void ssi_aead_xcbc_setup_digest_desc(
unsigned int idx = *seq_size;
/* Loading MAC state */
- HW_DESC_INIT(&desc[idx]);
- HW_DESC_SET_DIN_CONST(&desc[idx], 0, CC_AES_BLOCK_SIZE);
- HW_DESC_SET_SETUP_MODE(&desc[idx], SETUP_LOAD_STATE0);
- HW_DESC_SET_CIPHER_MODE(&desc[idx], DRV_CIPHER_XCBC_MAC);
- HW_DESC_SET_CIPHER_CONFIG0(&desc[idx], DESC_DIRECTION_ENCRYPT_ENCRYPT);
- HW_DESC_SET_KEY_SIZE_AES(&desc[idx], CC_AES_128_BIT_KEY_SIZE);
- HW_DESC_SET_FLOW_MODE(&desc[idx], S_DIN_to_HASH);
- HW_DESC_SET_AES_NOT_HASH_MODE(&desc[idx]);
+ hw_desc_init(&desc[idx]);
+ set_din_const(&desc[idx], 0, CC_AES_BLOCK_SIZE);
+ set_setup_mode(&desc[idx], SETUP_LOAD_STATE0);
+ set_cipher_mode(&desc[idx], DRV_CIPHER_XCBC_MAC);
+ set_cipher_config0(&desc[idx], DESC_DIRECTION_ENCRYPT_ENCRYPT);
+ set_key_size_aes(&desc[idx], CC_AES_128_BIT_KEY_SIZE);
+ set_flow_mode(&desc[idx], S_DIN_to_HASH);
+ set_aes_not_hash_mode(&desc[idx]);
idx++;
/* Setup XCBC MAC K1 */
- HW_DESC_INIT(&desc[idx]);
- HW_DESC_SET_DIN_TYPE(&desc[idx], DMA_DLLI,
- ctx->auth_state.xcbc.xcbc_keys_dma_addr,
- AES_KEYSIZE_128, NS_BIT);
- HW_DESC_SET_SETUP_MODE(&desc[idx], SETUP_LOAD_KEY0);
- HW_DESC_SET_CIPHER_MODE(&desc[idx], DRV_CIPHER_XCBC_MAC);
- HW_DESC_SET_CIPHER_CONFIG0(&desc[idx], DESC_DIRECTION_ENCRYPT_ENCRYPT);
- HW_DESC_SET_KEY_SIZE_AES(&desc[idx], CC_AES_128_BIT_KEY_SIZE);
- HW_DESC_SET_FLOW_MODE(&desc[idx], S_DIN_to_HASH);
- HW_DESC_SET_AES_NOT_HASH_MODE(&desc[idx]);
+ hw_desc_init(&desc[idx]);
+ set_din_type(&desc[idx], DMA_DLLI,
+ ctx->auth_state.xcbc.xcbc_keys_dma_addr,
+ AES_KEYSIZE_128, NS_BIT);
+ set_setup_mode(&desc[idx], SETUP_LOAD_KEY0);
+ set_cipher_mode(&desc[idx], DRV_CIPHER_XCBC_MAC);
+ set_cipher_config0(&desc[idx], DESC_DIRECTION_ENCRYPT_ENCRYPT);
+ set_key_size_aes(&desc[idx], CC_AES_128_BIT_KEY_SIZE);
+ set_flow_mode(&desc[idx], S_DIN_to_HASH);
+ set_aes_not_hash_mode(&desc[idx]);
idx++;
/* Setup XCBC MAC K2 */
- HW_DESC_INIT(&desc[idx]);
- HW_DESC_SET_DIN_TYPE(&desc[idx], DMA_DLLI,
- (ctx->auth_state.xcbc.xcbc_keys_dma_addr +
- AES_KEYSIZE_128),
- AES_KEYSIZE_128, NS_BIT);
- HW_DESC_SET_SETUP_MODE(&desc[idx], SETUP_LOAD_STATE1);
- HW_DESC_SET_CIPHER_MODE(&desc[idx], DRV_CIPHER_XCBC_MAC);
- HW_DESC_SET_CIPHER_CONFIG0(&desc[idx], DESC_DIRECTION_ENCRYPT_ENCRYPT);
- HW_DESC_SET_KEY_SIZE_AES(&desc[idx], CC_AES_128_BIT_KEY_SIZE);
- HW_DESC_SET_FLOW_MODE(&desc[idx], S_DIN_to_HASH);
- HW_DESC_SET_AES_NOT_HASH_MODE(&desc[idx]);
+ hw_desc_init(&desc[idx]);
+ set_din_type(&desc[idx], DMA_DLLI,
+ (ctx->auth_state.xcbc.xcbc_keys_dma_addr +
+ AES_KEYSIZE_128), AES_KEYSIZE_128, NS_BIT);
+ set_setup_mode(&desc[idx], SETUP_LOAD_STATE1);
+ set_cipher_mode(&desc[idx], DRV_CIPHER_XCBC_MAC);
+ set_cipher_config0(&desc[idx], DESC_DIRECTION_ENCRYPT_ENCRYPT);
+ set_key_size_aes(&desc[idx], CC_AES_128_BIT_KEY_SIZE);
+ set_flow_mode(&desc[idx], S_DIN_to_HASH);
+ set_aes_not_hash_mode(&desc[idx]);
idx++;
/* Setup XCBC MAC K3 */
- HW_DESC_INIT(&desc[idx]);
- HW_DESC_SET_DIN_TYPE(&desc[idx], DMA_DLLI,
- (ctx->auth_state.xcbc.xcbc_keys_dma_addr +
- 2 * AES_KEYSIZE_128),
- AES_KEYSIZE_128, NS_BIT);
- HW_DESC_SET_SETUP_MODE(&desc[idx], SETUP_LOAD_STATE2);
- HW_DESC_SET_CIPHER_MODE(&desc[idx], DRV_CIPHER_XCBC_MAC);
- HW_DESC_SET_CIPHER_CONFIG0(&desc[idx], DESC_DIRECTION_ENCRYPT_ENCRYPT);
- HW_DESC_SET_KEY_SIZE_AES(&desc[idx], CC_AES_128_BIT_KEY_SIZE);
- HW_DESC_SET_FLOW_MODE(&desc[idx], S_DIN_to_HASH);
- HW_DESC_SET_AES_NOT_HASH_MODE(&desc[idx]);
+ hw_desc_init(&desc[idx]);
+ set_din_type(&desc[idx], DMA_DLLI,
+ (ctx->auth_state.xcbc.xcbc_keys_dma_addr +
+ 2 * AES_KEYSIZE_128), AES_KEYSIZE_128, NS_BIT);
+ set_setup_mode(&desc[idx], SETUP_LOAD_STATE2);
+ set_cipher_mode(&desc[idx], DRV_CIPHER_XCBC_MAC);
+ set_cipher_config0(&desc[idx], DESC_DIRECTION_ENCRYPT_ENCRYPT);
+ set_key_size_aes(&desc[idx], CC_AES_128_BIT_KEY_SIZE);
+ set_flow_mode(&desc[idx], S_DIN_to_HASH);
+ set_aes_not_hash_mode(&desc[idx]);
idx++;
*seq_size = idx;
@@ -1128,7 +1077,7 @@ static inline void ssi_aead_xcbc_setup_digest_desc(
static inline void ssi_aead_process_digest_header_desc(
struct aead_request *req,
- HwDesc_s desc[],
+ struct cc_hw_desc desc[],
unsigned int *seq_size)
{
unsigned int idx = *seq_size;
@@ -1142,7 +1091,7 @@ static inline void ssi_aead_process_digest_header_desc(
static inline void ssi_aead_process_digest_scheme_desc(
struct aead_request *req,
- HwDesc_s desc[],
+ struct cc_hw_desc desc[],
unsigned int *seq_size)
{
struct crypto_aead *tfm = crypto_aead_reqtfm(req);
@@ -1150,55 +1099,56 @@ static inline void ssi_aead_process_digest_scheme_desc(
struct ssi_aead_handle *aead_handle = ctx->drvdata->aead_handle;
unsigned int hash_mode = (ctx->auth_mode == DRV_HASH_SHA1) ?
DRV_HASH_HW_SHA1 : DRV_HASH_HW_SHA256;
- unsigned int digest_size = (ctx->auth_mode == DRV_HASH_SHA1) ?
+ unsigned int digest_size = (ctx->auth_mode == DRV_HASH_SHA1) ?
CC_SHA1_DIGEST_SIZE : CC_SHA256_DIGEST_SIZE;
unsigned int idx = *seq_size;
- HW_DESC_INIT(&desc[idx]);
- HW_DESC_SET_CIPHER_MODE(&desc[idx], hash_mode);
- HW_DESC_SET_DOUT_SRAM(&desc[idx], aead_handle->sram_workspace_addr,
- HASH_LEN_SIZE);
- HW_DESC_SET_FLOW_MODE(&desc[idx], S_HASH_to_DOUT);
- HW_DESC_SET_SETUP_MODE(&desc[idx], SETUP_WRITE_STATE1);
- HW_DESC_SET_CIPHER_DO(&desc[idx], DO_PAD);
+ hw_desc_init(&desc[idx]);
+ set_cipher_mode(&desc[idx], hash_mode);
+ set_dout_sram(&desc[idx], aead_handle->sram_workspace_addr,
+ HASH_LEN_SIZE);
+ set_flow_mode(&desc[idx], S_HASH_to_DOUT);
+ set_setup_mode(&desc[idx], SETUP_WRITE_STATE1);
+ set_cipher_do(&desc[idx], DO_PAD);
idx++;
/* Get final ICV result */
- HW_DESC_INIT(&desc[idx]);
- HW_DESC_SET_DOUT_SRAM(&desc[idx], aead_handle->sram_workspace_addr,
- digest_size);
- HW_DESC_SET_FLOW_MODE(&desc[idx], S_HASH_to_DOUT);
- HW_DESC_SET_SETUP_MODE(&desc[idx], SETUP_WRITE_STATE0);
- HW_DESC_SET_CIPHER_CONFIG0(&desc[idx], HASH_DIGEST_RESULT_LITTLE_ENDIAN);
- HW_DESC_SET_CIPHER_MODE(&desc[idx], hash_mode);
+ hw_desc_init(&desc[idx]);
+ set_dout_sram(&desc[idx], aead_handle->sram_workspace_addr,
+ digest_size);
+ set_flow_mode(&desc[idx], S_HASH_to_DOUT);
+ set_setup_mode(&desc[idx], SETUP_WRITE_STATE0);
+ set_cipher_config0(&desc[idx], HASH_DIGEST_RESULT_LITTLE_ENDIAN);
+ set_cipher_mode(&desc[idx], hash_mode);
idx++;
/* Loading hash opad xor key state */
- HW_DESC_INIT(&desc[idx]);
- HW_DESC_SET_CIPHER_MODE(&desc[idx], hash_mode);
- HW_DESC_SET_DIN_TYPE(&desc[idx], DMA_DLLI,
- (ctx->auth_state.hmac.ipad_opad_dma_addr + digest_size),
- digest_size, NS_BIT);
- HW_DESC_SET_FLOW_MODE(&desc[idx], S_DIN_to_HASH);
- HW_DESC_SET_SETUP_MODE(&desc[idx], SETUP_LOAD_STATE0);
+ hw_desc_init(&desc[idx]);
+ set_cipher_mode(&desc[idx], hash_mode);
+ set_din_type(&desc[idx], DMA_DLLI,
+ (ctx->auth_state.hmac.ipad_opad_dma_addr + digest_size),
+ digest_size, NS_BIT);
+ set_flow_mode(&desc[idx], S_DIN_to_HASH);
+ set_setup_mode(&desc[idx], SETUP_LOAD_STATE0);
idx++;
/* Load init. digest len (64 bytes) */
- HW_DESC_INIT(&desc[idx]);
- HW_DESC_SET_CIPHER_MODE(&desc[idx], hash_mode);
- HW_DESC_SET_DIN_SRAM(&desc[idx],
- ssi_ahash_get_initial_digest_len_sram_addr(ctx->drvdata, hash_mode),
- HASH_LEN_SIZE);
- HW_DESC_SET_CIPHER_CONFIG1(&desc[idx], HASH_PADDING_ENABLED);
- HW_DESC_SET_FLOW_MODE(&desc[idx], S_DIN_to_HASH);
- HW_DESC_SET_SETUP_MODE(&desc[idx], SETUP_LOAD_KEY0);
+ hw_desc_init(&desc[idx]);
+ set_cipher_mode(&desc[idx], hash_mode);
+ set_din_sram(&desc[idx],
+ ssi_ahash_get_initial_digest_len_sram_addr(ctx->drvdata,
+ hash_mode),
+ HASH_LEN_SIZE);
+ set_cipher_config1(&desc[idx], HASH_PADDING_ENABLED);
+ set_flow_mode(&desc[idx], S_DIN_to_HASH);
+ set_setup_mode(&desc[idx], SETUP_LOAD_KEY0);
idx++;
/* Perform HASH update */
- HW_DESC_INIT(&desc[idx]);
- HW_DESC_SET_DIN_SRAM(&desc[idx], aead_handle->sram_workspace_addr,
- digest_size);
- HW_DESC_SET_FLOW_MODE(&desc[idx], DIN_HASH);
+ hw_desc_init(&desc[idx]);
+ set_din_sram(&desc[idx], aead_handle->sram_workspace_addr,
+ digest_size);
+ set_flow_mode(&desc[idx], DIN_HASH);
idx++;
*seq_size = idx;
@@ -1206,7 +1156,7 @@ static inline void ssi_aead_process_digest_scheme_desc(
static inline void ssi_aead_load_mlli_to_sram(
struct aead_request *req,
- HwDesc_s desc[],
+ struct cc_hw_desc desc[],
unsigned int *seq_size)
{
struct aead_req_ctx *req_ctx = aead_request_ctx(req);
@@ -1216,29 +1166,29 @@ static inline void ssi_aead_load_mlli_to_sram(
if (unlikely(
(req_ctx->assoc_buff_type == SSI_DMA_BUF_MLLI) ||
(req_ctx->data_buff_type == SSI_DMA_BUF_MLLI) ||
- (req_ctx->is_single_pass == false))) {
+ !req_ctx->is_single_pass)) {
SSI_LOG_DEBUG("Copy-to-sram: mlli_dma=%08x, mlli_size=%u\n",
(unsigned int)ctx->drvdata->mlli_sram_addr,
req_ctx->mlli_params.mlli_len);
/* Copy MLLI table host-to-sram */
- HW_DESC_INIT(&desc[*seq_size]);
- HW_DESC_SET_DIN_TYPE(&desc[*seq_size], DMA_DLLI,
- req_ctx->mlli_params.mlli_dma_addr,
- req_ctx->mlli_params.mlli_len, NS_BIT);
- HW_DESC_SET_DOUT_SRAM(&desc[*seq_size],
- ctx->drvdata->mlli_sram_addr,
- req_ctx->mlli_params.mlli_len);
- HW_DESC_SET_FLOW_MODE(&desc[*seq_size], BYPASS);
+ hw_desc_init(&desc[*seq_size]);
+ set_din_type(&desc[*seq_size], DMA_DLLI,
+ req_ctx->mlli_params.mlli_dma_addr,
+ req_ctx->mlli_params.mlli_len, NS_BIT);
+ set_dout_sram(&desc[*seq_size],
+ ctx->drvdata->mlli_sram_addr,
+ req_ctx->mlli_params.mlli_len);
+ set_flow_mode(&desc[*seq_size], BYPASS);
(*seq_size)++;
}
}
-static inline enum FlowMode ssi_aead_get_data_flow_mode(
+static inline enum cc_flow_mode ssi_aead_get_data_flow_mode(
enum drv_crypto_direction direct,
- enum FlowMode setup_flow_mode,
+ enum cc_flow_mode setup_flow_mode,
bool is_single_pass)
{
- enum FlowMode data_flow_mode;
+ enum cc_flow_mode data_flow_mode;
if (direct == DRV_CRYPTO_DIRECTION_ENCRYPT) {
if (setup_flow_mode == S_DIN_to_AES)
@@ -1261,7 +1211,7 @@ static inline enum FlowMode ssi_aead_get_data_flow_mode(
static inline void ssi_aead_hmac_authenc(
struct aead_request *req,
- HwDesc_s desc[],
+ struct cc_hw_desc desc[],
unsigned int *seq_size)
{
struct crypto_aead *tfm = crypto_aead_reqtfm(req);
@@ -1271,7 +1221,7 @@ static inline void ssi_aead_hmac_authenc(
unsigned int data_flow_mode = ssi_aead_get_data_flow_mode(
direct, ctx->flow_mode, req_ctx->is_single_pass);
- if (req_ctx->is_single_pass == true) {
+ if (req_ctx->is_single_pass) {
/**
* Single-pass flow
*/
@@ -1284,10 +1234,11 @@ static inline void ssi_aead_hmac_authenc(
return;
}
- /**
+ /**
* Double-pass flow
- * Fallback for unsupported single-pass modes,
- * i.e. using assoc. data of non-word-multiple */
+ * Fallback for unsupported single-pass modes,
+ * i.e. using assoc. data of non-word-multiple
+ */
if (direct == DRV_CRYPTO_DIRECTION_ENCRYPT) {
/* encrypt first.. */
ssi_aead_process_cipher(req, desc, seq_size, data_flow_mode);
@@ -1305,7 +1256,8 @@ static inline void ssi_aead_hmac_authenc(
/* decrypt after.. */
ssi_aead_process_cipher(req, desc, seq_size, data_flow_mode);
/* read the digest result with setting the completion bit
- must be after the cipher operation */
+ * must be after the cipher operation
+ */
ssi_aead_process_digest_result_desc(req, desc, seq_size);
}
}
@@ -1313,7 +1265,7 @@ static inline void ssi_aead_hmac_authenc(
static inline void
ssi_aead_xcbc_authenc(
struct aead_request *req,
- HwDesc_s desc[],
+ struct cc_hw_desc desc[],
unsigned int *seq_size)
{
struct crypto_aead *tfm = crypto_aead_reqtfm(req);
@@ -1323,7 +1275,7 @@ ssi_aead_xcbc_authenc(
unsigned int data_flow_mode = ssi_aead_get_data_flow_mode(
direct, ctx->flow_mode, req_ctx->is_single_pass);
- if (req_ctx->is_single_pass == true) {
+ if (req_ctx->is_single_pass) {
/**
* Single-pass flow
*/
@@ -1335,10 +1287,11 @@ ssi_aead_xcbc_authenc(
return;
}
- /**
+ /**
* Double-pass flow
- * Fallback for unsupported single-pass modes,
- * i.e. using assoc. data of non-word-multiple */
+ * Fallback for unsupported single-pass modes,
+ * i.e. using assoc. data of non-word-multiple
+ */
if (direct == DRV_CRYPTO_DIRECTION_ENCRYPT) {
/* encrypt first.. */
ssi_aead_process_cipher(req, desc, seq_size, data_flow_mode);
@@ -1353,7 +1306,8 @@ ssi_aead_xcbc_authenc(
/* decrypt after..*/
ssi_aead_process_cipher(req, desc, seq_size, data_flow_mode);
/* read the digest result with setting the completion bit
- must be after the cipher operation */
+ * must be after the cipher operation
+ */
ssi_aead_process_digest_result_desc(req, desc, seq_size);
}
}
@@ -1379,18 +1333,17 @@ static int validate_data_size(struct ssi_aead_ctx *ctx,
goto data_size_err;
if (ctx->cipher_mode == DRV_CIPHER_CCM)
break;
- if (ctx->cipher_mode == DRV_CIPHER_GCTR)
- {
- if (areq_ctx->plaintext_authenticate_only == true)
- areq_ctx->is_single_pass = false;
+ if (ctx->cipher_mode == DRV_CIPHER_GCTR) {
+ if (areq_ctx->plaintext_authenticate_only)
+ areq_ctx->is_single_pass = false;
break;
}
- if (!IS_ALIGNED(assoclen, sizeof(uint32_t)))
+ if (!IS_ALIGNED(assoclen, sizeof(u32)))
areq_ctx->is_single_pass = false;
if ((ctx->cipher_mode == DRV_CIPHER_CTR) &&
- !IS_ALIGNED(cipherlen, sizeof(uint32_t)))
+ !IS_ALIGNED(cipherlen, sizeof(u32)))
areq_ctx->is_single_pass = false;
break;
@@ -1412,13 +1365,14 @@ data_size_err:
}
#if SSI_CC_HAS_AES_CCM
-static unsigned int format_ccm_a0(uint8_t *pA0Buff, uint32_t headerSize)
+static unsigned int format_ccm_a0(u8 *pA0Buff, u32 headerSize)
{
unsigned int len = 0;
- if ( headerSize == 0 ) {
+
+ if (headerSize == 0)
return 0;
- }
- if ( headerSize < ((1UL << 16) - (1UL << 8) )) {
+
+ if (headerSize < ((1UL << 16) - (1UL << 8))) {
len = 2;
pA0Buff[0] = (headerSize >> 8) & 0xFF;
@@ -1457,7 +1411,7 @@ static int set_msg_len(u8 *block, unsigned int msglen, unsigned int csize)
static inline int ssi_aead_ccm(
struct aead_request *req,
- HwDesc_s desc[],
+ struct cc_hw_desc desc[],
unsigned int *seq_size)
{
struct crypto_aead *tfm = crypto_aead_reqtfm(req);
@@ -1467,7 +1421,6 @@ static inline int ssi_aead_ccm(
unsigned int cipher_flow_mode;
dma_addr_t mac_result;
-
if (req_ctx->gen_ctx.op_type == DRV_CRYPTO_DIRECTION_DECRYPT) {
cipher_flow_mode = AES_to_HASH_and_DOUT;
mac_result = req_ctx->mac_buf_dma_addr;
@@ -1477,118 +1430,111 @@ static inline int ssi_aead_ccm(
}
/* load key */
- HW_DESC_INIT(&desc[idx]);
- HW_DESC_SET_CIPHER_MODE(&desc[idx], DRV_CIPHER_CTR);
- HW_DESC_SET_DIN_TYPE(&desc[idx], DMA_DLLI, ctx->enckey_dma_addr,
- ((ctx->enc_keylen == 24) ?
- CC_AES_KEY_SIZE_MAX : ctx->enc_keylen),
- NS_BIT);
- HW_DESC_SET_KEY_SIZE_AES(&desc[idx], ctx->enc_keylen);
- HW_DESC_SET_SETUP_MODE(&desc[idx], SETUP_LOAD_KEY0);
- HW_DESC_SET_CIPHER_CONFIG0(&desc[idx], DESC_DIRECTION_ENCRYPT_ENCRYPT);
- HW_DESC_SET_FLOW_MODE(&desc[idx], S_DIN_to_AES);
+ hw_desc_init(&desc[idx]);
+ set_cipher_mode(&desc[idx], DRV_CIPHER_CTR);
+ set_din_type(&desc[idx], DMA_DLLI, ctx->enckey_dma_addr,
+ ((ctx->enc_keylen == 24) ? CC_AES_KEY_SIZE_MAX :
+ ctx->enc_keylen), NS_BIT);
+ set_key_size_aes(&desc[idx], ctx->enc_keylen);
+ set_setup_mode(&desc[idx], SETUP_LOAD_KEY0);
+ set_cipher_config0(&desc[idx], DESC_DIRECTION_ENCRYPT_ENCRYPT);
+ set_flow_mode(&desc[idx], S_DIN_to_AES);
idx++;
/* load ctr state */
- HW_DESC_INIT(&desc[idx]);
- HW_DESC_SET_CIPHER_MODE(&desc[idx], DRV_CIPHER_CTR);
- HW_DESC_SET_KEY_SIZE_AES(&desc[idx], ctx->enc_keylen);
- HW_DESC_SET_DIN_TYPE(&desc[idx], DMA_DLLI,
- req_ctx->gen_ctx.iv_dma_addr,
- AES_BLOCK_SIZE, NS_BIT);
- HW_DESC_SET_CIPHER_CONFIG0(&desc[idx], DESC_DIRECTION_ENCRYPT_ENCRYPT);
- HW_DESC_SET_SETUP_MODE(&desc[idx], SETUP_LOAD_STATE1);
- HW_DESC_SET_FLOW_MODE(&desc[idx], S_DIN_to_AES);
+ hw_desc_init(&desc[idx]);
+ set_cipher_mode(&desc[idx], DRV_CIPHER_CTR);
+ set_key_size_aes(&desc[idx], ctx->enc_keylen);
+ set_din_type(&desc[idx], DMA_DLLI,
+ req_ctx->gen_ctx.iv_dma_addr, AES_BLOCK_SIZE, NS_BIT);
+ set_cipher_config0(&desc[idx], DESC_DIRECTION_ENCRYPT_ENCRYPT);
+ set_setup_mode(&desc[idx], SETUP_LOAD_STATE1);
+ set_flow_mode(&desc[idx], S_DIN_to_AES);
idx++;
/* load MAC key */
- HW_DESC_INIT(&desc[idx]);
- HW_DESC_SET_CIPHER_MODE(&desc[idx], DRV_CIPHER_CBC_MAC);
- HW_DESC_SET_DIN_TYPE(&desc[idx], DMA_DLLI, ctx->enckey_dma_addr,
- ((ctx->enc_keylen == 24) ?
- CC_AES_KEY_SIZE_MAX : ctx->enc_keylen),
- NS_BIT);
- HW_DESC_SET_KEY_SIZE_AES(&desc[idx], ctx->enc_keylen);
- HW_DESC_SET_SETUP_MODE(&desc[idx], SETUP_LOAD_KEY0);
- HW_DESC_SET_CIPHER_CONFIG0(&desc[idx], DESC_DIRECTION_ENCRYPT_ENCRYPT);
- HW_DESC_SET_FLOW_MODE(&desc[idx], S_DIN_to_HASH);
- HW_DESC_SET_AES_NOT_HASH_MODE(&desc[idx]);
+ hw_desc_init(&desc[idx]);
+ set_cipher_mode(&desc[idx], DRV_CIPHER_CBC_MAC);
+ set_din_type(&desc[idx], DMA_DLLI, ctx->enckey_dma_addr,
+ ((ctx->enc_keylen == 24) ? CC_AES_KEY_SIZE_MAX :
+ ctx->enc_keylen), NS_BIT);
+ set_key_size_aes(&desc[idx], ctx->enc_keylen);
+ set_setup_mode(&desc[idx], SETUP_LOAD_KEY0);
+ set_cipher_config0(&desc[idx], DESC_DIRECTION_ENCRYPT_ENCRYPT);
+ set_flow_mode(&desc[idx], S_DIN_to_HASH);
+ set_aes_not_hash_mode(&desc[idx]);
idx++;
/* load MAC state */
- HW_DESC_INIT(&desc[idx]);
- HW_DESC_SET_CIPHER_MODE(&desc[idx], DRV_CIPHER_CBC_MAC);
- HW_DESC_SET_KEY_SIZE_AES(&desc[idx], ctx->enc_keylen);
- HW_DESC_SET_DIN_TYPE(&desc[idx], DMA_DLLI,
- req_ctx->mac_buf_dma_addr,
- AES_BLOCK_SIZE, NS_BIT);
- HW_DESC_SET_CIPHER_CONFIG0(&desc[idx], DESC_DIRECTION_ENCRYPT_ENCRYPT);
- HW_DESC_SET_SETUP_MODE(&desc[idx], SETUP_LOAD_STATE0);
- HW_DESC_SET_FLOW_MODE(&desc[idx], S_DIN_to_HASH);
- HW_DESC_SET_AES_NOT_HASH_MODE(&desc[idx]);
+ hw_desc_init(&desc[idx]);
+ set_cipher_mode(&desc[idx], DRV_CIPHER_CBC_MAC);
+ set_key_size_aes(&desc[idx], ctx->enc_keylen);
+ set_din_type(&desc[idx], DMA_DLLI, req_ctx->mac_buf_dma_addr,
+ AES_BLOCK_SIZE, NS_BIT);
+ set_cipher_config0(&desc[idx], DESC_DIRECTION_ENCRYPT_ENCRYPT);
+ set_setup_mode(&desc[idx], SETUP_LOAD_STATE0);
+ set_flow_mode(&desc[idx], S_DIN_to_HASH);
+ set_aes_not_hash_mode(&desc[idx]);
idx++;
-
/* process assoc data */
if (req->assoclen > 0) {
ssi_aead_create_assoc_desc(req, DIN_HASH, desc, &idx);
} else {
- HW_DESC_INIT(&desc[idx]);
- HW_DESC_SET_DIN_TYPE(&desc[idx], DMA_DLLI,
- sg_dma_address(&req_ctx->ccm_adata_sg),
- AES_BLOCK_SIZE + req_ctx->ccm_hdr_size,
- NS_BIT);
- HW_DESC_SET_FLOW_MODE(&desc[idx], DIN_HASH);
+ hw_desc_init(&desc[idx]);
+ set_din_type(&desc[idx], DMA_DLLI,
+ sg_dma_address(&req_ctx->ccm_adata_sg),
+ AES_BLOCK_SIZE + req_ctx->ccm_hdr_size, NS_BIT);
+ set_flow_mode(&desc[idx], DIN_HASH);
idx++;
}
/* process the cipher */
- if (req_ctx->cryptlen != 0) {
+ if (req_ctx->cryptlen != 0)
ssi_aead_process_cipher_data_desc(req, cipher_flow_mode, desc, &idx);
- }
/* Read temporal MAC */
- HW_DESC_INIT(&desc[idx]);
- HW_DESC_SET_CIPHER_MODE(&desc[idx], DRV_CIPHER_CBC_MAC);
- HW_DESC_SET_DOUT_DLLI(&desc[idx], req_ctx->mac_buf_dma_addr,
- ctx->authsize, NS_BIT, 0);
- HW_DESC_SET_SETUP_MODE(&desc[idx], SETUP_WRITE_STATE0);
- HW_DESC_SET_CIPHER_CONFIG0(&desc[idx], HASH_DIGEST_RESULT_LITTLE_ENDIAN);
- HW_DESC_SET_FLOW_MODE(&desc[idx], S_HASH_to_DOUT);
- HW_DESC_SET_AES_NOT_HASH_MODE(&desc[idx]);
+ hw_desc_init(&desc[idx]);
+ set_cipher_mode(&desc[idx], DRV_CIPHER_CBC_MAC);
+ set_dout_dlli(&desc[idx], req_ctx->mac_buf_dma_addr, ctx->authsize,
+ NS_BIT, 0);
+ set_setup_mode(&desc[idx], SETUP_WRITE_STATE0);
+ set_cipher_config0(&desc[idx], HASH_DIGEST_RESULT_LITTLE_ENDIAN);
+ set_flow_mode(&desc[idx], S_HASH_to_DOUT);
+ set_aes_not_hash_mode(&desc[idx]);
idx++;
/* load AES-CTR state (for last MAC calculation)*/
- HW_DESC_INIT(&desc[idx]);
- HW_DESC_SET_CIPHER_MODE(&desc[idx], DRV_CIPHER_CTR);
- HW_DESC_SET_CIPHER_CONFIG0(&desc[idx], DRV_CRYPTO_DIRECTION_ENCRYPT);
- HW_DESC_SET_DIN_TYPE(&desc[idx], DMA_DLLI,
- req_ctx->ccm_iv0_dma_addr ,
- AES_BLOCK_SIZE, NS_BIT);
- HW_DESC_SET_KEY_SIZE_AES(&desc[idx], ctx->enc_keylen);
- HW_DESC_SET_SETUP_MODE(&desc[idx], SETUP_LOAD_STATE1);
- HW_DESC_SET_FLOW_MODE(&desc[idx], S_DIN_to_AES);
+ hw_desc_init(&desc[idx]);
+ set_cipher_mode(&desc[idx], DRV_CIPHER_CTR);
+ set_cipher_config0(&desc[idx], DRV_CRYPTO_DIRECTION_ENCRYPT);
+ set_din_type(&desc[idx], DMA_DLLI, req_ctx->ccm_iv0_dma_addr,
+ AES_BLOCK_SIZE, NS_BIT);
+ set_key_size_aes(&desc[idx], ctx->enc_keylen);
+ set_setup_mode(&desc[idx], SETUP_LOAD_STATE1);
+ set_flow_mode(&desc[idx], S_DIN_to_AES);
idx++;
- HW_DESC_INIT(&desc[idx]);
- HW_DESC_SET_DIN_NO_DMA(&desc[idx], 0, 0xfffff0);
- HW_DESC_SET_DOUT_NO_DMA(&desc[idx], 0, 0, 1);
+ hw_desc_init(&desc[idx]);
+ set_din_no_dma(&desc[idx], 0, 0xfffff0);
+ set_dout_no_dma(&desc[idx], 0, 0, 1);
idx++;
/* encrypt the "T" value and store MAC in mac_state */
- HW_DESC_INIT(&desc[idx]);
- HW_DESC_SET_DIN_TYPE(&desc[idx], DMA_DLLI,
- req_ctx->mac_buf_dma_addr , ctx->authsize, NS_BIT);
- HW_DESC_SET_DOUT_DLLI(&desc[idx], mac_result , ctx->authsize, NS_BIT, 1);
- HW_DESC_SET_QUEUE_LAST_IND(&desc[idx]);
- HW_DESC_SET_FLOW_MODE(&desc[idx], DIN_AES_DOUT);
- idx++;
+ hw_desc_init(&desc[idx]);
+ set_din_type(&desc[idx], DMA_DLLI, req_ctx->mac_buf_dma_addr,
+ ctx->authsize, NS_BIT);
+ set_dout_dlli(&desc[idx], mac_result, ctx->authsize, NS_BIT, 1);
+ set_queue_last_ind(&desc[idx]);
+ set_flow_mode(&desc[idx], DIN_AES_DOUT);
+ idx++;
*seq_size = idx;
return 0;
}
-static int config_ccm_adata(struct aead_request *req) {
+static int config_ccm_adata(struct aead_request *req)
+{
struct crypto_aead *tfm = crypto_aead_reqtfm(req);
struct ssi_aead_ctx *ctx = crypto_aead_ctx(tfm);
struct aead_req_ctx *req_ctx = aead_request_ctx(req);
@@ -1597,21 +1543,22 @@ static int config_ccm_adata(struct aead_request *req) {
/* Note: The code assume that req->iv[0] already contains the value of L' of RFC3610 */
unsigned int l = lp + 1; /* This is L' of RFC 3610. */
unsigned int m = ctx->authsize; /* This is M' of RFC 3610. */
- uint8_t *b0 = req_ctx->ccm_config + CCM_B0_OFFSET;
- uint8_t *a0 = req_ctx->ccm_config + CCM_A0_OFFSET;
- uint8_t *ctr_count_0 = req_ctx->ccm_config + CCM_CTR_COUNT_0_OFFSET;
- unsigned int cryptlen = (req_ctx->gen_ctx.op_type ==
- DRV_CRYPTO_DIRECTION_ENCRYPT) ?
- req->cryptlen :
+ u8 *b0 = req_ctx->ccm_config + CCM_B0_OFFSET;
+ u8 *a0 = req_ctx->ccm_config + CCM_A0_OFFSET;
+ u8 *ctr_count_0 = req_ctx->ccm_config + CCM_CTR_COUNT_0_OFFSET;
+ unsigned int cryptlen = (req_ctx->gen_ctx.op_type ==
+ DRV_CRYPTO_DIRECTION_ENCRYPT) ?
+ req->cryptlen :
(req->cryptlen - ctx->authsize);
int rc;
+
memset(req_ctx->mac_buf, 0, AES_BLOCK_SIZE);
- memset(req_ctx->ccm_config, 0, AES_BLOCK_SIZE*3);
+ memset(req_ctx->ccm_config, 0, AES_BLOCK_SIZE * 3);
/* taken from crypto/ccm.c */
/* 2 <= L <= 8, so 1 <= L' <= 7. */
if (2 > l || l > 8) {
- SSI_LOG_ERR("illegal iv value %X\n",req->iv[0]);
+ SSI_LOG_ERR("illegal iv value %X\n", req->iv[0]);
return -EINVAL;
}
memcpy(b0, req->iv, AES_BLOCK_SIZE);
@@ -1622,20 +1569,19 @@ static int config_ccm_adata(struct aead_request *req) {
*b0 |= (8 * ((m - 2) / 2));
if (req->assoclen > 0)
*b0 |= 64; /* Enable bit 6 if Adata exists. */
-
+
rc = set_msg_len(b0 + 16 - l, cryptlen, l); /* Write L'. */
- if (rc != 0) {
+ if (rc != 0)
return rc;
- }
/* END of "taken from crypto/ccm.c" */
-
+
/* l(a) - size of associated data. */
- req_ctx->ccm_hdr_size = format_ccm_a0 (a0, req->assoclen);
+ req_ctx->ccm_hdr_size = format_ccm_a0(a0, req->assoclen);
memset(req->iv + 15 - req->iv[0], 0, req->iv[0] + 1);
- req->iv [15] = 1;
+ req->iv[15] = 1;
- memcpy(ctr_count_0, req->iv, AES_BLOCK_SIZE) ;
+ memcpy(ctr_count_0, req->iv, AES_BLOCK_SIZE);
ctr_count_0[15] = 0;
return 0;
@@ -1654,7 +1600,7 @@ static void ssi_rfc4309_ccm_process(struct aead_request *req)
/* In RFC 4309 there is an 11-bytes nonce+IV part, that we build here. */
memcpy(areq_ctx->ctr_iv + CCM_BLOCK_NONCE_OFFSET, ctx->ctr_nonce, CCM_BLOCK_NONCE_SIZE);
memcpy(areq_ctx->ctr_iv + CCM_BLOCK_IV_OFFSET, req->iv, CCM_BLOCK_IV_SIZE);
- req->iv = areq_ctx->ctr_iv;
+ req->iv = areq_ctx->ctr_iv;
req->assoclen -= CCM_BLOCK_IV_SIZE;
}
#endif /*SSI_CC_HAS_AES_CCM*/
@@ -1663,7 +1609,7 @@ static void ssi_rfc4309_ccm_process(struct aead_request *req)
static inline void ssi_aead_gcm_setup_ghash_desc(
struct aead_request *req,
- HwDesc_s desc[],
+ struct cc_hw_desc desc[],
unsigned int *seq_size)
{
struct crypto_aead *tfm = crypto_aead_reqtfm(req);
@@ -1672,69 +1618,68 @@ static inline void ssi_aead_gcm_setup_ghash_desc(
unsigned int idx = *seq_size;
/* load key to AES*/
- HW_DESC_INIT(&desc[idx]);
- HW_DESC_SET_CIPHER_MODE(&desc[idx], DRV_CIPHER_ECB);
- HW_DESC_SET_CIPHER_CONFIG0(&desc[idx], DRV_CRYPTO_DIRECTION_ENCRYPT);
- HW_DESC_SET_DIN_TYPE(&desc[idx], DMA_DLLI, ctx->enckey_dma_addr,
- ctx->enc_keylen, NS_BIT);
- HW_DESC_SET_KEY_SIZE_AES(&desc[idx], ctx->enc_keylen);
- HW_DESC_SET_SETUP_MODE(&desc[idx], SETUP_LOAD_KEY0);
- HW_DESC_SET_FLOW_MODE(&desc[idx], S_DIN_to_AES);
+ hw_desc_init(&desc[idx]);
+ set_cipher_mode(&desc[idx], DRV_CIPHER_ECB);
+ set_cipher_config0(&desc[idx], DRV_CRYPTO_DIRECTION_ENCRYPT);
+ set_din_type(&desc[idx], DMA_DLLI, ctx->enckey_dma_addr,
+ ctx->enc_keylen, NS_BIT);
+ set_key_size_aes(&desc[idx], ctx->enc_keylen);
+ set_setup_mode(&desc[idx], SETUP_LOAD_KEY0);
+ set_flow_mode(&desc[idx], S_DIN_to_AES);
idx++;
/* process one zero block to generate hkey */
- HW_DESC_INIT(&desc[idx]);
- HW_DESC_SET_DIN_CONST(&desc[idx], 0x0, AES_BLOCK_SIZE);
- HW_DESC_SET_DOUT_DLLI(&desc[idx],
- req_ctx->hkey_dma_addr,
- AES_BLOCK_SIZE,
- NS_BIT, 0);
- HW_DESC_SET_FLOW_MODE(&desc[idx], DIN_AES_DOUT);
+ hw_desc_init(&desc[idx]);
+ set_din_const(&desc[idx], 0x0, AES_BLOCK_SIZE);
+ set_dout_dlli(&desc[idx], req_ctx->hkey_dma_addr, AES_BLOCK_SIZE,
+ NS_BIT, 0);
+ set_flow_mode(&desc[idx], DIN_AES_DOUT);
idx++;
/* Memory Barrier */
- HW_DESC_INIT(&desc[idx]);
- HW_DESC_SET_DIN_NO_DMA(&desc[idx], 0, 0xfffff0);
- HW_DESC_SET_DOUT_NO_DMA(&desc[idx], 0, 0, 1);
+ hw_desc_init(&desc[idx]);
+ set_din_no_dma(&desc[idx], 0, 0xfffff0);
+ set_dout_no_dma(&desc[idx], 0, 0, 1);
idx++;
/* Load GHASH subkey */
- HW_DESC_INIT(&desc[idx]);
- HW_DESC_SET_DIN_TYPE(&desc[idx], DMA_DLLI,
- req_ctx->hkey_dma_addr,
- AES_BLOCK_SIZE, NS_BIT);
- HW_DESC_SET_DOUT_NO_DMA(&desc[idx], 0, 0, 1);
- HW_DESC_SET_FLOW_MODE(&desc[idx], S_DIN_to_HASH);
- HW_DESC_SET_AES_NOT_HASH_MODE(&desc[idx]);
- HW_DESC_SET_CIPHER_MODE(&desc[idx], DRV_HASH_HW_GHASH);
- HW_DESC_SET_CIPHER_CONFIG1(&desc[idx], HASH_PADDING_ENABLED);
- HW_DESC_SET_SETUP_MODE(&desc[idx], SETUP_LOAD_KEY0);
+ hw_desc_init(&desc[idx]);
+ set_din_type(&desc[idx], DMA_DLLI, req_ctx->hkey_dma_addr,
+ AES_BLOCK_SIZE, NS_BIT);
+ set_dout_no_dma(&desc[idx], 0, 0, 1);
+ set_flow_mode(&desc[idx], S_DIN_to_HASH);
+ set_aes_not_hash_mode(&desc[idx]);
+ set_cipher_mode(&desc[idx], DRV_HASH_HW_GHASH);
+ set_cipher_config1(&desc[idx], HASH_PADDING_ENABLED);
+ set_setup_mode(&desc[idx], SETUP_LOAD_KEY0);
idx++;
/* Configure Hash Engine to work with GHASH.
- Since it was not possible to extend HASH submodes to add GHASH,
- The following command is necessary in order to select GHASH (according to HW designers)*/
- HW_DESC_INIT(&desc[idx]);
- HW_DESC_SET_DIN_NO_DMA(&desc[idx], 0, 0xfffff0);
- HW_DESC_SET_DOUT_NO_DMA(&desc[idx], 0, 0, 1);
- HW_DESC_SET_FLOW_MODE(&desc[idx], S_DIN_to_HASH);
- HW_DESC_SET_AES_NOT_HASH_MODE(&desc[idx]);
- HW_DESC_SET_CIPHER_MODE(&desc[idx], DRV_HASH_HW_GHASH);
- HW_DESC_SET_CIPHER_DO(&desc[idx], 1); //1=AES_SK RKEK
- HW_DESC_SET_CIPHER_CONFIG0(&desc[idx], DRV_CRYPTO_DIRECTION_ENCRYPT);
- HW_DESC_SET_CIPHER_CONFIG1(&desc[idx], HASH_PADDING_ENABLED);
- HW_DESC_SET_SETUP_MODE(&desc[idx], SETUP_LOAD_KEY0);
+ * Since it was not possible to extend HASH submodes to add GHASH,
+ * The following command is necessary in order to
+ * select GHASH (according to HW designers)
+ */
+ hw_desc_init(&desc[idx]);
+ set_din_no_dma(&desc[idx], 0, 0xfffff0);
+ set_dout_no_dma(&desc[idx], 0, 0, 1);
+ set_flow_mode(&desc[idx], S_DIN_to_HASH);
+ set_aes_not_hash_mode(&desc[idx]);
+ set_cipher_mode(&desc[idx], DRV_HASH_HW_GHASH);
+ set_cipher_do(&desc[idx], 1); //1=AES_SK RKEK
+ set_cipher_config0(&desc[idx], DRV_CRYPTO_DIRECTION_ENCRYPT);
+ set_cipher_config1(&desc[idx], HASH_PADDING_ENABLED);
+ set_setup_mode(&desc[idx], SETUP_LOAD_KEY0);
idx++;
/* Load GHASH initial STATE (which is 0). (for any hash there is an initial state) */
- HW_DESC_INIT(&desc[idx]);
- HW_DESC_SET_DIN_CONST(&desc[idx], 0x0, AES_BLOCK_SIZE);
- HW_DESC_SET_DOUT_NO_DMA(&desc[idx], 0, 0, 1);
- HW_DESC_SET_FLOW_MODE(&desc[idx], S_DIN_to_HASH);
- HW_DESC_SET_AES_NOT_HASH_MODE(&desc[idx]);
- HW_DESC_SET_CIPHER_MODE(&desc[idx], DRV_HASH_HW_GHASH);
- HW_DESC_SET_CIPHER_CONFIG1(&desc[idx], HASH_PADDING_ENABLED);
- HW_DESC_SET_SETUP_MODE(&desc[idx], SETUP_LOAD_STATE0);
+ hw_desc_init(&desc[idx]);
+ set_din_const(&desc[idx], 0x0, AES_BLOCK_SIZE);
+ set_dout_no_dma(&desc[idx], 0, 0, 1);
+ set_flow_mode(&desc[idx], S_DIN_to_HASH);
+ set_aes_not_hash_mode(&desc[idx]);
+ set_cipher_mode(&desc[idx], DRV_HASH_HW_GHASH);
+ set_cipher_config1(&desc[idx], HASH_PADDING_ENABLED);
+ set_setup_mode(&desc[idx], SETUP_LOAD_STATE0);
idx++;
*seq_size = idx;
@@ -1742,7 +1687,7 @@ static inline void ssi_aead_gcm_setup_ghash_desc(
static inline void ssi_aead_gcm_setup_gctr_desc(
struct aead_request *req,
- HwDesc_s desc[],
+ struct cc_hw_desc desc[],
unsigned int *seq_size)
{
struct crypto_aead *tfm = crypto_aead_reqtfm(req);
@@ -1751,27 +1696,27 @@ static inline void ssi_aead_gcm_setup_gctr_desc(
unsigned int idx = *seq_size;
/* load key to AES*/
- HW_DESC_INIT(&desc[idx]);
- HW_DESC_SET_CIPHER_MODE(&desc[idx], DRV_CIPHER_GCTR);
- HW_DESC_SET_CIPHER_CONFIG0(&desc[idx], DRV_CRYPTO_DIRECTION_ENCRYPT);
- HW_DESC_SET_DIN_TYPE(&desc[idx], DMA_DLLI, ctx->enckey_dma_addr,
- ctx->enc_keylen, NS_BIT);
- HW_DESC_SET_KEY_SIZE_AES(&desc[idx], ctx->enc_keylen);
- HW_DESC_SET_SETUP_MODE(&desc[idx], SETUP_LOAD_KEY0);
- HW_DESC_SET_FLOW_MODE(&desc[idx], S_DIN_to_AES);
+ hw_desc_init(&desc[idx]);
+ set_cipher_mode(&desc[idx], DRV_CIPHER_GCTR);
+ set_cipher_config0(&desc[idx], DRV_CRYPTO_DIRECTION_ENCRYPT);
+ set_din_type(&desc[idx], DMA_DLLI, ctx->enckey_dma_addr,
+ ctx->enc_keylen, NS_BIT);
+ set_key_size_aes(&desc[idx], ctx->enc_keylen);
+ set_setup_mode(&desc[idx], SETUP_LOAD_KEY0);
+ set_flow_mode(&desc[idx], S_DIN_to_AES);
idx++;
- if ((req_ctx->cryptlen != 0) && (req_ctx->plaintext_authenticate_only==false)){
+ if ((req_ctx->cryptlen != 0) && (!req_ctx->plaintext_authenticate_only)) {
/* load AES/CTR initial CTR value inc by 2*/
- HW_DESC_INIT(&desc[idx]);
- HW_DESC_SET_CIPHER_MODE(&desc[idx], DRV_CIPHER_GCTR);
- HW_DESC_SET_KEY_SIZE_AES(&desc[idx], ctx->enc_keylen);
- HW_DESC_SET_DIN_TYPE(&desc[idx], DMA_DLLI,
- req_ctx->gcm_iv_inc2_dma_addr,
- AES_BLOCK_SIZE, NS_BIT);
- HW_DESC_SET_CIPHER_CONFIG0(&desc[idx], DRV_CRYPTO_DIRECTION_ENCRYPT);
- HW_DESC_SET_SETUP_MODE(&desc[idx], SETUP_LOAD_STATE1);
- HW_DESC_SET_FLOW_MODE(&desc[idx], S_DIN_to_AES);
+ hw_desc_init(&desc[idx]);
+ set_cipher_mode(&desc[idx], DRV_CIPHER_GCTR);
+ set_key_size_aes(&desc[idx], ctx->enc_keylen);
+ set_din_type(&desc[idx], DMA_DLLI,
+ req_ctx->gcm_iv_inc2_dma_addr, AES_BLOCK_SIZE,
+ NS_BIT);
+ set_cipher_config0(&desc[idx], DRV_CRYPTO_DIRECTION_ENCRYPT);
+ set_setup_mode(&desc[idx], SETUP_LOAD_STATE1);
+ set_flow_mode(&desc[idx], S_DIN_to_AES);
idx++;
}
@@ -1780,13 +1725,13 @@ static inline void ssi_aead_gcm_setup_gctr_desc(
static inline void ssi_aead_process_gcm_result_desc(
struct aead_request *req,
- HwDesc_s desc[],
+ struct cc_hw_desc desc[],
unsigned int *seq_size)
{
struct crypto_aead *tfm = crypto_aead_reqtfm(req);
struct ssi_aead_ctx *ctx = crypto_aead_ctx(tfm);
struct aead_req_ctx *req_ctx = aead_request_ctx(req);
- dma_addr_t mac_result;
+ dma_addr_t mac_result;
unsigned int idx = *seq_size;
if (req_ctx->gen_ctx.op_type == DRV_CRYPTO_DIRECTION_DECRYPT) {
@@ -1796,60 +1741,57 @@ static inline void ssi_aead_process_gcm_result_desc(
}
/* process(ghash) gcm_block_len */
- HW_DESC_INIT(&desc[idx]);
- HW_DESC_SET_DIN_TYPE(&desc[idx], DMA_DLLI,
- req_ctx->gcm_block_len_dma_addr,
- AES_BLOCK_SIZE, NS_BIT);
- HW_DESC_SET_FLOW_MODE(&desc[idx], DIN_HASH);
+ hw_desc_init(&desc[idx]);
+ set_din_type(&desc[idx], DMA_DLLI, req_ctx->gcm_block_len_dma_addr,
+ AES_BLOCK_SIZE, NS_BIT);
+ set_flow_mode(&desc[idx], DIN_HASH);
idx++;
/* Store GHASH state after GHASH(Associated Data + Cipher +LenBlock) */
- HW_DESC_INIT(&desc[idx]);
- HW_DESC_SET_CIPHER_MODE(&desc[idx], DRV_HASH_HW_GHASH);
- HW_DESC_SET_DIN_NO_DMA(&desc[idx], 0, 0xfffff0);
- HW_DESC_SET_DOUT_DLLI(&desc[idx], req_ctx->mac_buf_dma_addr,
- AES_BLOCK_SIZE, NS_BIT, 0);
- HW_DESC_SET_SETUP_MODE(&desc[idx], SETUP_WRITE_STATE0);
- HW_DESC_SET_FLOW_MODE(&desc[idx], S_HASH_to_DOUT);
- HW_DESC_SET_AES_NOT_HASH_MODE(&desc[idx]);
+ hw_desc_init(&desc[idx]);
+ set_cipher_mode(&desc[idx], DRV_HASH_HW_GHASH);
+ set_din_no_dma(&desc[idx], 0, 0xfffff0);
+ set_dout_dlli(&desc[idx], req_ctx->mac_buf_dma_addr, AES_BLOCK_SIZE,
+ NS_BIT, 0);
+ set_setup_mode(&desc[idx], SETUP_WRITE_STATE0);
+ set_flow_mode(&desc[idx], S_HASH_to_DOUT);
+ set_aes_not_hash_mode(&desc[idx]);
- idx++;
+ idx++;
/* load AES/CTR initial CTR value inc by 1*/
- HW_DESC_INIT(&desc[idx]);
- HW_DESC_SET_CIPHER_MODE(&desc[idx], DRV_CIPHER_GCTR);
- HW_DESC_SET_KEY_SIZE_AES(&desc[idx], ctx->enc_keylen);
- HW_DESC_SET_DIN_TYPE(&desc[idx], DMA_DLLI,
- req_ctx->gcm_iv_inc1_dma_addr,
- AES_BLOCK_SIZE, NS_BIT);
- HW_DESC_SET_CIPHER_CONFIG0(&desc[idx], DRV_CRYPTO_DIRECTION_ENCRYPT);
- HW_DESC_SET_SETUP_MODE(&desc[idx], SETUP_LOAD_STATE1);
- HW_DESC_SET_FLOW_MODE(&desc[idx], S_DIN_to_AES);
+ hw_desc_init(&desc[idx]);
+ set_cipher_mode(&desc[idx], DRV_CIPHER_GCTR);
+ set_key_size_aes(&desc[idx], ctx->enc_keylen);
+ set_din_type(&desc[idx], DMA_DLLI, req_ctx->gcm_iv_inc1_dma_addr,
+ AES_BLOCK_SIZE, NS_BIT);
+ set_cipher_config0(&desc[idx], DRV_CRYPTO_DIRECTION_ENCRYPT);
+ set_setup_mode(&desc[idx], SETUP_LOAD_STATE1);
+ set_flow_mode(&desc[idx], S_DIN_to_AES);
idx++;
/* Memory Barrier */
- HW_DESC_INIT(&desc[idx]);
- HW_DESC_SET_DIN_NO_DMA(&desc[idx], 0, 0xfffff0);
- HW_DESC_SET_DOUT_NO_DMA(&desc[idx], 0, 0, 1);
+ hw_desc_init(&desc[idx]);
+ set_din_no_dma(&desc[idx], 0, 0xfffff0);
+ set_dout_no_dma(&desc[idx], 0, 0, 1);
idx++;
/* process GCTR on stored GHASH and store MAC in mac_state*/
- HW_DESC_INIT(&desc[idx]);
- HW_DESC_SET_CIPHER_MODE(&desc[idx], DRV_CIPHER_GCTR);
- HW_DESC_SET_DIN_TYPE(&desc[idx], DMA_DLLI,
- req_ctx->mac_buf_dma_addr,
- AES_BLOCK_SIZE, NS_BIT);
- HW_DESC_SET_DOUT_DLLI(&desc[idx], mac_result, ctx->authsize, NS_BIT, 1);
- HW_DESC_SET_QUEUE_LAST_IND(&desc[idx]);
- HW_DESC_SET_FLOW_MODE(&desc[idx], DIN_AES_DOUT);
- idx++;
+ hw_desc_init(&desc[idx]);
+ set_cipher_mode(&desc[idx], DRV_CIPHER_GCTR);
+ set_din_type(&desc[idx], DMA_DLLI, req_ctx->mac_buf_dma_addr,
+ AES_BLOCK_SIZE, NS_BIT);
+ set_dout_dlli(&desc[idx], mac_result, ctx->authsize, NS_BIT, 1);
+ set_queue_last_ind(&desc[idx]);
+ set_flow_mode(&desc[idx], DIN_AES_DOUT);
+ idx++;
*seq_size = idx;
}
static inline int ssi_aead_gcm(
struct aead_request *req,
- HwDesc_s desc[],
+ struct cc_hw_desc desc[],
unsigned int *seq_size)
{
struct aead_req_ctx *req_ctx = aead_request_ctx(req);
@@ -1862,9 +1804,8 @@ static inline int ssi_aead_gcm(
cipher_flow_mode = AES_to_HASH_and_DOUT;
}
-
//in RFC4543 no data to encrypt. just copy data from src to dest.
- if (req_ctx->plaintext_authenticate_only==true){
+ if (req_ctx->plaintext_authenticate_only) {
ssi_aead_process_cipher_data_desc(req, BYPASS, desc, seq_size);
ssi_aead_gcm_setup_ghash_desc(req, desc, seq_size);
/* process(ghash) assoc data */
@@ -1883,7 +1824,7 @@ static inline int ssi_aead_gcm(
ssi_aead_gcm_setup_gctr_desc(req, desc, seq_size);
/* process(gctr+ghash) */
if (req_ctx->cryptlen != 0)
- ssi_aead_process_cipher_data_desc(req, cipher_flow_mode, desc, seq_size);
+ ssi_aead_process_cipher_data_desc(req, cipher_flow_mode, desc, seq_size);
ssi_aead_process_gcm_result_desc(req, desc, seq_size);
idx = *seq_size;
@@ -1892,7 +1833,7 @@ static inline int ssi_aead_gcm(
#ifdef CC_DEBUG
static inline void ssi_aead_dump_gcm(
- const char* title,
+ const char *title,
struct aead_request *req)
{
struct crypto_aead *tfm = crypto_aead_reqtfm(req);
@@ -1902,52 +1843,50 @@ static inline void ssi_aead_dump_gcm(
if (ctx->cipher_mode != DRV_CIPHER_GCTR)
return;
- if (title != NULL) {
+ if (title) {
SSI_LOG_DEBUG("----------------------------------------------------------------------------------");
SSI_LOG_DEBUG("%s\n", title);
}
- SSI_LOG_DEBUG("cipher_mode %d, authsize %d, enc_keylen %d, assoclen %d, cryptlen %d \n", \
- ctx->cipher_mode, ctx->authsize, ctx->enc_keylen, req->assoclen, req_ctx->cryptlen );
+ SSI_LOG_DEBUG("cipher_mode %d, authsize %d, enc_keylen %d, assoclen %d, cryptlen %d\n", \
+ ctx->cipher_mode, ctx->authsize, ctx->enc_keylen, req->assoclen, req_ctx->cryptlen);
- if ( ctx->enckey != NULL ) {
- dump_byte_array("mac key",ctx->enckey, 16);
- }
+ if (ctx->enckey)
+ dump_byte_array("mac key", ctx->enckey, 16);
- dump_byte_array("req->iv",req->iv, AES_BLOCK_SIZE);
+ dump_byte_array("req->iv", req->iv, AES_BLOCK_SIZE);
- dump_byte_array("gcm_iv_inc1",req_ctx->gcm_iv_inc1, AES_BLOCK_SIZE);
+ dump_byte_array("gcm_iv_inc1", req_ctx->gcm_iv_inc1, AES_BLOCK_SIZE);
- dump_byte_array("gcm_iv_inc2",req_ctx->gcm_iv_inc2, AES_BLOCK_SIZE);
+ dump_byte_array("gcm_iv_inc2", req_ctx->gcm_iv_inc2, AES_BLOCK_SIZE);
- dump_byte_array("hkey",req_ctx->hkey, AES_BLOCK_SIZE);
+ dump_byte_array("hkey", req_ctx->hkey, AES_BLOCK_SIZE);
- dump_byte_array("mac_buf",req_ctx->mac_buf, AES_BLOCK_SIZE);
+ dump_byte_array("mac_buf", req_ctx->mac_buf, AES_BLOCK_SIZE);
- dump_byte_array("gcm_len_block",req_ctx->gcm_len_block.lenA, AES_BLOCK_SIZE);
+ dump_byte_array("gcm_len_block", req_ctx->gcm_len_block.lenA, AES_BLOCK_SIZE);
- if (req->src!=NULL && req->cryptlen) {
- dump_byte_array("req->src",sg_virt(req->src), req->cryptlen+req->assoclen);
- }
+ if (req->src && req->cryptlen)
+ dump_byte_array("req->src", sg_virt(req->src), req->cryptlen + req->assoclen);
- if (req->dst!=NULL) {
- dump_byte_array("req->dst",sg_virt(req->dst), req->cryptlen+ctx->authsize+req->assoclen);
- }
+ if (req->dst)
+ dump_byte_array("req->dst", sg_virt(req->dst), req->cryptlen + ctx->authsize + req->assoclen);
}
#endif
-static int config_gcm_context(struct aead_request *req) {
+static int config_gcm_context(struct aead_request *req)
+{
struct crypto_aead *tfm = crypto_aead_reqtfm(req);
struct ssi_aead_ctx *ctx = crypto_aead_ctx(tfm);
struct aead_req_ctx *req_ctx = aead_request_ctx(req);
-
- unsigned int cryptlen = (req_ctx->gen_ctx.op_type ==
- DRV_CRYPTO_DIRECTION_ENCRYPT) ?
- req->cryptlen :
+
+ unsigned int cryptlen = (req_ctx->gen_ctx.op_type ==
+ DRV_CRYPTO_DIRECTION_ENCRYPT) ?
+ req->cryptlen :
(req->cryptlen - ctx->authsize);
__be32 counter = cpu_to_be32(2);
- SSI_LOG_DEBUG("config_gcm_context() cryptlen = %d, req->assoclen = %d ctx->authsize = %d \n", cryptlen, req->assoclen, ctx->authsize);
+ SSI_LOG_DEBUG("config_gcm_context() cryptlen = %d, req->assoclen = %d ctx->authsize = %d\n", cryptlen, req->assoclen, ctx->authsize);
memset(req_ctx->hkey, 0, AES_BLOCK_SIZE);
@@ -1960,21 +1899,20 @@ static int config_gcm_context(struct aead_request *req) {
memcpy(req->iv + 12, &counter, 4);
memcpy(req_ctx->gcm_iv_inc1, req->iv, 16);
-
- if (req_ctx->plaintext_authenticate_only == false)
- {
+ if (!req_ctx->plaintext_authenticate_only) {
__be64 temp64;
+
temp64 = cpu_to_be64(req->assoclen * 8);
- memcpy ( &req_ctx->gcm_len_block.lenA , &temp64, sizeof(temp64) );
+ memcpy(&req_ctx->gcm_len_block.lenA, &temp64, sizeof(temp64));
temp64 = cpu_to_be64(cryptlen * 8);
- memcpy ( &req_ctx->gcm_len_block.lenC , &temp64, 8 );
- }
- else { //rfc4543=> all data(AAD,IV,Plain) are considered additional data that is nothing is encrypted.
+ memcpy(&req_ctx->gcm_len_block.lenC, &temp64, 8);
+ } else { //rfc4543=> all data(AAD,IV,Plain) are considered additional data that is nothing is encrypted.
__be64 temp64;
- temp64 = cpu_to_be64((req->assoclen+GCM_BLOCK_RFC4_IV_SIZE+cryptlen) * 8);
- memcpy ( &req_ctx->gcm_len_block.lenA , &temp64, sizeof(temp64) );
+
+ temp64 = cpu_to_be64((req->assoclen + GCM_BLOCK_RFC4_IV_SIZE + cryptlen) * 8);
+ memcpy(&req_ctx->gcm_len_block.lenA, &temp64, sizeof(temp64));
temp64 = 0;
- memcpy ( &req_ctx->gcm_len_block.lenC , &temp64, 8 );
+ memcpy(&req_ctx->gcm_len_block.lenC, &temp64, 8);
}
return 0;
@@ -1988,34 +1926,30 @@ static void ssi_rfc4_gcm_process(struct aead_request *req)
memcpy(areq_ctx->ctr_iv + GCM_BLOCK_RFC4_NONCE_OFFSET, ctx->ctr_nonce, GCM_BLOCK_RFC4_NONCE_SIZE);
memcpy(areq_ctx->ctr_iv + GCM_BLOCK_RFC4_IV_OFFSET, req->iv, GCM_BLOCK_RFC4_IV_SIZE);
- req->iv = areq_ctx->ctr_iv;
+ req->iv = areq_ctx->ctr_iv;
req->assoclen -= GCM_BLOCK_RFC4_IV_SIZE;
}
-
#endif /*SSI_CC_HAS_AES_GCM*/
static int ssi_aead_process(struct aead_request *req, enum drv_crypto_direction direct)
{
int rc = 0;
int seq_len = 0;
- HwDesc_s desc[MAX_AEAD_PROCESS_SEQ];
+ struct cc_hw_desc desc[MAX_AEAD_PROCESS_SEQ];
struct crypto_aead *tfm = crypto_aead_reqtfm(req);
struct ssi_aead_ctx *ctx = crypto_aead_ctx(tfm);
struct aead_req_ctx *areq_ctx = aead_request_ctx(req);
struct device *dev = &ctx->drvdata->plat_dev->dev;
struct ssi_crypto_req ssi_req = {};
- DECL_CYCLE_COUNT_RESOURCES;
-
SSI_LOG_DEBUG("%s context=%p req=%p iv=%p src=%p src_ofs=%d dst=%p dst_ofs=%d cryptolen=%d\n",
- ((direct==DRV_CRYPTO_DIRECTION_ENCRYPT)?"Encrypt":"Decrypt"), ctx, req, req->iv,
+ ((direct == DRV_CRYPTO_DIRECTION_ENCRYPT) ? "Encrypt" : "Decrypt"), ctx, req, req->iv,
sg_virt(req->src), req->src->offset, sg_virt(req->dst), req->dst->offset, req->cryptlen);
CHECK_AND_RETURN_UPON_FIPS_ERROR();
/* STAT_PHASE_0: Init and sanity checks */
- START_CYCLE_COUNT();
-
+
/* Check data length according to mode */
if (unlikely(validate_data_size(ctx, direct, req) != 0)) {
SSI_LOG_ERR("Unsupported crypt/assoc len %d/%d.\n",
@@ -2028,25 +1962,19 @@ static int ssi_aead_process(struct aead_request *req, enum drv_crypto_direction
ssi_req.user_cb = (void *)ssi_aead_complete;
ssi_req.user_arg = (void *)req;
-#ifdef ENABLE_CYCLE_COUNT
- ssi_req.op_type = (direct == DRV_CRYPTO_DIRECTION_DECRYPT) ?
- STAT_OP_TYPE_DECODE : STAT_OP_TYPE_ENCODE;
-#endif
/* Setup request context */
areq_ctx->gen_ctx.op_type = direct;
areq_ctx->req_authsize = ctx->authsize;
areq_ctx->cipher_mode = ctx->cipher_mode;
- END_CYCLE_COUNT(ssi_req.op_type, STAT_PHASE_0);
-
/* STAT_PHASE_1: Map buffers */
- START_CYCLE_COUNT();
-
+
if (ctx->cipher_mode == DRV_CIPHER_CTR) {
/* Build CTR IV - Copy nonce from last 4 bytes in
- * CTR key to first 4 bytes in CTR IV */
+ * CTR key to first 4 bytes in CTR IV
+ */
memcpy(areq_ctx->ctr_iv, ctx->ctr_nonce, CTR_RFC3686_NONCE_SIZE);
- if (areq_ctx->backup_giv == NULL) /*User none-generated IV*/
+ if (!areq_ctx->backup_giv) /*User none-generated IV*/
memcpy(areq_ctx->ctr_iv + CTR_RFC3686_NONCE_SIZE,
req->iv, CTR_RFC3686_IV_SIZE);
/* Initialize counter portion of counter block */
@@ -2056,8 +1984,8 @@ static int ssi_aead_process(struct aead_request *req, enum drv_crypto_direction
/* Replace with counter iv */
req->iv = areq_ctx->ctr_iv;
areq_ctx->hw_iv_size = CTR_RFC3686_BLOCK_SIZE;
- } else if ((ctx->cipher_mode == DRV_CIPHER_CCM) ||
- (ctx->cipher_mode == DRV_CIPHER_GCTR) ) {
+ } else if ((ctx->cipher_mode == DRV_CIPHER_CCM) ||
+ (ctx->cipher_mode == DRV_CIPHER_GCTR)) {
areq_ctx->hw_iv_size = AES_BLOCK_SIZE;
if (areq_ctx->ctr_iv != req->iv) {
memcpy(areq_ctx->ctr_iv, req->iv, crypto_aead_ivsize(tfm));
@@ -2072,23 +2000,23 @@ static int ssi_aead_process(struct aead_request *req, enum drv_crypto_direction
rc = config_ccm_adata(req);
if (unlikely(rc != 0)) {
SSI_LOG_ERR("config_ccm_adata() returned with a failure %d!", rc);
- goto exit;
+ goto exit;
}
} else {
- areq_ctx->ccm_hdr_size = ccm_header_size_null;
+ areq_ctx->ccm_hdr_size = ccm_header_size_null;
}
#else
- areq_ctx->ccm_hdr_size = ccm_header_size_null;
+ areq_ctx->ccm_hdr_size = ccm_header_size_null;
#endif /*SSI_CC_HAS_AES_CCM*/
-#if SSI_CC_HAS_AES_GCM
+#if SSI_CC_HAS_AES_GCM
if (ctx->cipher_mode == DRV_CIPHER_GCTR) {
rc = config_gcm_context(req);
if (unlikely(rc != 0)) {
SSI_LOG_ERR("config_gcm_context() returned with a failure %d!", rc);
- goto exit;
+ goto exit;
}
- }
+ }
#endif /*SSI_CC_HAS_AES_GCM*/
rc = ssi_buffer_mgr_map_aead_request(ctx->drvdata, req);
@@ -2098,17 +2026,17 @@ static int ssi_aead_process(struct aead_request *req, enum drv_crypto_direction
}
/* do we need to generate IV? */
- if (areq_ctx->backup_giv != NULL) {
-
+ if (areq_ctx->backup_giv) {
/* set the DMA mapped IV address*/
if (ctx->cipher_mode == DRV_CIPHER_CTR) {
ssi_req.ivgen_dma_addr[0] = areq_ctx->gen_ctx.iv_dma_addr + CTR_RFC3686_NONCE_SIZE;
ssi_req.ivgen_dma_addr_len = 1;
} else if (ctx->cipher_mode == DRV_CIPHER_CCM) {
/* In ccm, the IV needs to exist both inside B0 and inside the counter.
- It is also copied to iv_dma_addr for other reasons (like returning
- it to the user).
- So, using 3 (identical) IV outputs. */
+ * It is also copied to iv_dma_addr for other reasons (like returning
+ * it to the user).
+ * So, using 3 (identical) IV outputs.
+ */
ssi_req.ivgen_dma_addr[0] = areq_ctx->gen_ctx.iv_dma_addr + CCM_BLOCK_IV_OFFSET;
ssi_req.ivgen_dma_addr[1] = sg_dma_address(&areq_ctx->ccm_adata_sg) + CCM_B0_OFFSET + CCM_BLOCK_IV_OFFSET;
ssi_req.ivgen_dma_addr[2] = sg_dma_address(&areq_ctx->ccm_adata_sg) + CCM_CTR_COUNT_0_OFFSET + CCM_BLOCK_IV_OFFSET;
@@ -2122,10 +2050,7 @@ static int ssi_aead_process(struct aead_request *req, enum drv_crypto_direction
ssi_req.ivgen_size = crypto_aead_ivsize(tfm);
}
- END_CYCLE_COUNT(ssi_req.op_type, STAT_PHASE_1);
-
/* STAT_PHASE_2: Create sequence */
- START_CYCLE_COUNT();
/* Load MLLI tables to SRAM if necessary */
ssi_aead_load_mlli_to_sram(req, desc, &seq_len);
@@ -2139,31 +2064,26 @@ static int ssi_aead_process(struct aead_request *req, enum drv_crypto_direction
case DRV_HASH_XCBC_MAC:
ssi_aead_xcbc_authenc(req, desc, &seq_len);
break;
-#if ( SSI_CC_HAS_AES_CCM || SSI_CC_HAS_AES_GCM )
+#if (SSI_CC_HAS_AES_CCM || SSI_CC_HAS_AES_GCM)
case DRV_HASH_NULL:
#if SSI_CC_HAS_AES_CCM
- if (ctx->cipher_mode == DRV_CIPHER_CCM) {
+ if (ctx->cipher_mode == DRV_CIPHER_CCM)
ssi_aead_ccm(req, desc, &seq_len);
- }
#endif /*SSI_CC_HAS_AES_CCM*/
#if SSI_CC_HAS_AES_GCM
- if (ctx->cipher_mode == DRV_CIPHER_GCTR) {
+ if (ctx->cipher_mode == DRV_CIPHER_GCTR)
ssi_aead_gcm(req, desc, &seq_len);
- }
#endif /*SSI_CC_HAS_AES_GCM*/
break;
#endif
- default:
+ default:
SSI_LOG_ERR("Unsupported authenc (%d)\n", ctx->auth_mode);
ssi_buffer_mgr_unmap_aead_request(dev, req);
rc = -ENOTSUPP;
goto exit;
}
- END_CYCLE_COUNT(ssi_req.op_type, STAT_PHASE_2);
-
/* STAT_PHASE_3: Lock HW and push sequence */
- START_CYCLE_COUNT();
rc = send_request(ctx->drvdata, &ssi_req, desc, seq_len, 1);
@@ -2172,8 +2092,6 @@ static int ssi_aead_process(struct aead_request *req, enum drv_crypto_direction
ssi_buffer_mgr_unmap_aead_request(dev, req);
}
-
- END_CYCLE_COUNT(ssi_req.op_type, STAT_PHASE_3);
exit:
return rc;
}
@@ -2206,7 +2124,7 @@ static int ssi_rfc4309_ccm_encrypt(struct aead_request *req)
int rc = -EINVAL;
if (!valid_assoclen(req)) {
- SSI_LOG_ERR("invalid Assoclen:%u\n", req->assoclen );
+ SSI_LOG_ERR("invalid Assoclen:%u\n", req->assoclen);
goto out;
}
@@ -2214,9 +2132,9 @@ static int ssi_rfc4309_ccm_encrypt(struct aead_request *req)
areq_ctx->backup_iv = req->iv;
areq_ctx->backup_giv = NULL;
areq_ctx->is_gcm4543 = true;
-
+
ssi_rfc4309_ccm_process(req);
-
+
rc = ssi_aead_process(req, DRV_CRYPTO_DIRECTION_ENCRYPT);
if (rc != -EINPROGRESS)
req->iv = areq_ctx->backup_iv;
@@ -2242,7 +2160,6 @@ static int ssi_aead_decrypt(struct aead_request *req)
req->iv = areq_ctx->backup_iv;
return rc;
-
}
#if SSI_CC_HAS_AES_CCM
@@ -2261,10 +2178,10 @@ static int ssi_rfc4309_ccm_decrypt(struct aead_request *req)
/* No generated IV required */
areq_ctx->backup_iv = req->iv;
areq_ctx->backup_giv = NULL;
-
+
areq_ctx->is_gcm4543 = true;
ssi_rfc4309_ccm_process(req);
-
+
rc = ssi_aead_process(req, DRV_CRYPTO_DIRECTION_DECRYPT);
if (rc != -EINPROGRESS)
req->iv = areq_ctx->backup_iv;
@@ -2280,8 +2197,8 @@ static int ssi_rfc4106_gcm_setkey(struct crypto_aead *tfm, const u8 *key, unsign
{
struct ssi_aead_ctx *ctx = crypto_aead_ctx(tfm);
int rc = 0;
-
- SSI_LOG_DEBUG("ssi_rfc4106_gcm_setkey() keylen %d, key %p \n", keylen, key );
+
+ SSI_LOG_DEBUG("ssi_rfc4106_gcm_setkey() keylen %d, key %p\n", keylen, key);
if (keylen < 4)
return -EINVAL;
@@ -2298,8 +2215,8 @@ static int ssi_rfc4543_gcm_setkey(struct crypto_aead *tfm, const u8 *key, unsign
{
struct ssi_aead_ctx *ctx = crypto_aead_ctx(tfm);
int rc = 0;
-
- SSI_LOG_DEBUG("ssi_rfc4543_gcm_setkey() keylen %d, key %p \n", keylen, key );
+
+ SSI_LOG_DEBUG("ssi_rfc4543_gcm_setkey() keylen %d, key %p\n", keylen, key);
if (keylen < 4)
return -EINVAL;
@@ -2334,24 +2251,24 @@ static int ssi_gcm_setauthsize(struct crypto_aead *authenc,
static int ssi_rfc4106_gcm_setauthsize(struct crypto_aead *authenc,
unsigned int authsize)
{
- SSI_LOG_DEBUG("ssi_rfc4106_gcm_setauthsize() authsize %d \n", authsize );
-
- switch (authsize) {
- case 8:
- case 12:
- case 16:
- break;
- default:
- return -EINVAL;
- }
-
- return ssi_aead_setauthsize(authenc, authsize);
+ SSI_LOG_DEBUG("ssi_rfc4106_gcm_setauthsize() authsize %d\n", authsize);
+
+ switch (authsize) {
+ case 8:
+ case 12:
+ case 16:
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ return ssi_aead_setauthsize(authenc, authsize);
}
static int ssi_rfc4543_gcm_setauthsize(struct crypto_aead *authenc,
- unsigned int authsize)
+ unsigned int authsize)
{
- SSI_LOG_DEBUG("ssi_rfc4543_gcm_setauthsize() authsize %d \n", authsize );
+ SSI_LOG_DEBUG("ssi_rfc4543_gcm_setauthsize() authsize %d\n", authsize);
if (authsize != 16)
return -EINVAL;
@@ -2364,7 +2281,7 @@ static int ssi_rfc4106_gcm_encrypt(struct aead_request *req)
/* Very similar to ssi_aead_encrypt() above. */
struct aead_req_ctx *areq_ctx = aead_request_ctx(req);
- int rc = -EINVAL;
+ int rc = -EINVAL;
if (!valid_assoclen(req)) {
SSI_LOG_ERR("invalid Assoclen:%u\n", req->assoclen);
@@ -2374,7 +2291,7 @@ static int ssi_rfc4106_gcm_encrypt(struct aead_request *req)
/* No generated IV required */
areq_ctx->backup_iv = req->iv;
areq_ctx->backup_giv = NULL;
-
+
areq_ctx->plaintext_authenticate_only = false;
ssi_rfc4_gcm_process(req);
@@ -2393,14 +2310,14 @@ static int ssi_rfc4543_gcm_encrypt(struct aead_request *req)
struct aead_req_ctx *areq_ctx = aead_request_ctx(req);
int rc;
-
+
//plaintext is not encryped with rfc4543
areq_ctx->plaintext_authenticate_only = true;
/* No generated IV required */
areq_ctx->backup_iv = req->iv;
areq_ctx->backup_giv = NULL;
-
+
ssi_rfc4_gcm_process(req);
areq_ctx->is_gcm4543 = true;
@@ -2416,7 +2333,7 @@ static int ssi_rfc4106_gcm_decrypt(struct aead_request *req)
/* Very similar to ssi_aead_decrypt() above. */
struct aead_req_ctx *areq_ctx = aead_request_ctx(req);
- int rc = -EINVAL;
+ int rc = -EINVAL;
if (!valid_assoclen(req)) {
SSI_LOG_ERR("invalid Assoclen:%u\n", req->assoclen);
@@ -2426,7 +2343,7 @@ static int ssi_rfc4106_gcm_decrypt(struct aead_request *req)
/* No generated IV required */
areq_ctx->backup_iv = req->iv;
areq_ctx->backup_giv = NULL;
-
+
areq_ctx->plaintext_authenticate_only = false;
ssi_rfc4_gcm_process(req);
@@ -2452,7 +2369,7 @@ static int ssi_rfc4543_gcm_decrypt(struct aead_request *req)
/* No generated IV required */
areq_ctx->backup_iv = req->iv;
areq_ctx->backup_giv = NULL;
-
+
ssi_rfc4_gcm_process(req);
areq_ctx->is_gcm4543 = true;
@@ -2715,7 +2632,7 @@ static struct ssi_alg_template aead_algs[] = {
.cipher_mode = DRV_CIPHER_GCTR,
.flow_mode = S_DIN_to_AES,
.auth_mode = DRV_HASH_NULL,
- },
+ },
#endif /*SSI_CC_HAS_AES_GCM*/
};
@@ -2758,7 +2675,7 @@ int ssi_aead_free(struct ssi_drvdata *drvdata)
struct ssi_aead_handle *aead_handle =
(struct ssi_aead_handle *)drvdata->aead_handle;
- if (aead_handle != NULL) {
+ if (aead_handle) {
/* Remove registered algs */
list_for_each_entry_safe(t_alg, n, &aead_handle->aead_list, entry) {
crypto_unregister_aead(&t_alg->aead_alg);
@@ -2780,7 +2697,7 @@ int ssi_aead_alloc(struct ssi_drvdata *drvdata)
int alg;
aead_handle = kmalloc(sizeof(struct ssi_aead_handle), GFP_KERNEL);
- if (aead_handle == NULL) {
+ if (!aead_handle) {
rc = -ENOMEM;
goto fail0;
}
@@ -2827,6 +2744,3 @@ fail1:
fail0:
return rc;
}
-
-
-
diff --git a/drivers/staging/ccree/ssi_aead.h b/drivers/staging/ccree/ssi_aead.h
index fe88c9e04f88..39cc633a3ffa 100644
--- a/drivers/staging/ccree/ssi_aead.h
+++ b/drivers/staging/ccree/ssi_aead.h
@@ -1,21 +1,21 @@
/*
* Copyright (C) 2012-2017 ARM Limited or its affiliates.
- *
+ *
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
- *
+ *
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
- *
+ *
* You should have received a copy of the GNU General Public License
* along with this program; if not, see <http://www.gnu.org/licenses/>.
*/
/* \file ssi_aead.h
- ARM CryptoCell AEAD Crypto API
+ * ARM CryptoCell AEAD Crypto API
*/
#ifndef __SSI_AEAD_H__
@@ -25,22 +25,18 @@
#include <crypto/algapi.h>
#include <crypto/ctr.h>
-
/* mac_cmp - HW writes 8 B but all bytes hold the same value */
#define ICV_CMP_SIZE 8
-#define CCM_CONFIG_BUF_SIZE (AES_BLOCK_SIZE*3)
+#define CCM_CONFIG_BUF_SIZE (AES_BLOCK_SIZE * 3)
#define MAX_MAC_SIZE MAX(SHA256_DIGEST_SIZE, AES_BLOCK_SIZE)
-
/* defines for AES GCM configuration buffer */
#define GCM_BLOCK_LEN_SIZE 8
-#define GCM_BLOCK_RFC4_IV_OFFSET 4
-#define GCM_BLOCK_RFC4_IV_SIZE 8 /* IV size for rfc's */
-#define GCM_BLOCK_RFC4_NONCE_OFFSET 0
-#define GCM_BLOCK_RFC4_NONCE_SIZE 4
-
-
+#define GCM_BLOCK_RFC4_IV_OFFSET 4
+#define GCM_BLOCK_RFC4_IV_SIZE 8 /* IV size for rfc's */
+#define GCM_BLOCK_RFC4_NONCE_OFFSET 0
+#define GCM_BLOCK_RFC4_NONCE_SIZE 4
/* Offsets into AES CCM configuration buffer */
#define CCM_B0_OFFSET 0
@@ -57,48 +53,49 @@ enum aead_ccm_header_size {
ccm_header_size_zero = 0,
ccm_header_size_2 = 2,
ccm_header_size_6 = 6,
- ccm_header_size_max = INT32_MAX
+ ccm_header_size_max = S32_MAX
};
struct aead_req_ctx {
/* Allocate cache line although only 4 bytes are needed to
- * assure next field falls @ cache line
- * Used for both: digest HW compare and CCM/GCM MAC value */
- uint8_t mac_buf[MAX_MAC_SIZE] ____cacheline_aligned;
- uint8_t ctr_iv[AES_BLOCK_SIZE] ____cacheline_aligned;
-
- //used in gcm
- uint8_t gcm_iv_inc1[AES_BLOCK_SIZE] ____cacheline_aligned;
- uint8_t gcm_iv_inc2[AES_BLOCK_SIZE] ____cacheline_aligned;
- uint8_t hkey[AES_BLOCK_SIZE] ____cacheline_aligned;
+ * assure next field falls @ cache line
+ * Used for both: digest HW compare and CCM/GCM MAC value
+ */
+ u8 mac_buf[MAX_MAC_SIZE] ____cacheline_aligned;
+ u8 ctr_iv[AES_BLOCK_SIZE] ____cacheline_aligned;
+
+ //used in gcm
+ u8 gcm_iv_inc1[AES_BLOCK_SIZE] ____cacheline_aligned;
+ u8 gcm_iv_inc2[AES_BLOCK_SIZE] ____cacheline_aligned;
+ u8 hkey[AES_BLOCK_SIZE] ____cacheline_aligned;
struct {
- uint8_t lenA[GCM_BLOCK_LEN_SIZE] ____cacheline_aligned;
- uint8_t lenC[GCM_BLOCK_LEN_SIZE] ;
+ u8 lenA[GCM_BLOCK_LEN_SIZE] ____cacheline_aligned;
+ u8 lenC[GCM_BLOCK_LEN_SIZE];
} gcm_len_block;
- uint8_t ccm_config[CCM_CONFIG_BUF_SIZE] ____cacheline_aligned;
+ u8 ccm_config[CCM_CONFIG_BUF_SIZE] ____cacheline_aligned;
unsigned int hw_iv_size ____cacheline_aligned; /*HW actual size input*/
- uint8_t backup_mac[MAX_MAC_SIZE]; /*used to prevent cache coherence problem*/
- uint8_t *backup_iv; /*store iv for generated IV flow*/
- uint8_t *backup_giv; /*store iv for rfc3686(ctr) flow*/
+ u8 backup_mac[MAX_MAC_SIZE]; /*used to prevent cache coherence problem*/
+ u8 *backup_iv; /*store iv for generated IV flow*/
+ u8 *backup_giv; /*store iv for rfc3686(ctr) flow*/
dma_addr_t mac_buf_dma_addr; /* internal ICV DMA buffer */
dma_addr_t ccm_iv0_dma_addr; /* buffer for internal ccm configurations */
dma_addr_t icv_dma_addr; /* Phys. address of ICV */
- //used in gcm
+ //used in gcm
dma_addr_t gcm_iv_inc1_dma_addr; /* buffer for internal gcm configurations */
dma_addr_t gcm_iv_inc2_dma_addr; /* buffer for internal gcm configurations */
dma_addr_t hkey_dma_addr; /* Phys. address of hkey */
dma_addr_t gcm_block_len_dma_addr; /* Phys. address of gcm block len */
bool is_gcm4543;
- uint8_t *icv_virt_addr; /* Virt. address of ICV */
+ u8 *icv_virt_addr; /* Virt. address of ICV */
struct async_gen_req_ctx gen_ctx;
struct ssi_mlli assoc;
struct ssi_mlli src;
struct ssi_mlli dst;
- struct scatterlist* srcSgl;
- struct scatterlist* dstSgl;
+ struct scatterlist *srcSgl;
+ struct scatterlist *dstSgl;
unsigned int srcOffset;
unsigned int dstOffset;
enum ssi_req_dma_buf_type assoc_buff_type;
diff --git a/drivers/staging/ccree/ssi_buffer_mgr.c b/drivers/staging/ccree/ssi_buffer_mgr.c
index 038e2ff5e545..b35871eeabd1 100644
--- a/drivers/staging/ccree/ssi_buffer_mgr.c
+++ b/drivers/staging/ccree/ssi_buffer_mgr.c
@@ -1,15 +1,15 @@
/*
* Copyright (C) 2012-2017 ARM Limited or its affiliates.
- *
+ *
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
- *
+ *
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
- *
+ *
* You should have received a copy of the GNU General Public License
* along with this program; if not, see <http://www.gnu.org/licenses/>.
*/
@@ -33,42 +33,15 @@
#include "ssi_hash.h"
#include "ssi_aead.h"
-#define LLI_MAX_NUM_OF_DATA_ENTRIES 128
-#define LLI_MAX_NUM_OF_ASSOC_DATA_ENTRIES 4
-#define MLLI_TABLE_MIN_ALIGNMENT 4 /*Force the MLLI table to be align to uint32 */
-#define MAX_NUM_OF_BUFFERS_IN_MLLI 4
-#define MAX_NUM_OF_TOTAL_MLLI_ENTRIES (2*LLI_MAX_NUM_OF_DATA_ENTRIES + \
- LLI_MAX_NUM_OF_ASSOC_DATA_ENTRIES )
-
#ifdef CC_DEBUG
-#define DUMP_SGL(sg) \
- while (sg) { \
- SSI_LOG_DEBUG("page=%lu offset=%u length=%u (dma_len=%u) " \
- "dma_addr=%08x\n", (sg)->page_link, (sg)->offset, \
- (sg)->length, sg_dma_len(sg), (sg)->dma_address); \
- (sg) = sg_next(sg); \
- }
-#define DUMP_MLLI_TABLE(mlli_p, nents) \
- do { \
- SSI_LOG_DEBUG("mlli=%pK nents=%u\n", (mlli_p), (nents)); \
- while((nents)--) { \
- SSI_LOG_DEBUG("addr=0x%08X size=0x%08X\n", \
- (mlli_p)[LLI_WORD0_OFFSET], \
- (mlli_p)[LLI_WORD1_OFFSET]); \
- (mlli_p) += LLI_ENTRY_WORD_SIZE; \
- } \
- } while (0)
#define GET_DMA_BUFFER_TYPE(buff_type) ( \
((buff_type) == SSI_DMA_BUF_NULL) ? "BUF_NULL" : \
((buff_type) == SSI_DMA_BUF_DLLI) ? "BUF_DLLI" : \
((buff_type) == SSI_DMA_BUF_MLLI) ? "BUF_MLLI" : "BUF_INVALID")
#else
-#define DX_BUFFER_MGR_DUMP_SGL(sg)
-#define DX_BUFFER_MGR_DUMP_MLLI_TABLE(mlli_p, nents)
#define GET_DMA_BUFFER_TYPE(buff_type)
#endif
-
enum dma_buffer_type {
DMA_NULL_TYPE = -1,
DMA_SGL_TYPE = 1,
@@ -92,103 +65,55 @@ struct buffer_array {
int total_data_len[MAX_NUM_OF_BUFFERS_IN_MLLI];
enum dma_buffer_type type[MAX_NUM_OF_BUFFERS_IN_MLLI];
bool is_last[MAX_NUM_OF_BUFFERS_IN_MLLI];
- uint32_t * mlli_nents[MAX_NUM_OF_BUFFERS_IN_MLLI];
+ u32 *mlli_nents[MAX_NUM_OF_BUFFERS_IN_MLLI];
};
-#ifdef CC_DMA_48BIT_SIM
-dma_addr_t ssi_buff_mgr_update_dma_addr(dma_addr_t orig_addr, uint32_t data_len)
-{
- dma_addr_t tmp_dma_addr;
-#ifdef CC_DMA_48BIT_SIM_FULL
- /* With this code all addresses will be switched to 48 bits. */
- /* The if condition protects from double expention */
- if((((orig_addr >> 16) & 0xFFFF) != 0xFFFF) &&
- (data_len <= CC_MAX_MLLI_ENTRY_SIZE)) {
-#else
- if((!(((orig_addr >> 16) & 0xFF) % 2)) &&
- (data_len <= CC_MAX_MLLI_ENTRY_SIZE)) {
-#endif
- tmp_dma_addr = ((orig_addr<<16) | 0xFFFF0000 |
- (orig_addr & UINT16_MAX));
- SSI_LOG_DEBUG("MAP DMA: orig address=0x%llX "
- "dma_address=0x%llX\n",
- orig_addr, tmp_dma_addr);
- return tmp_dma_addr;
- }
- return orig_addr;
-}
-
-dma_addr_t ssi_buff_mgr_restore_dma_addr(dma_addr_t orig_addr)
-{
- dma_addr_t tmp_dma_addr;
-#ifdef CC_DMA_48BIT_SIM_FULL
- /* With this code all addresses will be restored from 48 bits. */
- /* The if condition protects from double restoring */
- if((orig_addr >> 32) & 0xFFFF ) {
-#else
- if(((orig_addr >> 32) & 0xFFFF) &&
- !(((orig_addr >> 32) & 0xFF) % 2) ) {
-#endif
- /*return high 16 bits*/
- tmp_dma_addr = ((orig_addr >> 16));
- /*clean the 0xFFFF in the lower bits (set in the add expansion)*/
- tmp_dma_addr &= 0xFFFF0000;
- /* Set the original 16 bits */
- tmp_dma_addr |= (orig_addr & UINT16_MAX);
- SSI_LOG_DEBUG("Release DMA: orig address=0x%llX "
- "dma_address=0x%llX\n",
- orig_addr, tmp_dma_addr);
- return tmp_dma_addr;
- }
- return orig_addr;
-}
-#endif
/**
* ssi_buffer_mgr_get_sgl_nents() - Get scatterlist number of entries.
- *
+ *
* @sg_list: SG list
* @nbytes: [IN] Total SGL data bytes.
- * @lbytes: [OUT] Returns the amount of bytes at the last entry
+ * @lbytes: [OUT] Returns the amount of bytes at the last entry
*/
static unsigned int ssi_buffer_mgr_get_sgl_nents(
- struct scatterlist *sg_list, unsigned int nbytes, uint32_t *lbytes, bool *is_chained)
+ struct scatterlist *sg_list, unsigned int nbytes, u32 *lbytes, bool *is_chained)
{
unsigned int nents = 0;
+
while (nbytes != 0) {
if (sg_is_chain(sg_list)) {
- SSI_LOG_ERR("Unexpected chanined entry "
- "in sg (entry =0x%X) \n", nents);
+ SSI_LOG_ERR("Unexpected chained entry "
+ "in sg (entry =0x%X)\n", nents);
BUG();
}
if (sg_list->length != 0) {
nents++;
/* get the number of bytes in the last entry */
*lbytes = nbytes;
- nbytes -= ( sg_list->length > nbytes ) ? nbytes : sg_list->length;
+ nbytes -= (sg_list->length > nbytes) ? nbytes : sg_list->length;
sg_list = sg_next(sg_list);
} else {
sg_list = (struct scatterlist *)sg_page(sg_list);
- if (is_chained != NULL) {
+ if (is_chained)
*is_chained = true;
- }
}
}
- SSI_LOG_DEBUG("nents %d last bytes %d\n",nents, *lbytes);
+ SSI_LOG_DEBUG("nents %d last bytes %d\n", nents, *lbytes);
return nents;
}
/**
* ssi_buffer_mgr_zero_sgl() - Zero scatter scatter list data.
- *
+ *
* @sgl:
*/
-void ssi_buffer_mgr_zero_sgl(struct scatterlist *sgl, uint32_t data_len)
+void ssi_buffer_mgr_zero_sgl(struct scatterlist *sgl, u32 data_len)
{
struct scatterlist *current_sg = sgl;
int sg_index = 0;
while (sg_index <= data_len) {
- if (current_sg == NULL) {
+ if (!current_sg) {
/* reached the end of the sgl --> just return back */
return;
}
@@ -201,7 +126,7 @@ void ssi_buffer_mgr_zero_sgl(struct scatterlist *sgl, uint32_t data_len)
/**
* ssi_buffer_mgr_copy_scatterlist_portion() - Copy scatter list data,
* from to_skip to end, to dest and vice versa
- *
+ *
* @dest:
* @sg:
* @to_skip:
@@ -210,47 +135,44 @@ void ssi_buffer_mgr_zero_sgl(struct scatterlist *sgl, uint32_t data_len)
*/
void ssi_buffer_mgr_copy_scatterlist_portion(
u8 *dest, struct scatterlist *sg,
- uint32_t to_skip, uint32_t end,
+ u32 to_skip, u32 end,
enum ssi_sg_cpy_direct direct)
{
- uint32_t nents, lbytes;
+ u32 nents, lbytes;
nents = ssi_buffer_mgr_get_sgl_nents(sg, end, &lbytes, NULL);
- sg_copy_buffer(sg, nents, (void *)dest, (end - to_skip), 0, (direct == SSI_SG_TO_BUF));
+ sg_copy_buffer(sg, nents, (void *)dest, (end - to_skip + 1), to_skip,
+ (direct == SSI_SG_TO_BUF));
}
static inline int ssi_buffer_mgr_render_buff_to_mlli(
- dma_addr_t buff_dma, uint32_t buff_size, uint32_t *curr_nents,
- uint32_t **mlli_entry_pp)
+ dma_addr_t buff_dma, u32 buff_size, u32 *curr_nents,
+ u32 **mlli_entry_pp)
{
- uint32_t *mlli_entry_p = *mlli_entry_pp;
- uint32_t new_nents;;
+ u32 *mlli_entry_p = *mlli_entry_pp;
+ u32 new_nents;;
/* Verify there is no memory overflow*/
- new_nents = (*curr_nents + buff_size/CC_MAX_MLLI_ENTRY_SIZE + 1);
- if (new_nents > MAX_NUM_OF_TOTAL_MLLI_ENTRIES ) {
+ new_nents = (*curr_nents + buff_size / CC_MAX_MLLI_ENTRY_SIZE + 1);
+ if (new_nents > MAX_NUM_OF_TOTAL_MLLI_ENTRIES)
return -ENOMEM;
- }
/*handle buffer longer than 64 kbytes */
- while (buff_size > CC_MAX_MLLI_ENTRY_SIZE ) {
- SSI_UPDATE_DMA_ADDR_TO_48BIT(buff_dma, CC_MAX_MLLI_ENTRY_SIZE);
- LLI_SET_ADDR(mlli_entry_p,buff_dma);
- LLI_SET_SIZE(mlli_entry_p, CC_MAX_MLLI_ENTRY_SIZE);
- SSI_LOG_DEBUG("entry[%d]: single_buff=0x%08X size=%08X\n",*curr_nents,
+ while (buff_size > CC_MAX_MLLI_ENTRY_SIZE) {
+ cc_lli_set_addr(mlli_entry_p, buff_dma);
+ cc_lli_set_size(mlli_entry_p, CC_MAX_MLLI_ENTRY_SIZE);
+ SSI_LOG_DEBUG("entry[%d]: single_buff=0x%08X size=%08X\n", *curr_nents,
mlli_entry_p[LLI_WORD0_OFFSET],
mlli_entry_p[LLI_WORD1_OFFSET]);
- SSI_RESTORE_DMA_ADDR_TO_48BIT(buff_dma);
buff_dma += CC_MAX_MLLI_ENTRY_SIZE;
buff_size -= CC_MAX_MLLI_ENTRY_SIZE;
mlli_entry_p = mlli_entry_p + 2;
(*curr_nents)++;
}
/*Last entry */
- SSI_UPDATE_DMA_ADDR_TO_48BIT(buff_dma, buff_size);
- LLI_SET_ADDR(mlli_entry_p,buff_dma);
- LLI_SET_SIZE(mlli_entry_p, buff_size);
- SSI_LOG_DEBUG("entry[%d]: single_buff=0x%08X size=%08X\n",*curr_nents,
+ cc_lli_set_addr(mlli_entry_p, buff_dma);
+ cc_lli_set_size(mlli_entry_p, buff_size);
+ SSI_LOG_DEBUG("entry[%d]: single_buff=0x%08X size=%08X\n", *curr_nents,
mlli_entry_p[LLI_WORD0_OFFSET],
mlli_entry_p[LLI_WORD1_OFFSET]);
mlli_entry_p = mlli_entry_p + 2;
@@ -259,28 +181,27 @@ static inline int ssi_buffer_mgr_render_buff_to_mlli(
return 0;
}
-
static inline int ssi_buffer_mgr_render_scatterlist_to_mlli(
- struct scatterlist *sgl, uint32_t sgl_data_len, uint32_t sglOffset, uint32_t *curr_nents,
- uint32_t **mlli_entry_pp)
+ struct scatterlist *sgl, u32 sgl_data_len, u32 sglOffset, u32 *curr_nents,
+ u32 **mlli_entry_pp)
{
struct scatterlist *curr_sgl = sgl;
- uint32_t *mlli_entry_p = *mlli_entry_pp;
- int32_t rc = 0;
+ u32 *mlli_entry_p = *mlli_entry_pp;
+ s32 rc = 0;
- for ( ; (curr_sgl != NULL) && (sgl_data_len != 0);
+ for ( ; (curr_sgl) && (sgl_data_len != 0);
curr_sgl = sg_next(curr_sgl)) {
- uint32_t entry_data_len =
+ u32 entry_data_len =
(sgl_data_len > sg_dma_len(curr_sgl) - sglOffset) ?
- sg_dma_len(curr_sgl) - sglOffset : sgl_data_len ;
+ sg_dma_len(curr_sgl) - sglOffset : sgl_data_len;
sgl_data_len -= entry_data_len;
rc = ssi_buffer_mgr_render_buff_to_mlli(
sg_dma_address(curr_sgl) + sglOffset, entry_data_len, curr_nents,
&mlli_entry_p);
- if(rc != 0) {
+ if (rc != 0)
return rc;
- }
- sglOffset=0;
+
+ sglOffset = 0;
}
*mlli_entry_pp = mlli_entry_p;
return 0;
@@ -291,8 +212,8 @@ static int ssi_buffer_mgr_generate_mlli(
struct buffer_array *sg_data,
struct mlli_params *mlli_params)
{
- uint32_t *mlli_p;
- uint32_t total_nents = 0,prev_total_nents = 0;
+ u32 *mlli_p;
+ u32 total_nents = 0, prev_total_nents = 0;
int rc = 0, i;
SSI_LOG_DEBUG("NUM of SG's = %d\n", sg_data->num_of_buffers);
@@ -301,21 +222,18 @@ static int ssi_buffer_mgr_generate_mlli(
mlli_params->mlli_virt_addr = dma_pool_alloc(
mlli_params->curr_pool, GFP_KERNEL,
&(mlli_params->mlli_dma_addr));
- if (unlikely(mlli_params->mlli_virt_addr == NULL)) {
+ if (unlikely(!mlli_params->mlli_virt_addr)) {
SSI_LOG_ERR("dma_pool_alloc() failed\n");
- rc =-ENOMEM;
+ rc = -ENOMEM;
goto build_mlli_exit;
}
- SSI_UPDATE_DMA_ADDR_TO_48BIT(mlli_params->mlli_dma_addr,
- (MAX_NUM_OF_TOTAL_MLLI_ENTRIES*
- LLI_ENTRY_BYTE_SIZE));
/* Point to start of MLLI */
- mlli_p = (uint32_t *)mlli_params->mlli_virt_addr;
+ mlli_p = (u32 *)mlli_params->mlli_virt_addr;
/* go over all SG's and link it to one MLLI table */
for (i = 0; i < sg_data->num_of_buffers; i++) {
if (sg_data->type[i] == DMA_SGL_TYPE)
rc = ssi_buffer_mgr_render_scatterlist_to_mlli(
- sg_data->entry[i].sgl,
+ sg_data->entry[i].sgl,
sg_data->total_data_len[i], sg_data->offset[i], &total_nents,
&mlli_p);
else /*DMA_BUFF_TYPE*/
@@ -323,15 +241,15 @@ static int ssi_buffer_mgr_generate_mlli(
sg_data->entry[i].buffer_dma,
sg_data->total_data_len[i], &total_nents,
&mlli_p);
- if(rc != 0) {
+ if (rc != 0)
return rc;
- }
/* set last bit in the current table */
- if (sg_data->mlli_nents[i] != NULL) {
- /*Calculate the current MLLI table length for the
- length field in the descriptor*/
- *(sg_data->mlli_nents[i]) +=
+ if (sg_data->mlli_nents[i]) {
+ /*Calculate the current MLLI table length for the
+ *length field in the descriptor
+ */
+ *(sg_data->mlli_nents[i]) +=
(total_nents - prev_total_nents);
prev_total_nents = total_nents;
}
@@ -353,7 +271,7 @@ build_mlli_exit:
static inline void ssi_buffer_mgr_add_buffer_entry(
struct buffer_array *sgl_data,
dma_addr_t buffer_dma, unsigned int buffer_len,
- bool is_last_entry, uint32_t *mlli_nents)
+ bool is_last_entry, u32 *mlli_nents)
{
unsigned int index = sgl_data->num_of_buffers;
@@ -367,7 +285,7 @@ static inline void ssi_buffer_mgr_add_buffer_entry(
sgl_data->type[index] = DMA_BUFF_TYPE;
sgl_data->is_last[index] = is_last_entry;
sgl_data->mlli_nents[index] = mlli_nents;
- if (sgl_data->mlli_nents[index] != NULL)
+ if (sgl_data->mlli_nents[index])
*sgl_data->mlli_nents[index] = 0;
sgl_data->num_of_buffers++;
}
@@ -379,7 +297,7 @@ static inline void ssi_buffer_mgr_add_scatterlist_entry(
unsigned int data_len,
unsigned int data_offset,
bool is_last_table,
- uint32_t *mlli_nents)
+ u32 *mlli_nents)
{
unsigned int index = sgl_data->num_of_buffers;
@@ -392,22 +310,22 @@ static inline void ssi_buffer_mgr_add_scatterlist_entry(
sgl_data->type[index] = DMA_SGL_TYPE;
sgl_data->is_last[index] = is_last_table;
sgl_data->mlli_nents[index] = mlli_nents;
- if (sgl_data->mlli_nents[index] != NULL)
+ if (sgl_data->mlli_nents[index])
*sgl_data->mlli_nents[index] = 0;
sgl_data->num_of_buffers++;
}
static int
-ssi_buffer_mgr_dma_map_sg(struct device *dev, struct scatterlist *sg, uint32_t nents,
+ssi_buffer_mgr_dma_map_sg(struct device *dev, struct scatterlist *sg, u32 nents,
enum dma_data_direction direction)
{
- uint32_t i , j;
+ u32 i, j;
struct scatterlist *l_sg = sg;
+
for (i = 0; i < nents; i++) {
- if (l_sg == NULL) {
+ if (!l_sg)
break;
- }
- if (unlikely(dma_map_sg(dev, l_sg, 1, direction) != 1)){
+ if (unlikely(dma_map_sg(dev, l_sg, 1, direction) != 1)) {
SSI_LOG_ERR("dma_map_page() sg buffer failed\n");
goto err;
}
@@ -418,10 +336,9 @@ ssi_buffer_mgr_dma_map_sg(struct device *dev, struct scatterlist *sg, uint32_t n
err:
/* Restore mapped parts */
for (j = 0; j < i; j++) {
- if (sg == NULL) {
+ if (!sg)
break;
- }
- dma_unmap_sg(dev,sg,1,direction);
+ dma_unmap_sg(dev, sg, 1, direction);
sg = sg_next(sg);
}
return 0;
@@ -430,8 +347,8 @@ err:
static int ssi_buffer_mgr_map_scatterlist(
struct device *dev, struct scatterlist *sg,
unsigned int nbytes, int direction,
- uint32_t *nents, uint32_t max_sg_nents,
- uint32_t *lbytes, uint32_t *mapped_nents)
+ u32 *nents, u32 max_sg_nents,
+ u32 *lbytes, u32 *mapped_nents)
{
bool is_chained = false;
@@ -440,20 +357,19 @@ static int ssi_buffer_mgr_map_scatterlist(
if (unlikely(dma_map_sg(dev, sg, 1, direction) != 1)) {
SSI_LOG_ERR("dma_map_sg() single buffer failed\n");
return -ENOMEM;
- }
+ }
SSI_LOG_DEBUG("Mapped sg: dma_address=0x%llX "
- "page_link=0x%08lX addr=%pK offset=%u "
+ "page=%p addr=%pK offset=%u "
"length=%u\n",
- (unsigned long long)sg_dma_address(sg),
- sg->page_link,
- sg_virt(sg),
+ (unsigned long long)sg_dma_address(sg),
+ sg_page(sg),
+ sg_virt(sg),
sg->offset, sg->length);
*lbytes = nbytes;
*nents = 1;
*mapped_nents = 1;
- SSI_UPDATE_DMA_ADDR_TO_48BIT(sg_dma_address(sg), sg_dma_len(sg));
} else { /*sg_is_last*/
- *nents = ssi_buffer_mgr_get_sgl_nents(sg, nbytes, lbytes,
+ *nents = ssi_buffer_mgr_get_sgl_nents(sg, nbytes, lbytes,
&is_chained);
if (*nents > max_sg_nents) {
*nents = 0;
@@ -463,21 +379,23 @@ static int ssi_buffer_mgr_map_scatterlist(
}
if (!is_chained) {
/* In case of mmu the number of mapped nents might
- be changed from the original sgl nents */
+ * be changed from the original sgl nents
+ */
*mapped_nents = dma_map_sg(dev, sg, *nents, direction);
- if (unlikely(*mapped_nents == 0)){
+ if (unlikely(*mapped_nents == 0)) {
*nents = 0;
SSI_LOG_ERR("dma_map_sg() sg buffer failed\n");
return -ENOMEM;
}
} else {
/*In this case the driver maps entry by entry so it
- must have the same nents before and after map */
+ * must have the same nents before and after map
+ */
*mapped_nents = ssi_buffer_mgr_dma_map_sg(dev,
sg,
*nents,
direction);
- if (unlikely(*mapped_nents != *nents)){
+ if (unlikely(*mapped_nents != *nents)) {
*nents = *mapped_nents;
SSI_LOG_ERR("dma_map_sg() sg buffer failed\n");
return -ENOMEM;
@@ -491,48 +409,47 @@ static int ssi_buffer_mgr_map_scatterlist(
static inline int
ssi_aead_handle_config_buf(struct device *dev,
struct aead_req_ctx *areq_ctx,
- uint8_t* config_data,
+ u8 *config_data,
struct buffer_array *sg_data,
unsigned int assoclen)
{
- SSI_LOG_DEBUG(" handle additional data config set to DLLI \n");
+ SSI_LOG_DEBUG(" handle additional data config set to DLLI\n");
/* create sg for the current buffer */
sg_init_one(&areq_ctx->ccm_adata_sg, config_data, AES_BLOCK_SIZE + areq_ctx->ccm_hdr_size);
- if (unlikely(dma_map_sg(dev, &areq_ctx->ccm_adata_sg, 1,
+ if (unlikely(dma_map_sg(dev, &areq_ctx->ccm_adata_sg, 1,
DMA_TO_DEVICE) != 1)) {
SSI_LOG_ERR("dma_map_sg() "
"config buffer failed\n");
return -ENOMEM;
}
SSI_LOG_DEBUG("Mapped curr_buff: dma_address=0x%llX "
- "page_link=0x%08lX addr=%pK "
+ "page=%p addr=%pK "
"offset=%u length=%u\n",
- (unsigned long long)sg_dma_address(&areq_ctx->ccm_adata_sg),
- areq_ctx->ccm_adata_sg.page_link,
+ (unsigned long long)sg_dma_address(&areq_ctx->ccm_adata_sg),
+ sg_page(&areq_ctx->ccm_adata_sg),
sg_virt(&areq_ctx->ccm_adata_sg),
- areq_ctx->ccm_adata_sg.offset,
+ areq_ctx->ccm_adata_sg.offset,
areq_ctx->ccm_adata_sg.length);
/* prepare for case of MLLI */
if (assoclen > 0) {
- ssi_buffer_mgr_add_scatterlist_entry(sg_data, 1,
+ ssi_buffer_mgr_add_scatterlist_entry(sg_data, 1,
&areq_ctx->ccm_adata_sg,
- (AES_BLOCK_SIZE +
+ (AES_BLOCK_SIZE +
areq_ctx->ccm_hdr_size), 0,
false, NULL);
}
return 0;
}
-
static inline int ssi_ahash_handle_curr_buf(struct device *dev,
struct ahash_req_ctx *areq_ctx,
- uint8_t* curr_buff,
- uint32_t curr_buff_cnt,
+ u8 *curr_buff,
+ u32 curr_buff_cnt,
struct buffer_array *sg_data)
{
- SSI_LOG_DEBUG(" handle curr buff %x set to DLLI \n", curr_buff_cnt);
+ SSI_LOG_DEBUG(" handle curr buff %x set to DLLI\n", curr_buff_cnt);
/* create sg for the current buffer */
- sg_init_one(areq_ctx->buff_sg,curr_buff, curr_buff_cnt);
+ sg_init_one(areq_ctx->buff_sg, curr_buff, curr_buff_cnt);
if (unlikely(dma_map_sg(dev, areq_ctx->buff_sg, 1,
DMA_TO_DEVICE) != 1)) {
SSI_LOG_ERR("dma_map_sg() "
@@ -540,12 +457,12 @@ static inline int ssi_ahash_handle_curr_buf(struct device *dev,
return -ENOMEM;
}
SSI_LOG_DEBUG("Mapped curr_buff: dma_address=0x%llX "
- "page_link=0x%08lX addr=%pK "
+ "page=%p addr=%pK "
"offset=%u length=%u\n",
- (unsigned long long)sg_dma_address(areq_ctx->buff_sg),
- areq_ctx->buff_sg->page_link,
+ (unsigned long long)sg_dma_address(areq_ctx->buff_sg),
+ sg_page(areq_ctx->buff_sg),
sg_virt(areq_ctx->buff_sg),
- areq_ctx->buff_sg->offset,
+ areq_ctx->buff_sg->offset,
areq_ctx->buff_sg->length);
areq_ctx->data_dma_buf_type = SSI_DMA_BUF_DLLI;
areq_ctx->curr_sg = areq_ctx->buff_sg;
@@ -566,32 +483,28 @@ void ssi_buffer_mgr_unmap_blkcipher_request(
struct blkcipher_req_ctx *req_ctx = (struct blkcipher_req_ctx *)ctx;
if (likely(req_ctx->gen_ctx.iv_dma_addr != 0)) {
- SSI_LOG_DEBUG("Unmapped iv: iv_dma_addr=0x%llX iv_size=%u\n",
+ SSI_LOG_DEBUG("Unmapped iv: iv_dma_addr=0x%llX iv_size=%u\n",
(unsigned long long)req_ctx->gen_ctx.iv_dma_addr,
ivsize);
- SSI_RESTORE_DMA_ADDR_TO_48BIT(req_ctx->gen_ctx.iv_dma_addr);
- dma_unmap_single(dev, req_ctx->gen_ctx.iv_dma_addr,
- ivsize,
+ dma_unmap_single(dev, req_ctx->gen_ctx.iv_dma_addr,
+ ivsize,
req_ctx->is_giv ? DMA_BIDIRECTIONAL :
DMA_TO_DEVICE);
}
/* Release pool */
if (req_ctx->dma_buf_type == SSI_DMA_BUF_MLLI) {
- SSI_RESTORE_DMA_ADDR_TO_48BIT(req_ctx->mlli_params.mlli_dma_addr);
dma_pool_free(req_ctx->mlli_params.curr_pool,
req_ctx->mlli_params.mlli_virt_addr,
req_ctx->mlli_params.mlli_dma_addr);
}
- SSI_RESTORE_DMA_ADDR_TO_48BIT(sg_dma_address(src));
dma_unmap_sg(dev, src, req_ctx->in_nents,
DMA_BIDIRECTIONAL);
- SSI_LOG_DEBUG("Unmapped req->src=%pK\n",
+ SSI_LOG_DEBUG("Unmapped req->src=%pK\n",
sg_virt(src));
if (src != dst) {
- SSI_RESTORE_DMA_ADDR_TO_48BIT(sg_dma_address(dst));
- dma_unmap_sg(dev, dst, req_ctx->out_nents,
+ dma_unmap_sg(dev, dst, req_ctx->out_nents,
DMA_BIDIRECTIONAL);
SSI_LOG_DEBUG("Unmapped req->dst=%pK\n",
sg_virt(dst));
@@ -608,40 +521,39 @@ int ssi_buffer_mgr_map_blkcipher_request(
struct scatterlist *dst)
{
struct blkcipher_req_ctx *req_ctx = (struct blkcipher_req_ctx *)ctx;
- struct mlli_params *mlli_params = &req_ctx->mlli_params;
+ struct mlli_params *mlli_params = &req_ctx->mlli_params;
struct buff_mgr_handle *buff_mgr = drvdata->buff_mgr_handle;
struct device *dev = &drvdata->plat_dev->dev;
struct buffer_array sg_data;
- uint32_t dummy = 0;
+ u32 dummy = 0;
int rc = 0;
- uint32_t mapped_nents = 0;
+ u32 mapped_nents = 0;
req_ctx->dma_buf_type = SSI_DMA_BUF_DLLI;
mlli_params->curr_pool = NULL;
sg_data.num_of_buffers = 0;
/* Map IV buffer */
- if (likely(ivsize != 0) ) {
- dump_byte_array("iv", (uint8_t *)info, ivsize);
- req_ctx->gen_ctx.iv_dma_addr =
- dma_map_single(dev, (void *)info,
- ivsize,
- req_ctx->is_giv ? DMA_BIDIRECTIONAL:
+ if (likely(ivsize != 0)) {
+ dump_byte_array("iv", (u8 *)info, ivsize);
+ req_ctx->gen_ctx.iv_dma_addr =
+ dma_map_single(dev, (void *)info,
+ ivsize,
+ req_ctx->is_giv ? DMA_BIDIRECTIONAL :
DMA_TO_DEVICE);
- if (unlikely(dma_mapping_error(dev,
+ if (unlikely(dma_mapping_error(dev,
req_ctx->gen_ctx.iv_dma_addr))) {
SSI_LOG_ERR("Mapping iv %u B at va=%pK "
"for DMA failed\n", ivsize, info);
return -ENOMEM;
}
- SSI_UPDATE_DMA_ADDR_TO_48BIT(req_ctx->gen_ctx.iv_dma_addr,
- ivsize);
SSI_LOG_DEBUG("Mapped iv %u B at va=%pK to dma=0x%llX\n",
ivsize, info,
(unsigned long long)req_ctx->gen_ctx.iv_dma_addr);
- } else
+ } else {
req_ctx->gen_ctx.iv_dma_addr = 0;
-
+ }
+
/* Map the src SGL */
rc = ssi_buffer_mgr_map_scatterlist(dev, src,
nbytes, DMA_BIDIRECTIONAL, &req_ctx->in_nents,
@@ -664,7 +576,7 @@ int ssi_buffer_mgr_map_blkcipher_request(
} else {
/* Map the dst sg */
if (unlikely(ssi_buffer_mgr_map_scatterlist(
- dev,dst, nbytes,
+ dev, dst, nbytes,
DMA_BIDIRECTIONAL, &req_ctx->out_nents,
LLI_MAX_NUM_OF_DATA_ENTRIES, &dummy,
&mapped_nents))){
@@ -681,17 +593,16 @@ int ssi_buffer_mgr_map_blkcipher_request(
&req_ctx->in_mlli_nents);
ssi_buffer_mgr_add_scatterlist_entry(&sg_data,
req_ctx->out_nents, dst,
- nbytes, 0, true,
+ nbytes, 0, true,
&req_ctx->out_mlli_nents);
}
}
-
+
if (unlikely(req_ctx->dma_buf_type == SSI_DMA_BUF_MLLI)) {
mlli_params->curr_pool = buff_mgr->mlli_buffs_pool;
rc = ssi_buffer_mgr_generate_mlli(dev, &sg_data, mlli_params);
- if (unlikely(rc!= 0))
+ if (unlikely(rc != 0))
goto ablkcipher_exit;
-
}
SSI_LOG_DEBUG("areq_ctx->dma_buf_type = %s\n",
@@ -710,39 +621,35 @@ void ssi_buffer_mgr_unmap_aead_request(
struct aead_req_ctx *areq_ctx = aead_request_ctx(req);
unsigned int hw_iv_size = areq_ctx->hw_iv_size;
struct crypto_aead *tfm = crypto_aead_reqtfm(req);
- uint32_t dummy;
+ struct ssi_drvdata *drvdata = dev_get_drvdata(dev);
+ u32 dummy;
bool chained;
- uint32_t size_to_unmap = 0;
+ u32 size_to_unmap = 0;
if (areq_ctx->mac_buf_dma_addr != 0) {
- SSI_RESTORE_DMA_ADDR_TO_48BIT(areq_ctx->mac_buf_dma_addr);
- dma_unmap_single(dev, areq_ctx->mac_buf_dma_addr,
+ dma_unmap_single(dev, areq_ctx->mac_buf_dma_addr,
MAX_MAC_SIZE, DMA_BIDIRECTIONAL);
}
#if SSI_CC_HAS_AES_GCM
if (areq_ctx->cipher_mode == DRV_CIPHER_GCTR) {
if (areq_ctx->hkey_dma_addr != 0) {
- SSI_RESTORE_DMA_ADDR_TO_48BIT(areq_ctx->hkey_dma_addr);
dma_unmap_single(dev, areq_ctx->hkey_dma_addr,
AES_BLOCK_SIZE, DMA_BIDIRECTIONAL);
}
-
+
if (areq_ctx->gcm_block_len_dma_addr != 0) {
- SSI_RESTORE_DMA_ADDR_TO_48BIT(areq_ctx->gcm_block_len_dma_addr);
dma_unmap_single(dev, areq_ctx->gcm_block_len_dma_addr,
AES_BLOCK_SIZE, DMA_TO_DEVICE);
}
-
+
if (areq_ctx->gcm_iv_inc1_dma_addr != 0) {
- SSI_RESTORE_DMA_ADDR_TO_48BIT(areq_ctx->gcm_iv_inc1_dma_addr);
- dma_unmap_single(dev, areq_ctx->gcm_iv_inc1_dma_addr,
+ dma_unmap_single(dev, areq_ctx->gcm_iv_inc1_dma_addr,
AES_BLOCK_SIZE, DMA_TO_DEVICE);
}
-
+
if (areq_ctx->gcm_iv_inc2_dma_addr != 0) {
- SSI_RESTORE_DMA_ADDR_TO_48BIT(areq_ctx->gcm_iv_inc2_dma_addr);
- dma_unmap_single(dev, areq_ctx->gcm_iv_inc2_dma_addr,
+ dma_unmap_single(dev, areq_ctx->gcm_iv_inc2_dma_addr,
AES_BLOCK_SIZE, DMA_TO_DEVICE);
}
}
@@ -750,93 +657,87 @@ void ssi_buffer_mgr_unmap_aead_request(
if (areq_ctx->ccm_hdr_size != ccm_header_size_null) {
if (areq_ctx->ccm_iv0_dma_addr != 0) {
- SSI_RESTORE_DMA_ADDR_TO_48BIT(areq_ctx->ccm_iv0_dma_addr);
- dma_unmap_single(dev, areq_ctx->ccm_iv0_dma_addr,
+ dma_unmap_single(dev, areq_ctx->ccm_iv0_dma_addr,
AES_BLOCK_SIZE, DMA_TO_DEVICE);
}
dma_unmap_sg(dev, &areq_ctx->ccm_adata_sg, 1, DMA_TO_DEVICE);
}
if (areq_ctx->gen_ctx.iv_dma_addr != 0) {
- SSI_RESTORE_DMA_ADDR_TO_48BIT(areq_ctx->gen_ctx.iv_dma_addr);
dma_unmap_single(dev, areq_ctx->gen_ctx.iv_dma_addr,
hw_iv_size, DMA_BIDIRECTIONAL);
}
- /*In case a pool was set, a table was
- allocated and should be released */
- if (areq_ctx->mlli_params.curr_pool != NULL) {
- SSI_LOG_DEBUG("free MLLI buffer: dma=0x%08llX virt=%pK\n",
+ /*In case a pool was set, a table was
+ *allocated and should be released
+ */
+ if (areq_ctx->mlli_params.curr_pool) {
+ SSI_LOG_DEBUG("free MLLI buffer: dma=0x%08llX virt=%pK\n",
(unsigned long long)areq_ctx->mlli_params.mlli_dma_addr,
areq_ctx->mlli_params.mlli_virt_addr);
- SSI_RESTORE_DMA_ADDR_TO_48BIT(areq_ctx->mlli_params.mlli_dma_addr);
dma_pool_free(areq_ctx->mlli_params.curr_pool,
areq_ctx->mlli_params.mlli_virt_addr,
areq_ctx->mlli_params.mlli_dma_addr);
}
- SSI_LOG_DEBUG("Unmapping src sgl: req->src=%pK areq_ctx->src.nents=%u areq_ctx->assoc.nents=%u assoclen:%u cryptlen=%u\n", sg_virt(req->src),areq_ctx->src.nents,areq_ctx->assoc.nents,req->assoclen,req->cryptlen);
- SSI_RESTORE_DMA_ADDR_TO_48BIT(sg_dma_address(req->src));
- size_to_unmap = req->assoclen+req->cryptlen;
- if(areq_ctx->gen_ctx.op_type == DRV_CRYPTO_DIRECTION_ENCRYPT){
+ SSI_LOG_DEBUG("Unmapping src sgl: req->src=%pK areq_ctx->src.nents=%u areq_ctx->assoc.nents=%u assoclen:%u cryptlen=%u\n", sg_virt(req->src), areq_ctx->src.nents, areq_ctx->assoc.nents, req->assoclen, req->cryptlen);
+ size_to_unmap = req->assoclen + req->cryptlen;
+ if (areq_ctx->gen_ctx.op_type == DRV_CRYPTO_DIRECTION_ENCRYPT)
size_to_unmap += areq_ctx->req_authsize;
- }
if (areq_ctx->is_gcm4543)
size_to_unmap += crypto_aead_ivsize(tfm);
- dma_unmap_sg(dev, req->src, ssi_buffer_mgr_get_sgl_nents(req->src,size_to_unmap,&dummy,&chained) , DMA_BIDIRECTIONAL);
+ dma_unmap_sg(dev, req->src, ssi_buffer_mgr_get_sgl_nents(req->src, size_to_unmap, &dummy, &chained), DMA_BIDIRECTIONAL);
if (unlikely(req->src != req->dst)) {
- SSI_LOG_DEBUG("Unmapping dst sgl: req->dst=%pK\n",
+ SSI_LOG_DEBUG("Unmapping dst sgl: req->dst=%pK\n",
sg_virt(req->dst));
- SSI_RESTORE_DMA_ADDR_TO_48BIT(sg_dma_address(req->dst));
- dma_unmap_sg(dev, req->dst, ssi_buffer_mgr_get_sgl_nents(req->dst,size_to_unmap,&dummy,&chained),
+ dma_unmap_sg(dev, req->dst, ssi_buffer_mgr_get_sgl_nents(req->dst, size_to_unmap, &dummy, &chained),
DMA_BIDIRECTIONAL);
}
-#if DX_HAS_ACP
- if ((areq_ctx->gen_ctx.op_type == DRV_CRYPTO_DIRECTION_DECRYPT) &&
+ if (drvdata->coherent &&
+ (areq_ctx->gen_ctx.op_type == DRV_CRYPTO_DIRECTION_DECRYPT) &&
likely(req->src == req->dst))
{
- uint32_t size_to_skip = req->assoclen;
- if (areq_ctx->is_gcm4543) {
+ u32 size_to_skip = req->assoclen;
+
+ if (areq_ctx->is_gcm4543)
size_to_skip += crypto_aead_ivsize(tfm);
- }
+
/* copy mac to a temporary location to deal with possible
- data memory overriding that caused by cache coherence problem. */
+ * data memory overriding that caused by cache coherence problem.
+ */
ssi_buffer_mgr_copy_scatterlist_portion(
areq_ctx->backup_mac, req->src,
- size_to_skip+ req->cryptlen - areq_ctx->req_authsize,
- size_to_skip+ req->cryptlen, SSI_SG_FROM_BUF);
+ size_to_skip + req->cryptlen - areq_ctx->req_authsize,
+ size_to_skip + req->cryptlen, SSI_SG_FROM_BUF);
}
-#endif
}
static inline int ssi_buffer_mgr_get_aead_icv_nents(
struct scatterlist *sgl,
unsigned int sgl_nents,
unsigned int authsize,
- uint32_t last_entry_data_size,
+ u32 last_entry_data_size,
bool *is_icv_fragmented)
{
unsigned int icv_max_size = 0;
unsigned int icv_required_size = authsize > last_entry_data_size ? (authsize - last_entry_data_size) : authsize;
unsigned int nents;
unsigned int i;
-
+
if (sgl_nents < MAX_ICV_NENTS_SUPPORTED) {
*is_icv_fragmented = false;
return 0;
}
-
- for( i = 0 ; i < (sgl_nents - MAX_ICV_NENTS_SUPPORTED) ; i++) {
- if (sgl == NULL) {
+
+ for (i = 0 ; i < (sgl_nents - MAX_ICV_NENTS_SUPPORTED) ; i++) {
+ if (!sgl)
break;
- }
sgl = sg_next(sgl);
}
- if (sgl != NULL) {
+ if (sgl)
icv_max_size = sgl->length;
- }
if (last_entry_data_size > authsize) {
nents = 0; /* ICV attached to data in last entry (not fragmented!) */
@@ -872,7 +773,7 @@ static inline int ssi_buffer_mgr_aead_chain_iv(
struct device *dev = &drvdata->plat_dev->dev;
int rc = 0;
- if (unlikely(req->iv == NULL)) {
+ if (unlikely(!req->iv)) {
areq_ctx->gen_ctx.iv_dma_addr = 0;
goto chain_iv_exit;
}
@@ -883,14 +784,13 @@ static inline int ssi_buffer_mgr_aead_chain_iv(
SSI_LOG_ERR("Mapping iv %u B at va=%pK for DMA failed\n",
hw_iv_size, req->iv);
rc = -ENOMEM;
- goto chain_iv_exit;
+ goto chain_iv_exit;
}
- SSI_UPDATE_DMA_ADDR_TO_48BIT(areq_ctx->gen_ctx.iv_dma_addr, hw_iv_size);
SSI_LOG_DEBUG("Mapped iv %u B at va=%pK to dma=0x%llX\n",
- hw_iv_size, req->iv,
+ hw_iv_size, req->iv,
(unsigned long long)areq_ctx->gen_ctx.iv_dma_addr);
- if (do_chain == true && areq_ctx->plaintext_authenticate_only == true){ // TODO: what about CTR?? ask Ron
+ if (do_chain && areq_ctx->plaintext_authenticate_only) { // TODO: what about CTR?? ask Ron
struct crypto_aead *tfm = crypto_aead_reqtfm(req);
unsigned int iv_size_to_authenc = crypto_aead_ivsize(tfm);
unsigned int iv_ofs = GCM_BLOCK_RFC4_IV_OFFSET;
@@ -914,17 +814,16 @@ static inline int ssi_buffer_mgr_aead_chain_assoc(
{
struct aead_req_ctx *areq_ctx = aead_request_ctx(req);
int rc = 0;
- uint32_t mapped_nents = 0;
+ u32 mapped_nents = 0;
struct scatterlist *current_sg = req->src;
struct crypto_aead *tfm = crypto_aead_reqtfm(req);
unsigned int sg_index = 0;
- uint32_t size_of_assoc = req->assoclen;
+ u32 size_of_assoc = req->assoclen;
- if (areq_ctx->is_gcm4543) {
+ if (areq_ctx->is_gcm4543)
size_of_assoc += crypto_aead_ivsize(tfm);
- }
- if (sg_data == NULL) {
+ if (!sg_data) {
rc = -EINVAL;
goto chain_assoc_exit;
}
@@ -943,14 +842,13 @@ static inline int ssi_buffer_mgr_aead_chain_assoc(
//it is assumed that if we reach here , the sgl is already mapped
sg_index = current_sg->length;
if (sg_index > size_of_assoc) { //the first entry in the scatter list contains all the associated data
- mapped_nents++;
- }
- else{
+ mapped_nents++;
+ } else {
while (sg_index <= size_of_assoc) {
current_sg = sg_next(current_sg);
//if have reached the end of the sgl, then this is unexpected
- if (current_sg == NULL) {
- SSI_LOG_ERR("reached end of sg list. unexpected \n");
+ if (!current_sg) {
+ SSI_LOG_ERR("reached end of sg list. unexpected\n");
BUG();
}
sg_index += current_sg->length;
@@ -965,11 +863,11 @@ static inline int ssi_buffer_mgr_aead_chain_assoc(
areq_ctx->assoc.nents = mapped_nents;
/* in CCM case we have additional entry for
- * ccm header configurations */
+ * ccm header configurations
+ */
if (areq_ctx->ccm_hdr_size != ccm_header_size_null) {
if (unlikely((mapped_nents + 1) >
LLI_MAX_NUM_OF_ASSOC_DATA_ENTRIES)) {
-
SSI_LOG_ERR("CCM case.Too many fragments. "
"Current %d max %d\n",
(areq_ctx->assoc.nents + 1),
@@ -985,9 +883,8 @@ static inline int ssi_buffer_mgr_aead_chain_assoc(
else
areq_ctx->assoc_buff_type = SSI_DMA_BUF_MLLI;
- if (unlikely((do_chain == true) ||
+ if (unlikely((do_chain) ||
(areq_ctx->assoc_buff_type == SSI_DMA_BUF_MLLI))) {
-
SSI_LOG_DEBUG("Chain assoc: buff_type=%s nents=%u\n",
GET_DMA_BUFFER_TYPE(areq_ctx->assoc_buff_type),
areq_ctx->assoc.nents);
@@ -1004,7 +901,7 @@ chain_assoc_exit:
static inline void ssi_buffer_mgr_prepare_aead_data_dlli(
struct aead_request *req,
- uint32_t *src_last_bytes, uint32_t *dst_last_bytes)
+ u32 *src_last_bytes, u32 *dst_last_bytes)
{
struct aead_req_ctx *areq_ctx = aead_request_ctx(req);
enum drv_crypto_direction direct = areq_ctx->gen_ctx.op_type;
@@ -1014,7 +911,7 @@ static inline void ssi_buffer_mgr_prepare_aead_data_dlli(
if (likely(req->src == req->dst)) {
/*INPLACE*/
areq_ctx->icv_dma_addr = sg_dma_address(
- areq_ctx->srcSgl)+
+ areq_ctx->srcSgl) +
(*src_last_bytes - authsize);
areq_ctx->icv_virt_addr = sg_virt(
areq_ctx->srcSgl) +
@@ -1033,7 +930,7 @@ static inline void ssi_buffer_mgr_prepare_aead_data_dlli(
areq_ctx->dstSgl) +
(*dst_last_bytes - authsize);
areq_ctx->icv_virt_addr = sg_virt(
- areq_ctx->dstSgl)+
+ areq_ctx->dstSgl) +
(*dst_last_bytes - authsize);
}
}
@@ -1042,7 +939,7 @@ static inline int ssi_buffer_mgr_prepare_aead_data_mlli(
struct ssi_drvdata *drvdata,
struct aead_request *req,
struct buffer_array *sg_data,
- uint32_t *src_last_bytes, uint32_t *dst_last_bytes,
+ u32 *src_last_bytes, u32 *dst_last_bytes,
bool is_last_table)
{
struct aead_req_ctx *areq_ctx = aead_request_ctx(req);
@@ -1055,7 +952,7 @@ static inline int ssi_buffer_mgr_prepare_aead_data_mlli(
/*INPLACE*/
ssi_buffer_mgr_add_scatterlist_entry(sg_data,
areq_ctx->src.nents, areq_ctx->srcSgl,
- areq_ctx->cryptlen,areq_ctx->srcOffset, is_last_table,
+ areq_ctx->cryptlen, areq_ctx->srcOffset, is_last_table,
&areq_ctx->src.mlli_nents);
icv_nents = ssi_buffer_mgr_get_aead_icv_nents(areq_ctx->srcSgl,
@@ -1066,24 +963,30 @@ static inline int ssi_buffer_mgr_prepare_aead_data_mlli(
goto prepare_data_mlli_exit;
}
- if (unlikely(areq_ctx->is_icv_fragmented == true)) {
+ if (unlikely(areq_ctx->is_icv_fragmented)) {
/* Backup happens only when ICV is fragmented, ICV
- verification is made by CPU compare in order to simplify
- MAC verification upon request completion */
+ * verification is made by CPU compare in order to simplify
+ * MAC verification upon request completion
+ */
if (direct == DRV_CRYPTO_DIRECTION_DECRYPT) {
-#if !DX_HAS_ACP
- /* In ACP platform we already copying ICV
- for any INPLACE-DECRYPT operation, hence
- we must neglect this code. */
- uint32_t size_to_skip = req->assoclen;
- if (areq_ctx->is_gcm4543) {
- size_to_skip += crypto_aead_ivsize(tfm);
+ if (!drvdata->coherent) {
+ /* In coherent platforms (e.g. ACP)
+ * already copying ICV for any
+ * INPLACE-DECRYPT operation, hence
+ * we must neglect this code.
+ */
+ u32 skip = req->assoclen;
+
+ if (areq_ctx->is_gcm4543)
+ skip += crypto_aead_ivsize(tfm);
+
+ ssi_buffer_mgr_copy_scatterlist_portion(
+ areq_ctx->backup_mac, req->src,
+ (skip + req->cryptlen -
+ areq_ctx->req_authsize),
+ skip + req->cryptlen,
+ SSI_SG_TO_BUF);
}
- ssi_buffer_mgr_copy_scatterlist_portion(
- areq_ctx->backup_mac, req->src,
- size_to_skip+ req->cryptlen - areq_ctx->req_authsize,
- size_to_skip+ req->cryptlen, SSI_SG_TO_BUF);
-#endif
areq_ctx->icv_virt_addr = areq_ctx->backup_mac;
} else {
areq_ctx->icv_virt_addr = areq_ctx->mac_buf;
@@ -1095,7 +998,7 @@ static inline int ssi_buffer_mgr_prepare_aead_data_mlli(
&areq_ctx->srcSgl[areq_ctx->src.nents - 1]) +
(*src_last_bytes - authsize);
areq_ctx->icv_virt_addr = sg_virt(
- &areq_ctx->srcSgl[areq_ctx->src.nents - 1]) +
+ &areq_ctx->srcSgl[areq_ctx->src.nents - 1]) +
(*src_last_bytes - authsize);
}
@@ -1103,11 +1006,11 @@ static inline int ssi_buffer_mgr_prepare_aead_data_mlli(
/*NON-INPLACE and DECRYPT*/
ssi_buffer_mgr_add_scatterlist_entry(sg_data,
areq_ctx->src.nents, areq_ctx->srcSgl,
- areq_ctx->cryptlen, areq_ctx->srcOffset,is_last_table,
+ areq_ctx->cryptlen, areq_ctx->srcOffset, is_last_table,
&areq_ctx->src.mlli_nents);
ssi_buffer_mgr_add_scatterlist_entry(sg_data,
areq_ctx->dst.nents, areq_ctx->dstSgl,
- areq_ctx->cryptlen,areq_ctx->dstOffset, is_last_table,
+ areq_ctx->cryptlen, areq_ctx->dstOffset, is_last_table,
&areq_ctx->dst.mlli_nents);
icv_nents = ssi_buffer_mgr_get_aead_icv_nents(areq_ctx->srcSgl,
@@ -1118,18 +1021,20 @@ static inline int ssi_buffer_mgr_prepare_aead_data_mlli(
goto prepare_data_mlli_exit;
}
- if (unlikely(areq_ctx->is_icv_fragmented == true)) {
+ if (unlikely(areq_ctx->is_icv_fragmented)) {
/* Backup happens only when ICV is fragmented, ICV
- verification is made by CPU compare in order to simplify
- MAC verification upon request completion */
- uint32_t size_to_skip = req->assoclen;
- if (areq_ctx->is_gcm4543) {
+ * verification is made by CPU compare in order to simplify
+ * MAC verification upon request completion
+ */
+ u32 size_to_skip = req->assoclen;
+
+ if (areq_ctx->is_gcm4543)
size_to_skip += crypto_aead_ivsize(tfm);
- }
+
ssi_buffer_mgr_copy_scatterlist_portion(
areq_ctx->backup_mac, req->src,
- size_to_skip+ req->cryptlen - areq_ctx->req_authsize,
- size_to_skip+ req->cryptlen, SSI_SG_TO_BUF);
+ size_to_skip + req->cryptlen - areq_ctx->req_authsize,
+ size_to_skip + req->cryptlen, SSI_SG_TO_BUF);
areq_ctx->icv_virt_addr = areq_ctx->backup_mac;
} else { /* Contig. ICV */
/*Should hanlde if the sg is not contig.*/
@@ -1145,11 +1050,11 @@ static inline int ssi_buffer_mgr_prepare_aead_data_mlli(
/*NON-INPLACE and ENCRYPT*/
ssi_buffer_mgr_add_scatterlist_entry(sg_data,
areq_ctx->dst.nents, areq_ctx->dstSgl,
- areq_ctx->cryptlen,areq_ctx->dstOffset, is_last_table,
+ areq_ctx->cryptlen, areq_ctx->dstOffset, is_last_table,
&areq_ctx->dst.mlli_nents);
ssi_buffer_mgr_add_scatterlist_entry(sg_data,
areq_ctx->src.nents, areq_ctx->srcSgl,
- areq_ctx->cryptlen, areq_ctx->srcOffset,is_last_table,
+ areq_ctx->cryptlen, areq_ctx->srcOffset, is_last_table,
&areq_ctx->src.mlli_nents);
icv_nents = ssi_buffer_mgr_get_aead_icv_nents(areq_ctx->dstSgl,
@@ -1160,7 +1065,7 @@ static inline int ssi_buffer_mgr_prepare_aead_data_mlli(
goto prepare_data_mlli_exit;
}
- if (likely(areq_ctx->is_icv_fragmented == false)) {
+ if (likely(!areq_ctx->is_icv_fragmented)) {
/* Contig. ICV */
areq_ctx->icv_dma_addr = sg_dma_address(
&areq_ctx->dstSgl[areq_ctx->dst.nents - 1]) +
@@ -1190,40 +1095,40 @@ static inline int ssi_buffer_mgr_aead_chain_data(
unsigned int authsize = areq_ctx->req_authsize;
int src_last_bytes = 0, dst_last_bytes = 0;
int rc = 0;
- uint32_t src_mapped_nents = 0, dst_mapped_nents = 0;
- uint32_t offset = 0;
- unsigned int size_for_map = req->assoclen +req->cryptlen; /*non-inplace mode*/
+ u32 src_mapped_nents = 0, dst_mapped_nents = 0;
+ u32 offset = 0;
+ unsigned int size_for_map = req->assoclen + req->cryptlen; /*non-inplace mode*/
struct crypto_aead *tfm = crypto_aead_reqtfm(req);
- uint32_t sg_index = 0;
+ u32 sg_index = 0;
bool chained = false;
bool is_gcm4543 = areq_ctx->is_gcm4543;
- uint32_t size_to_skip = req->assoclen;
- if (is_gcm4543) {
+ u32 size_to_skip = req->assoclen;
+
+ if (is_gcm4543)
size_to_skip += crypto_aead_ivsize(tfm);
- }
+
offset = size_to_skip;
- if (sg_data == NULL) {
+ if (!sg_data) {
rc = -EINVAL;
goto chain_data_exit;
}
areq_ctx->srcSgl = req->src;
areq_ctx->dstSgl = req->dst;
- if (is_gcm4543) {
+ if (is_gcm4543)
size_for_map += crypto_aead_ivsize(tfm);
- }
- size_for_map += (direct == DRV_CRYPTO_DIRECTION_ENCRYPT) ? authsize:0;
- src_mapped_nents = ssi_buffer_mgr_get_sgl_nents(req->src,size_for_map,&src_last_bytes, &chained);
+ size_for_map += (direct == DRV_CRYPTO_DIRECTION_ENCRYPT) ? authsize : 0;
+ src_mapped_nents = ssi_buffer_mgr_get_sgl_nents(req->src, size_for_map, &src_last_bytes, &chained);
sg_index = areq_ctx->srcSgl->length;
//check where the data starts
while (sg_index <= size_to_skip) {
offset -= areq_ctx->srcSgl->length;
areq_ctx->srcSgl = sg_next(areq_ctx->srcSgl);
//if have reached the end of the sgl, then this is unexpected
- if (areq_ctx->srcSgl == NULL) {
- SSI_LOG_ERR("reached end of sg list. unexpected \n");
+ if (!areq_ctx->srcSgl) {
+ SSI_LOG_ERR("reached end of sg list. unexpected\n");
BUG();
}
sg_index += areq_ctx->srcSgl->length;
@@ -1238,14 +1143,13 @@ static inline int ssi_buffer_mgr_aead_chain_data(
areq_ctx->src.nents = src_mapped_nents;
- areq_ctx->srcOffset = offset;
+ areq_ctx->srcOffset = offset;
if (req->src != req->dst) {
- size_for_map = req->assoclen +req->cryptlen;
+ size_for_map = req->assoclen + req->cryptlen;
size_for_map += (direct == DRV_CRYPTO_DIRECTION_ENCRYPT) ? authsize : 0;
- if (is_gcm4543) {
+ if (is_gcm4543)
size_for_map += crypto_aead_ivsize(tfm);
- }
rc = ssi_buffer_mgr_map_scatterlist(dev, req->dst, size_for_map,
DMA_BIDIRECTIONAL, &(areq_ctx->dst.nents),
@@ -1253,22 +1157,21 @@ static inline int ssi_buffer_mgr_aead_chain_data(
&dst_mapped_nents);
if (unlikely(rc != 0)) {
rc = -ENOMEM;
- goto chain_data_exit;
+ goto chain_data_exit;
}
}
- dst_mapped_nents = ssi_buffer_mgr_get_sgl_nents(req->dst,size_for_map,&dst_last_bytes, &chained);
+ dst_mapped_nents = ssi_buffer_mgr_get_sgl_nents(req->dst, size_for_map, &dst_last_bytes, &chained);
sg_index = areq_ctx->dstSgl->length;
offset = size_to_skip;
//check where the data starts
while (sg_index <= size_to_skip) {
-
offset -= areq_ctx->dstSgl->length;
areq_ctx->dstSgl = sg_next(areq_ctx->dstSgl);
//if have reached the end of the sgl, then this is unexpected
- if (areq_ctx->dstSgl == NULL) {
- SSI_LOG_ERR("reached end of sg list. unexpected \n");
+ if (!areq_ctx->dstSgl) {
+ SSI_LOG_ERR("reached end of sg list. unexpected\n");
BUG();
}
sg_index += areq_ctx->dstSgl->length;
@@ -1284,7 +1187,7 @@ static inline int ssi_buffer_mgr_aead_chain_data(
areq_ctx->dstOffset = offset;
if ((src_mapped_nents > 1) ||
(dst_mapped_nents > 1) ||
- (do_chain == true)) {
+ do_chain) {
areq_ctx->data_buff_type = SSI_DMA_BUF_MLLI;
rc = ssi_buffer_mgr_prepare_aead_data_mlli(drvdata, req, sg_data,
&src_last_bytes, &dst_last_bytes, is_last_table);
@@ -1298,15 +1201,15 @@ chain_data_exit:
return rc;
}
-static void ssi_buffer_mgr_update_aead_mlli_nents( struct ssi_drvdata *drvdata,
+static void ssi_buffer_mgr_update_aead_mlli_nents(struct ssi_drvdata *drvdata,
struct aead_request *req)
{
struct aead_req_ctx *areq_ctx = aead_request_ctx(req);
- uint32_t curr_mlli_size = 0;
-
+ u32 curr_mlli_size = 0;
+
if (areq_ctx->assoc_buff_type == SSI_DMA_BUF_MLLI) {
areq_ctx->assoc.sram_addr = drvdata->mlli_sram_addr;
- curr_mlli_size = areq_ctx->assoc.mlli_nents *
+ curr_mlli_size = areq_ctx->assoc.mlli_nents *
LLI_ENTRY_BYTE_SIZE;
}
@@ -1317,32 +1220,32 @@ static void ssi_buffer_mgr_update_aead_mlli_nents( struct ssi_drvdata *drvdata,
areq_ctx->src.sram_addr = drvdata->mlli_sram_addr +
curr_mlli_size;
areq_ctx->dst.sram_addr = areq_ctx->src.sram_addr;
- if (areq_ctx->is_single_pass == false)
- areq_ctx->assoc.mlli_nents +=
+ if (!areq_ctx->is_single_pass)
+ areq_ctx->assoc.mlli_nents +=
areq_ctx->src.mlli_nents;
} else {
- if (areq_ctx->gen_ctx.op_type ==
+ if (areq_ctx->gen_ctx.op_type ==
DRV_CRYPTO_DIRECTION_DECRYPT) {
- areq_ctx->src.sram_addr =
+ areq_ctx->src.sram_addr =
drvdata->mlli_sram_addr +
curr_mlli_size;
- areq_ctx->dst.sram_addr =
- areq_ctx->src.sram_addr +
- areq_ctx->src.mlli_nents *
+ areq_ctx->dst.sram_addr =
+ areq_ctx->src.sram_addr +
+ areq_ctx->src.mlli_nents *
LLI_ENTRY_BYTE_SIZE;
- if (areq_ctx->is_single_pass == false)
- areq_ctx->assoc.mlli_nents +=
+ if (!areq_ctx->is_single_pass)
+ areq_ctx->assoc.mlli_nents +=
areq_ctx->src.mlli_nents;
} else {
- areq_ctx->dst.sram_addr =
+ areq_ctx->dst.sram_addr =
drvdata->mlli_sram_addr +
curr_mlli_size;
- areq_ctx->src.sram_addr =
+ areq_ctx->src.sram_addr =
areq_ctx->dst.sram_addr +
- areq_ctx->dst.mlli_nents *
+ areq_ctx->dst.mlli_nents *
LLI_ENTRY_BYTE_SIZE;
- if (areq_ctx->is_single_pass == false)
- areq_ctx->assoc.mlli_nents +=
+ if (!areq_ctx->is_single_pass)
+ areq_ctx->assoc.mlli_nents +=
areq_ctx->dst.mlli_nents;
}
}
@@ -1362,33 +1265,34 @@ int ssi_buffer_mgr_map_aead_request(
struct crypto_aead *tfm = crypto_aead_reqtfm(req);
bool is_gcm4543 = areq_ctx->is_gcm4543;
- uint32_t mapped_nents = 0;
- uint32_t dummy = 0; /*used for the assoc data fragments */
- uint32_t size_to_map = 0;
+ u32 mapped_nents = 0;
+ u32 dummy = 0; /*used for the assoc data fragments */
+ u32 size_to_map = 0;
mlli_params->curr_pool = NULL;
sg_data.num_of_buffers = 0;
-#if DX_HAS_ACP
- if ((areq_ctx->gen_ctx.op_type == DRV_CRYPTO_DIRECTION_DECRYPT) &&
+ if (drvdata->coherent &&
+ (areq_ctx->gen_ctx.op_type == DRV_CRYPTO_DIRECTION_DECRYPT) &&
likely(req->src == req->dst))
{
- uint32_t size_to_skip = req->assoclen;
- if (is_gcm4543) {
+ u32 size_to_skip = req->assoclen;
+
+ if (is_gcm4543)
size_to_skip += crypto_aead_ivsize(tfm);
- }
+
/* copy mac to a temporary location to deal with possible
- data memory overriding that caused by cache coherence problem. */
+ * data memory overriding that caused by cache coherence problem.
+ */
ssi_buffer_mgr_copy_scatterlist_portion(
areq_ctx->backup_mac, req->src,
- size_to_skip+ req->cryptlen - areq_ctx->req_authsize,
- size_to_skip+ req->cryptlen, SSI_SG_TO_BUF);
+ size_to_skip + req->cryptlen - areq_ctx->req_authsize,
+ size_to_skip + req->cryptlen, SSI_SG_TO_BUF);
}
-#endif
/* cacluate the size for cipher remove ICV in decrypt*/
- areq_ctx->cryptlen = (areq_ctx->gen_ctx.op_type ==
- DRV_CRYPTO_DIRECTION_ENCRYPT) ?
+ areq_ctx->cryptlen = (areq_ctx->gen_ctx.op_type ==
+ DRV_CRYPTO_DIRECTION_ENCRYPT) ?
req->cryptlen :
(req->cryptlen - authsize);
@@ -1400,7 +1304,6 @@ int ssi_buffer_mgr_map_aead_request(
rc = -ENOMEM;
goto aead_map_failure;
}
- SSI_UPDATE_DMA_ADDR_TO_48BIT(areq_ctx->mac_buf_dma_addr, MAX_MAC_SIZE);
if (areq_ctx->ccm_hdr_size != ccm_header_size_null) {
areq_ctx->ccm_iv0_dma_addr = dma_map_single(dev,
@@ -1415,8 +1318,6 @@ int ssi_buffer_mgr_map_aead_request(
rc = -ENOMEM;
goto aead_map_failure;
}
- SSI_UPDATE_DMA_ADDR_TO_48BIT(areq_ctx->ccm_iv0_dma_addr,
- AES_BLOCK_SIZE);
if (ssi_aead_handle_config_buf(dev, areq_ctx,
areq_ctx->ccm_config, &sg_data, req->assoclen) != 0) {
rc = -ENOMEM;
@@ -1434,7 +1335,6 @@ int ssi_buffer_mgr_map_aead_request(
rc = -ENOMEM;
goto aead_map_failure;
}
- SSI_UPDATE_DMA_ADDR_TO_48BIT(areq_ctx->hkey_dma_addr, AES_BLOCK_SIZE);
areq_ctx->gcm_block_len_dma_addr = dma_map_single(dev,
&areq_ctx->gcm_len_block, AES_BLOCK_SIZE, DMA_TO_DEVICE);
@@ -1444,7 +1344,6 @@ int ssi_buffer_mgr_map_aead_request(
rc = -ENOMEM;
goto aead_map_failure;
}
- SSI_UPDATE_DMA_ADDR_TO_48BIT(areq_ctx->gcm_block_len_dma_addr, AES_BLOCK_SIZE);
areq_ctx->gcm_iv_inc1_dma_addr = dma_map_single(dev,
areq_ctx->gcm_iv_inc1,
@@ -1458,8 +1357,6 @@ int ssi_buffer_mgr_map_aead_request(
rc = -ENOMEM;
goto aead_map_failure;
}
- SSI_UPDATE_DMA_ADDR_TO_48BIT(areq_ctx->gcm_iv_inc1_dma_addr,
- AES_BLOCK_SIZE);
areq_ctx->gcm_iv_inc2_dma_addr = dma_map_single(dev,
areq_ctx->gcm_iv_inc2,
@@ -1473,32 +1370,30 @@ int ssi_buffer_mgr_map_aead_request(
rc = -ENOMEM;
goto aead_map_failure;
}
- SSI_UPDATE_DMA_ADDR_TO_48BIT(areq_ctx->gcm_iv_inc2_dma_addr,
- AES_BLOCK_SIZE);
}
#endif /*SSI_CC_HAS_AES_GCM*/
size_to_map = req->cryptlen + req->assoclen;
- if (areq_ctx->gen_ctx.op_type == DRV_CRYPTO_DIRECTION_ENCRYPT) {
+ if (areq_ctx->gen_ctx.op_type == DRV_CRYPTO_DIRECTION_ENCRYPT)
size_to_map += authsize;
- }
+
if (is_gcm4543)
size_to_map += crypto_aead_ivsize(tfm);
rc = ssi_buffer_mgr_map_scatterlist(dev, req->src,
size_to_map, DMA_BIDIRECTIONAL, &(areq_ctx->src.nents),
- LLI_MAX_NUM_OF_ASSOC_DATA_ENTRIES+LLI_MAX_NUM_OF_DATA_ENTRIES, &dummy, &mapped_nents);
+ LLI_MAX_NUM_OF_ASSOC_DATA_ENTRIES + LLI_MAX_NUM_OF_DATA_ENTRIES, &dummy, &mapped_nents);
if (unlikely(rc != 0)) {
rc = -ENOMEM;
- goto aead_map_failure;
+ goto aead_map_failure;
}
- if (likely(areq_ctx->is_single_pass == true)) {
+ if (likely(areq_ctx->is_single_pass)) {
/*
- * Create MLLI table for:
- * (1) Assoc. data
- * (2) Src/Dst SGLs
- * Note: IV is contg. buffer (not an SGL)
- */
+ * Create MLLI table for:
+ * (1) Assoc. data
+ * (2) Src/Dst SGLs
+ * Note: IV is contg. buffer (not an SGL)
+ */
rc = ssi_buffer_mgr_aead_chain_assoc(drvdata, req, &sg_data, true, false);
if (unlikely(rc != 0))
goto aead_map_failure;
@@ -1510,25 +1405,25 @@ int ssi_buffer_mgr_map_aead_request(
goto aead_map_failure;
} else { /* DOUBLE-PASS flow */
/*
- * Prepare MLLI table(s) in this order:
- *
- * If ENCRYPT/DECRYPT (inplace):
- * (1) MLLI table for assoc
- * (2) IV entry (chained right after end of assoc)
- * (3) MLLI for src/dst (inplace operation)
- *
- * If ENCRYPT (non-inplace)
- * (1) MLLI table for assoc
- * (2) IV entry (chained right after end of assoc)
- * (3) MLLI for dst
- * (4) MLLI for src
- *
- * If DECRYPT (non-inplace)
- * (1) MLLI table for assoc
- * (2) IV entry (chained right after end of assoc)
- * (3) MLLI for src
- * (4) MLLI for dst
- */
+ * Prepare MLLI table(s) in this order:
+ *
+ * If ENCRYPT/DECRYPT (inplace):
+ * (1) MLLI table for assoc
+ * (2) IV entry (chained right after end of assoc)
+ * (3) MLLI for src/dst (inplace operation)
+ *
+ * If ENCRYPT (non-inplace)
+ * (1) MLLI table for assoc
+ * (2) IV entry (chained right after end of assoc)
+ * (3) MLLI for dst
+ * (4) MLLI for src
+ *
+ * If DECRYPT (non-inplace)
+ * (1) MLLI table for assoc
+ * (2) IV entry (chained right after end of assoc)
+ * (3) MLLI for src
+ * (4) MLLI for dst
+ */
rc = ssi_buffer_mgr_aead_chain_assoc(drvdata, req, &sg_data, false, true);
if (unlikely(rc != 0))
goto aead_map_failure;
@@ -1544,17 +1439,15 @@ int ssi_buffer_mgr_map_aead_request(
if (unlikely(
(areq_ctx->assoc_buff_type == SSI_DMA_BUF_MLLI) ||
(areq_ctx->data_buff_type == SSI_DMA_BUF_MLLI))) {
-
mlli_params->curr_pool = buff_mgr->mlli_buffs_pool;
rc = ssi_buffer_mgr_generate_mlli(dev, &sg_data, mlli_params);
- if (unlikely(rc != 0)) {
+ if (unlikely(rc != 0))
goto aead_map_failure;
- }
ssi_buffer_mgr_update_aead_mlli_nents(drvdata, req);
- SSI_LOG_DEBUG("assoc params mn %d\n",areq_ctx->assoc.mlli_nents);
- SSI_LOG_DEBUG("src params mn %d\n",areq_ctx->src.mlli_nents);
- SSI_LOG_DEBUG("dst params mn %d\n",areq_ctx->dst.mlli_nents);
+ SSI_LOG_DEBUG("assoc params mn %d\n", areq_ctx->assoc.mlli_nents);
+ SSI_LOG_DEBUG("src params mn %d\n", areq_ctx->src.mlli_nents);
+ SSI_LOG_DEBUG("dst params mn %d\n", areq_ctx->dst.mlli_nents);
}
return 0;
@@ -1568,15 +1461,15 @@ int ssi_buffer_mgr_map_hash_request_final(
{
struct ahash_req_ctx *areq_ctx = (struct ahash_req_ctx *)ctx;
struct device *dev = &drvdata->plat_dev->dev;
- uint8_t* curr_buff = areq_ctx->buff_index ? areq_ctx->buff1 :
+ u8 *curr_buff = areq_ctx->buff_index ? areq_ctx->buff1 :
areq_ctx->buff0;
- uint32_t *curr_buff_cnt = areq_ctx->buff_index ? &areq_ctx->buff1_cnt :
+ u32 *curr_buff_cnt = areq_ctx->buff_index ? &areq_ctx->buff1_cnt :
&areq_ctx->buff0_cnt;
- struct mlli_params *mlli_params = &areq_ctx->mlli_params;
+ struct mlli_params *mlli_params = &areq_ctx->mlli_params;
struct buffer_array sg_data;
struct buff_mgr_handle *buff_mgr = drvdata->buff_mgr_handle;
- uint32_t dummy = 0;
- uint32_t mapped_nents = 0;
+ u32 dummy = 0;
+ u32 mapped_nents = 0;
SSI_LOG_DEBUG(" final params : curr_buff=%pK "
"curr_buff_cnt=0x%X nbytes = 0x%X "
@@ -1593,10 +1486,10 @@ int ssi_buffer_mgr_map_hash_request_final(
/* nothing to do */
return 0;
}
-
+
/*TODO: copy data in case that buffer is enough for operation */
/* map the previous buffer */
- if (*curr_buff_cnt != 0 ) {
+ if (*curr_buff_cnt != 0) {
if (ssi_ahash_handle_curr_buf(dev, areq_ctx, curr_buff,
*curr_buff_cnt, &sg_data) != 0) {
return -ENOMEM;
@@ -1604,7 +1497,7 @@ int ssi_buffer_mgr_map_hash_request_final(
}
if (src && (nbytes > 0) && do_update) {
- if ( unlikely( ssi_buffer_mgr_map_scatterlist( dev,src,
+ if (unlikely(ssi_buffer_mgr_map_scatterlist(dev, src,
nbytes,
DMA_TO_DEVICE,
&areq_ctx->in_nents,
@@ -1612,9 +1505,9 @@ int ssi_buffer_mgr_map_hash_request_final(
&dummy, &mapped_nents))){
goto unmap_curr_buff;
}
- if ( src && (mapped_nents == 1)
- && (areq_ctx->data_dma_buf_type == SSI_DMA_BUF_NULL) ) {
- memcpy(areq_ctx->buff_sg,src,
+ if (src && (mapped_nents == 1)
+ && (areq_ctx->data_dma_buf_type == SSI_DMA_BUF_NULL)) {
+ memcpy(areq_ctx->buff_sg, src,
sizeof(struct scatterlist));
areq_ctx->buff_sg->length = nbytes;
areq_ctx->curr_sg = areq_ctx->buff_sg;
@@ -1622,7 +1515,6 @@ int ssi_buffer_mgr_map_hash_request_final(
} else {
areq_ctx->data_dma_buf_type = SSI_DMA_BUF_MLLI;
}
-
}
/*build mlli */
@@ -1640,7 +1532,7 @@ int ssi_buffer_mgr_map_hash_request_final(
}
}
/* change the buffer index for the unmap function */
- areq_ctx->buff_index = (areq_ctx->buff_index^1);
+ areq_ctx->buff_index = (areq_ctx->buff_index ^ 1);
SSI_LOG_DEBUG("areq_ctx->data_dma_buf_type = %s\n",
GET_DMA_BUFFER_TYPE(areq_ctx->data_dma_buf_type));
return 0;
@@ -1649,9 +1541,9 @@ fail_unmap_din:
dma_unmap_sg(dev, src, areq_ctx->in_nents, DMA_TO_DEVICE);
unmap_curr_buff:
- if (*curr_buff_cnt != 0 ) {
+ if (*curr_buff_cnt != 0)
dma_unmap_sg(dev, areq_ctx->buff_sg, 1, DMA_TO_DEVICE);
- }
+
return -ENOMEM;
}
@@ -1660,26 +1552,26 @@ int ssi_buffer_mgr_map_hash_request_update(
{
struct ahash_req_ctx *areq_ctx = (struct ahash_req_ctx *)ctx;
struct device *dev = &drvdata->plat_dev->dev;
- uint8_t* curr_buff = areq_ctx->buff_index ? areq_ctx->buff1 :
+ u8 *curr_buff = areq_ctx->buff_index ? areq_ctx->buff1 :
areq_ctx->buff0;
- uint32_t *curr_buff_cnt = areq_ctx->buff_index ? &areq_ctx->buff1_cnt :
+ u32 *curr_buff_cnt = areq_ctx->buff_index ? &areq_ctx->buff1_cnt :
&areq_ctx->buff0_cnt;
- uint8_t* next_buff = areq_ctx->buff_index ? areq_ctx->buff0 :
+ u8 *next_buff = areq_ctx->buff_index ? areq_ctx->buff0 :
areq_ctx->buff1;
- uint32_t *next_buff_cnt = areq_ctx->buff_index ? &areq_ctx->buff0_cnt :
+ u32 *next_buff_cnt = areq_ctx->buff_index ? &areq_ctx->buff0_cnt :
&areq_ctx->buff1_cnt;
- struct mlli_params *mlli_params = &areq_ctx->mlli_params;
+ struct mlli_params *mlli_params = &areq_ctx->mlli_params;
unsigned int update_data_len;
- uint32_t total_in_len = nbytes + *curr_buff_cnt;
+ u32 total_in_len = nbytes + *curr_buff_cnt;
struct buffer_array sg_data;
struct buff_mgr_handle *buff_mgr = drvdata->buff_mgr_handle;
unsigned int swap_index = 0;
- uint32_t dummy = 0;
- uint32_t mapped_nents = 0;
-
+ u32 dummy = 0;
+ u32 mapped_nents = 0;
+
SSI_LOG_DEBUG(" update params : curr_buff=%pK "
"curr_buff_cnt=0x%X nbytes=0x%X "
- "src=%pK curr_index=%u \n",
+ "src=%pK curr_index=%u\n",
curr_buff, *curr_buff_cnt, nbytes,
src, areq_ctx->buff_index);
/* Init the type of the dma buffer */
@@ -1694,12 +1586,12 @@ int ssi_buffer_mgr_map_hash_request_update(
"*curr_buff_cnt=0x%X copy_to=%pK\n",
curr_buff, *curr_buff_cnt,
&curr_buff[*curr_buff_cnt]);
- areq_ctx->in_nents =
+ areq_ctx->in_nents =
ssi_buffer_mgr_get_sgl_nents(src,
nbytes,
&dummy, NULL);
sg_copy_to_buffer(src, areq_ctx->in_nents,
- &curr_buff[*curr_buff_cnt], nbytes);
+ &curr_buff[*curr_buff_cnt], nbytes);
*curr_buff_cnt += nbytes;
return 1;
}
@@ -1716,12 +1608,12 @@ int ssi_buffer_mgr_map_hash_request_update(
/* Copy the new residue to next buffer */
if (*next_buff_cnt != 0) {
SSI_LOG_DEBUG(" handle residue: next buff %pK skip data %u"
- " residue %u \n", next_buff,
+ " residue %u\n", next_buff,
(update_data_len - *curr_buff_cnt),
*next_buff_cnt);
ssi_buffer_mgr_copy_scatterlist_portion(next_buff, src,
- (update_data_len -*curr_buff_cnt),
- nbytes,SSI_SG_TO_BUF);
+ (update_data_len - *curr_buff_cnt),
+ nbytes, SSI_SG_TO_BUF);
/* change the buffer index for next operation */
swap_index = 1;
}
@@ -1734,20 +1626,20 @@ int ssi_buffer_mgr_map_hash_request_update(
/* change the buffer index for next operation */
swap_index = 1;
}
-
- if ( update_data_len > *curr_buff_cnt ) {
- if ( unlikely( ssi_buffer_mgr_map_scatterlist( dev,src,
- (update_data_len -*curr_buff_cnt),
+
+ if (update_data_len > *curr_buff_cnt) {
+ if (unlikely(ssi_buffer_mgr_map_scatterlist(dev, src,
+ (update_data_len - *curr_buff_cnt),
DMA_TO_DEVICE,
&areq_ctx->in_nents,
LLI_MAX_NUM_OF_DATA_ENTRIES,
&dummy, &mapped_nents))){
goto unmap_curr_buff;
}
- if ( (mapped_nents == 1)
- && (areq_ctx->data_dma_buf_type == SSI_DMA_BUF_NULL) ) {
+ if ((mapped_nents == 1)
+ && (areq_ctx->data_dma_buf_type == SSI_DMA_BUF_NULL)) {
/* only one entry in the SG and no previous data */
- memcpy(areq_ctx->buff_sg,src,
+ memcpy(areq_ctx->buff_sg, src,
sizeof(struct scatterlist));
areq_ctx->buff_sg->length = update_data_len;
areq_ctx->data_dma_buf_type = SSI_DMA_BUF_DLLI;
@@ -1769,9 +1661,8 @@ int ssi_buffer_mgr_map_hash_request_update(
mlli_params) != 0)) {
goto fail_unmap_din;
}
-
}
- areq_ctx->buff_index = (areq_ctx->buff_index^swap_index);
+ areq_ctx->buff_index = (areq_ctx->buff_index ^ swap_index);
return 0;
@@ -1779,9 +1670,9 @@ fail_unmap_din:
dma_unmap_sg(dev, src, areq_ctx->in_nents, DMA_TO_DEVICE);
unmap_curr_buff:
- if (*curr_buff_cnt != 0 ) {
+ if (*curr_buff_cnt != 0)
dma_unmap_sg(dev, areq_ctx->buff_sg, 1, DMA_TO_DEVICE);
- }
+
return -ENOMEM;
}
@@ -1789,36 +1680,35 @@ void ssi_buffer_mgr_unmap_hash_request(
struct device *dev, void *ctx, struct scatterlist *src, bool do_revert)
{
struct ahash_req_ctx *areq_ctx = (struct ahash_req_ctx *)ctx;
- uint32_t *prev_len = areq_ctx->buff_index ? &areq_ctx->buff0_cnt :
+ u32 *prev_len = areq_ctx->buff_index ? &areq_ctx->buff0_cnt :
&areq_ctx->buff1_cnt;
- /*In case a pool was set, a table was
- allocated and should be released */
- if (areq_ctx->mlli_params.curr_pool != NULL) {
- SSI_LOG_DEBUG("free MLLI buffer: dma=0x%llX virt=%pK\n",
+ /*In case a pool was set, a table was
+ *allocated and should be released
+ */
+ if (areq_ctx->mlli_params.curr_pool) {
+ SSI_LOG_DEBUG("free MLLI buffer: dma=0x%llX virt=%pK\n",
(unsigned long long)areq_ctx->mlli_params.mlli_dma_addr,
areq_ctx->mlli_params.mlli_virt_addr);
- SSI_RESTORE_DMA_ADDR_TO_48BIT(areq_ctx->mlli_params.mlli_dma_addr);
dma_pool_free(areq_ctx->mlli_params.curr_pool,
areq_ctx->mlli_params.mlli_virt_addr,
areq_ctx->mlli_params.mlli_dma_addr);
}
-
+
if ((src) && likely(areq_ctx->in_nents != 0)) {
SSI_LOG_DEBUG("Unmapped sg src: virt=%pK dma=0x%llX len=0x%X\n",
sg_virt(src),
- (unsigned long long)sg_dma_address(src),
+ (unsigned long long)sg_dma_address(src),
sg_dma_len(src));
- SSI_RESTORE_DMA_ADDR_TO_48BIT(sg_dma_address(src));
- dma_unmap_sg(dev, src,
+ dma_unmap_sg(dev, src,
areq_ctx->in_nents, DMA_TO_DEVICE);
}
if (*prev_len != 0) {
SSI_LOG_DEBUG("Unmapped buffer: areq_ctx->buff_sg=%pK"
- "dma=0x%llX len 0x%X\n",
+ " dma=0x%llX len 0x%X\n",
sg_virt(areq_ctx->buff_sg),
- (unsigned long long)sg_dma_address(areq_ctx->buff_sg),
+ (unsigned long long)sg_dma_address(areq_ctx->buff_sg),
sg_dma_len(areq_ctx->buff_sg));
dma_unmap_sg(dev, areq_ctx->buff_sg, 1, DMA_TO_DEVICE);
if (!do_revert) {
@@ -1837,18 +1727,18 @@ int ssi_buffer_mgr_init(struct ssi_drvdata *drvdata)
buff_mgr_handle = (struct buff_mgr_handle *)
kmalloc(sizeof(struct buff_mgr_handle), GFP_KERNEL);
- if (buff_mgr_handle == NULL)
+ if (!buff_mgr_handle)
return -ENOMEM;
drvdata->buff_mgr_handle = buff_mgr_handle;
buff_mgr_handle->mlli_buffs_pool = dma_pool_create(
"dx_single_mlli_tables", dev,
- MAX_NUM_OF_TOTAL_MLLI_ENTRIES *
+ MAX_NUM_OF_TOTAL_MLLI_ENTRIES *
LLI_ENTRY_BYTE_SIZE,
MLLI_TABLE_MIN_ALIGNMENT, 0);
- if (unlikely(buff_mgr_handle->mlli_buffs_pool == NULL))
+ if (unlikely(!buff_mgr_handle->mlli_buffs_pool))
goto error;
return 0;
@@ -1862,12 +1752,10 @@ int ssi_buffer_mgr_fini(struct ssi_drvdata *drvdata)
{
struct buff_mgr_handle *buff_mgr_handle = drvdata->buff_mgr_handle;
- if (buff_mgr_handle != NULL) {
+ if (buff_mgr_handle) {
dma_pool_destroy(buff_mgr_handle->mlli_buffs_pool);
kfree(drvdata->buff_mgr_handle);
drvdata->buff_mgr_handle = NULL;
-
}
return 0;
}
-
diff --git a/drivers/staging/ccree/ssi_buffer_mgr.h b/drivers/staging/ccree/ssi_buffer_mgr.h
index 5f4b032389f1..41f5223730f8 100644
--- a/drivers/staging/ccree/ssi_buffer_mgr.h
+++ b/drivers/staging/ccree/ssi_buffer_mgr.h
@@ -1,21 +1,21 @@
/*
* Copyright (C) 2012-2017 ARM Limited or its affiliates.
- *
+ *
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
- *
+ *
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
- *
+ *
* You should have received a copy of the GNU General Public License
* along with this program; if not, see <http://www.gnu.org/licenses/>.
*/
/* \file buffer_mgr.h
- Buffer Manager
+ * Buffer Manager
*/
#ifndef __SSI_BUFFER_MGR_H__
@@ -26,7 +26,6 @@
#include "ssi_config.h"
#include "ssi_driver.h"
-
enum ssi_req_dma_buf_type {
SSI_DMA_BUF_NULL = 0,
SSI_DMA_BUF_DLLI,
@@ -46,9 +45,9 @@ struct ssi_mlli {
struct mlli_params {
struct dma_pool *curr_pool;
- uint8_t *mlli_virt_addr;
+ u8 *mlli_virt_addr;
dma_addr_t mlli_dma_addr;
- uint32_t mlli_len;
+ u32 mlli_len;
};
int ssi_buffer_mgr_init(struct ssi_drvdata *drvdata);
@@ -65,7 +64,7 @@ int ssi_buffer_mgr_map_blkcipher_request(
struct scatterlist *dst);
void ssi_buffer_mgr_unmap_blkcipher_request(
- struct device *dev,
+ struct device *dev,
void *ctx,
unsigned int ivsize,
struct scatterlist *src,
@@ -81,25 +80,9 @@ int ssi_buffer_mgr_map_hash_request_update(struct ssi_drvdata *drvdata, void *ct
void ssi_buffer_mgr_unmap_hash_request(struct device *dev, void *ctx, struct scatterlist *src, bool do_revert);
-void ssi_buffer_mgr_copy_scatterlist_portion(u8 *dest, struct scatterlist *sg, uint32_t to_skip, uint32_t end, enum ssi_sg_cpy_direct direct);
-
-void ssi_buffer_mgr_zero_sgl(struct scatterlist *sgl, uint32_t data_len);
-
-
-#ifdef CC_DMA_48BIT_SIM
-dma_addr_t ssi_buff_mgr_update_dma_addr(dma_addr_t orig_addr, uint32_t data_len);
-dma_addr_t ssi_buff_mgr_restore_dma_addr(dma_addr_t orig_addr);
-
-#define SSI_UPDATE_DMA_ADDR_TO_48BIT(addr,size) addr = \
- ssi_buff_mgr_update_dma_addr(addr,size)
-#define SSI_RESTORE_DMA_ADDR_TO_48BIT(addr) addr = \
- ssi_buff_mgr_restore_dma_addr(addr)
-#else
-
-#define SSI_UPDATE_DMA_ADDR_TO_48BIT(addr,size) addr = addr
-#define SSI_RESTORE_DMA_ADDR_TO_48BIT(addr) addr = addr
+void ssi_buffer_mgr_copy_scatterlist_portion(u8 *dest, struct scatterlist *sg, u32 to_skip, u32 end, enum ssi_sg_cpy_direct direct);
-#endif
+void ssi_buffer_mgr_zero_sgl(struct scatterlist *sgl, u32 data_len);
#endif /*__BUFFER_MGR_H__*/
diff --git a/drivers/staging/ccree/ssi_cipher.c b/drivers/staging/ccree/ssi_cipher.c
index 664ed7e52cf2..cd2eafc04232 100644
--- a/drivers/staging/ccree/ssi_cipher.c
+++ b/drivers/staging/ccree/ssi_cipher.c
@@ -1,15 +1,15 @@
/*
* Copyright (C) 2012-2017 ARM Limited or its affiliates.
- *
+ *
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
- *
+ *
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
- *
+ *
* You should have received a copy of the GNU General Public License
* along with this program; if not, see <http://www.gnu.org/licenses/>.
*/
@@ -36,7 +36,6 @@
#define MAX_ABLKCIPHER_SEQ_LEN 6
#define template_ablkcipher template_u.ablkcipher
-#define template_sblkcipher template_u.blkcipher
#define SSI_MIN_AES_XTS_SIZE 0x10
#define SSI_MAX_AES_XTS_SIZE 0x2000
@@ -45,12 +44,13 @@ struct ssi_blkcipher_handle {
};
struct cc_user_key_info {
- uint8_t *key;
+ u8 *key;
dma_addr_t key_dma_addr;
};
+
struct cc_hw_key_info {
- enum HwCryptoKey key1_slot;
- enum HwCryptoKey key2_slot;
+ enum cc_hw_crypto_key key1_slot;
+ enum cc_hw_crypto_key key2_slot;
};
struct ssi_ablkcipher_ctx {
@@ -68,11 +68,10 @@ struct ssi_ablkcipher_ctx {
static void ssi_ablkcipher_complete(struct device *dev, void *ssi_req, void __iomem *cc_base);
-
-static int validate_keys_sizes(struct ssi_ablkcipher_ctx *ctx_p, uint32_t size) {
- switch (ctx_p->flow_mode){
+static int validate_keys_sizes(struct ssi_ablkcipher_ctx *ctx_p, u32 size) {
+ switch (ctx_p->flow_mode) {
case S_DIN_to_AES:
- switch (size){
+ switch (size) {
case CC_AES_128_BIT_KEY_SIZE:
case CC_AES_192_BIT_KEY_SIZE:
if (likely((ctx_p->cipher_mode != DRV_CIPHER_XTS) &&
@@ -82,8 +81,8 @@ static int validate_keys_sizes(struct ssi_ablkcipher_ctx *ctx_p, uint32_t size)
break;
case CC_AES_256_BIT_KEY_SIZE:
return 0;
- case (CC_AES_192_BIT_KEY_SIZE*2):
- case (CC_AES_256_BIT_KEY_SIZE*2):
+ case (CC_AES_192_BIT_KEY_SIZE * 2):
+ case (CC_AES_256_BIT_KEY_SIZE * 2):
if (likely((ctx_p->cipher_mode == DRV_CIPHER_XTS) ||
(ctx_p->cipher_mode == DRV_CIPHER_ESSIV) ||
(ctx_p->cipher_mode == DRV_CIPHER_BITLOCKER)))
@@ -105,19 +104,17 @@ static int validate_keys_sizes(struct ssi_ablkcipher_ctx *ctx_p, uint32_t size)
#endif
default:
break;
-
}
return -EINVAL;
}
-
static int validate_data_size(struct ssi_ablkcipher_ctx *ctx_p, unsigned int size) {
- switch (ctx_p->flow_mode){
+ switch (ctx_p->flow_mode) {
case S_DIN_to_AES:
- switch (ctx_p->cipher_mode){
+ switch (ctx_p->cipher_mode) {
case DRV_CIPHER_XTS:
if ((size >= SSI_MIN_AES_XTS_SIZE) &&
- (size <= SSI_MAX_AES_XTS_SIZE) &&
+ (size <= SSI_MAX_AES_XTS_SIZE) &&
IS_ALIGNED(size, AES_BLOCK_SIZE))
return 0;
break;
@@ -159,7 +156,6 @@ static int validate_data_size(struct ssi_ablkcipher_ctx *ctx_p, unsigned int siz
#endif /*SSI_CC_HAS_MULTI2*/
default:
break;
-
}
return -EINVAL;
}
@@ -168,13 +164,11 @@ static unsigned int get_max_keysize(struct crypto_tfm *tfm)
{
struct ssi_crypto_alg *ssi_alg = container_of(tfm->__crt_alg, struct ssi_crypto_alg, crypto_alg);
- if ((ssi_alg->crypto_alg.cra_flags & CRYPTO_ALG_TYPE_MASK) == CRYPTO_ALG_TYPE_ABLKCIPHER) {
+ if ((ssi_alg->crypto_alg.cra_flags & CRYPTO_ALG_TYPE_MASK) == CRYPTO_ALG_TYPE_ABLKCIPHER)
return ssi_alg->crypto_alg.cra_ablkcipher.max_keysize;
- }
- if ((ssi_alg->crypto_alg.cra_flags & CRYPTO_ALG_TYPE_MASK) == CRYPTO_ALG_TYPE_BLKCIPHER) {
+ if ((ssi_alg->crypto_alg.cra_flags & CRYPTO_ALG_TYPE_MASK) == CRYPTO_ALG_TYPE_BLKCIPHER)
return ssi_alg->crypto_alg.cra_blkcipher.max_keysize;
- }
return 0;
}
@@ -189,7 +183,7 @@ static int ssi_blkcipher_init(struct crypto_tfm *tfm)
int rc = 0;
unsigned int max_key_buf_size = get_max_keysize(tfm);
- SSI_LOG_DEBUG("Initializing context @%p for %s\n", ctx_p,
+ SSI_LOG_DEBUG("Initializing context @%p for %s\n", ctx_p,
crypto_tfm_alg_name(tfm));
CHECK_AND_RETURN_UPON_FIPS_ERROR();
@@ -199,7 +193,7 @@ static int ssi_blkcipher_init(struct crypto_tfm *tfm)
dev = &ctx_p->drvdata->plat_dev->dev;
/* Allocate key buffer, cache line aligned */
- ctx_p->user.key = kmalloc(max_key_buf_size, GFP_KERNEL|GFP_DMA);
+ ctx_p->user.key = kmalloc(max_key_buf_size, GFP_KERNEL | GFP_DMA);
if (!ctx_p->user.key) {
SSI_LOG_ERR("Allocating key buffer in context failed\n");
rc = -ENOMEM;
@@ -215,7 +209,6 @@ static int ssi_blkcipher_init(struct crypto_tfm *tfm)
max_key_buf_size, ctx_p->user.key);
return -ENOMEM;
}
- SSI_UPDATE_DMA_ADDR_TO_48BIT(ctx_p->user.key_dma_addr, max_key_buf_size);
SSI_LOG_DEBUG("Mapped key %u B at va=%pK to dma=0x%llX\n",
max_key_buf_size, ctx_p->user.key,
(unsigned long long)ctx_p->user.key_dma_addr);
@@ -248,10 +241,9 @@ static void ssi_blkcipher_exit(struct crypto_tfm *tfm)
}
/* Unmap key buffer */
- SSI_RESTORE_DMA_ADDR_TO_48BIT(ctx_p->user.key_dma_addr);
dma_unmap_single(dev, ctx_p->user.key_dma_addr, max_key_buf_size,
DMA_TO_DEVICE);
- SSI_LOG_DEBUG("Unmapped key buffer key_dma_addr=0x%llX\n",
+ SSI_LOG_DEBUG("Unmapped key buffer key_dma_addr=0x%llX\n",
(unsigned long long)ctx_p->user.key_dma_addr);
/* Free key buffer in context */
@@ -259,50 +251,48 @@ static void ssi_blkcipher_exit(struct crypto_tfm *tfm)
SSI_LOG_DEBUG("Free key buffer in context. key=@%p\n", ctx_p->user.key);
}
+struct tdes_keys {
+ u8 key1[DES_KEY_SIZE];
+ u8 key2[DES_KEY_SIZE];
+ u8 key3[DES_KEY_SIZE];
+};
-typedef struct tdes_keys{
- u8 key1[DES_KEY_SIZE];
- u8 key2[DES_KEY_SIZE];
- u8 key3[DES_KEY_SIZE];
-}tdes_keys_t;
-
-static const u8 zero_buff[] = {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
- 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
- 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
- 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0};
+static const u8 zero_buff[] = { 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0};
/* The function verifies that tdes keys are not weak.*/
static int ssi_fips_verify_3des_keys(const u8 *key, unsigned int keylen)
{
#ifdef CCREE_FIPS_SUPPORT
- tdes_keys_t *tdes_key = (tdes_keys_t*)key;
+ struct tdes_keys *tdes_key = (struct tdes_keys *)key;
/* verify key1 != key2 and key3 != key2*/
- if (unlikely( (memcmp((u8*)tdes_key->key1, (u8*)tdes_key->key2, sizeof(tdes_key->key1)) == 0) ||
- (memcmp((u8*)tdes_key->key3, (u8*)tdes_key->key2, sizeof(tdes_key->key3)) == 0) )) {
- return -ENOEXEC;
- }
+ if (unlikely((memcmp((u8 *)tdes_key->key1, (u8 *)tdes_key->key2, sizeof(tdes_key->key1)) == 0) ||
+ (memcmp((u8 *)tdes_key->key3, (u8 *)tdes_key->key2, sizeof(tdes_key->key3)) == 0))) {
+ return -ENOEXEC;
+ }
#endif /* CCREE_FIPS_SUPPORT */
- return 0;
+ return 0;
}
/* The function verifies that xts keys are not weak.*/
static int ssi_fips_verify_xts_keys(const u8 *key, unsigned int keylen)
{
#ifdef CCREE_FIPS_SUPPORT
- /* Weak key is define as key that its first half (128/256 lsb) equals its second half (128/256 msb) */
- int singleKeySize = keylen >> 1;
+ /* Weak key is define as key that its first half (128/256 lsb) equals its second half (128/256 msb) */
+ int singleKeySize = keylen >> 1;
- if (unlikely(memcmp(key, &key[singleKeySize], singleKeySize) == 0)) {
+ if (unlikely(memcmp(key, &key[singleKeySize], singleKeySize) == 0))
return -ENOEXEC;
- }
#endif /* CCREE_FIPS_SUPPORT */
- return 0;
+ return 0;
}
-static enum HwCryptoKey hw_key_to_cc_hw_key(int slot_num)
+static enum cc_hw_crypto_key hw_key_to_cc_hw_key(int slot_num)
{
switch (slot_num) {
case 0:
@@ -317,35 +307,32 @@ static enum HwCryptoKey hw_key_to_cc_hw_key(int slot_num)
return END_OF_KEYS;
}
-static int ssi_blkcipher_setkey(struct crypto_tfm *tfm,
- const u8 *key,
+static int ssi_blkcipher_setkey(struct crypto_tfm *tfm,
+ const u8 *key,
unsigned int keylen)
{
struct ssi_ablkcipher_ctx *ctx_p = crypto_tfm_ctx(tfm);
struct device *dev = &ctx_p->drvdata->plat_dev->dev;
u32 tmp[DES_EXPKEY_WORDS];
unsigned int max_key_buf_size = get_max_keysize(tfm);
- DECL_CYCLE_COUNT_RESOURCES;
SSI_LOG_DEBUG("Setting key in context @%p for %s. keylen=%u\n",
ctx_p, crypto_tfm_alg_name(tfm), keylen);
- dump_byte_array("key", (uint8_t *)key, keylen);
+ dump_byte_array("key", (u8 *)key, keylen);
CHECK_AND_RETURN_UPON_FIPS_ERROR();
SSI_LOG_DEBUG("ssi_blkcipher_setkey: after FIPS check");
-
+
/* STAT_PHASE_0: Init and sanity checks */
- START_CYCLE_COUNT();
#if SSI_CC_HAS_MULTI2
/*last byte of key buffer is round number and should not be a part of key size*/
- if (ctx_p->flow_mode == S_DIN_to_MULTI2) {
- keylen -=1;
- }
+ if (ctx_p->flow_mode == S_DIN_to_MULTI2)
+ keylen -= 1;
#endif /*SSI_CC_HAS_MULTI2*/
- if (unlikely(validate_keys_sizes(ctx_p,keylen) != 0)) {
+ if (unlikely(validate_keys_sizes(ctx_p, keylen) != 0)) {
SSI_LOG_ERR("Unsupported key size %d.\n", keylen);
crypto_tfm_set_flags(tfm, CRYPTO_TFM_RES_BAD_KEY_LEN);
return -EINVAL;
@@ -353,7 +340,7 @@ static int ssi_blkcipher_setkey(struct crypto_tfm *tfm,
if (ssi_is_hw_key(tfm)) {
/* setting HW key slots */
- struct arm_hw_key_info *hki = (struct arm_hw_key_info*)key;
+ struct arm_hw_key_info *hki = (struct arm_hw_key_info *)key;
if (unlikely(ctx_p->flow_mode != S_DIN_to_AES)) {
SSI_LOG_ERR("HW key not supported for non-AES flows\n");
@@ -381,7 +368,6 @@ static int ssi_blkcipher_setkey(struct crypto_tfm *tfm,
}
ctx_p->keylen = keylen;
- END_CYCLE_COUNT(STAT_OP_TYPE_SETKEY, STAT_PHASE_0);
SSI_LOG_DEBUG("ssi_blkcipher_setkey: ssi_is_hw_key ret 0");
return 0;
@@ -396,28 +382,24 @@ static int ssi_blkcipher_setkey(struct crypto_tfm *tfm,
return -EINVAL;
}
}
- if ((ctx_p->cipher_mode == DRV_CIPHER_XTS) &&
+ if ((ctx_p->cipher_mode == DRV_CIPHER_XTS) &&
ssi_fips_verify_xts_keys(key, keylen) != 0) {
SSI_LOG_DEBUG("ssi_blkcipher_setkey: weak XTS key");
return -EINVAL;
}
- if ((ctx_p->flow_mode == S_DIN_to_DES) &&
- (keylen == DES3_EDE_KEY_SIZE) &&
+ if ((ctx_p->flow_mode == S_DIN_to_DES) &&
+ (keylen == DES3_EDE_KEY_SIZE) &&
ssi_fips_verify_3des_keys(key, keylen) != 0) {
SSI_LOG_DEBUG("ssi_blkcipher_setkey: weak 3DES key");
return -EINVAL;
}
-
- END_CYCLE_COUNT(STAT_OP_TYPE_SETKEY, STAT_PHASE_0);
-
/* STAT_PHASE_1: Copy key to ctx */
- START_CYCLE_COUNT();
- SSI_RESTORE_DMA_ADDR_TO_48BIT(ctx_p->user.key_dma_addr);
- dma_sync_single_for_cpu(dev, ctx_p->user.key_dma_addr,
+ dma_sync_single_for_cpu(dev, ctx_p->user.key_dma_addr,
max_key_buf_size, DMA_TO_DEVICE);
-#if SSI_CC_HAS_MULTI2
+
if (ctx_p->flow_mode == S_DIN_to_MULTI2) {
+#if SSI_CC_HAS_MULTI2
memcpy(ctx_p->user.key, key, CC_MULTI2_SYSTEM_N_DATA_KEY_SIZE);
ctx_p->key_round_number = key[CC_MULTI2_SYSTEM_N_DATA_KEY_SIZE];
if (ctx_p->key_round_number < CC_MULTI2_MIN_NUM_ROUNDS ||
@@ -425,10 +407,8 @@ static int ssi_blkcipher_setkey(struct crypto_tfm *tfm,
crypto_tfm_set_flags(tfm, CRYPTO_TFM_RES_BAD_KEY_LEN);
SSI_LOG_DEBUG("ssi_blkcipher_setkey: SSI_CC_HAS_MULTI2 einval");
return -EINVAL;
- }
- } else
#endif /*SSI_CC_HAS_MULTI2*/
- {
+ } else {
memcpy(ctx_p->user.key, key, keylen);
if (keylen == 24)
memset(ctx_p->user.key + 24, 0, CC_AES_KEY_SIZE_MAX - 24);
@@ -438,6 +418,7 @@ static int ssi_blkcipher_setkey(struct crypto_tfm *tfm,
int key_len = keylen >> 1;
int err;
SHASH_DESC_ON_STACK(desc, ctx_p->shash_tfm);
+
desc->tfm = ctx_p->shash_tfm;
err = crypto_shash_digest(desc, ctx_p->user.key, key_len, ctx_p->user.key + key_len);
@@ -447,12 +428,9 @@ static int ssi_blkcipher_setkey(struct crypto_tfm *tfm,
}
}
}
- dma_sync_single_for_device(dev, ctx_p->user.key_dma_addr,
+ dma_sync_single_for_device(dev, ctx_p->user.key_dma_addr,
max_key_buf_size, DMA_TO_DEVICE);
- SSI_UPDATE_DMA_ADDR_TO_48BIT(ctx_p->user.key_dma_addr ,max_key_buf_size);
ctx_p->keylen = keylen;
-
- END_CYCLE_COUNT(STAT_OP_TYPE_SETKEY, STAT_PHASE_1);
SSI_LOG_DEBUG("ssi_blkcipher_setkey: return safely");
return 0;
@@ -464,7 +442,7 @@ ssi_blkcipher_create_setup_desc(
struct blkcipher_req_ctx *req_ctx,
unsigned int ivsize,
unsigned int nbytes,
- HwDesc_s desc[],
+ struct cc_hw_desc desc[],
unsigned int *seq_size)
{
struct ssi_ablkcipher_ctx *ctx_p = crypto_tfm_ctx(tfm);
@@ -489,96 +467,92 @@ ssi_blkcipher_create_setup_desc(
case DRV_CIPHER_CTR:
case DRV_CIPHER_OFB:
/* Load cipher state */
- HW_DESC_INIT(&desc[*seq_size]);
- HW_DESC_SET_DIN_TYPE(&desc[*seq_size], DMA_DLLI,
- iv_dma_addr, ivsize,
- NS_BIT);
- HW_DESC_SET_CIPHER_CONFIG0(&desc[*seq_size], direction);
- HW_DESC_SET_FLOW_MODE(&desc[*seq_size], flow_mode);
- HW_DESC_SET_CIPHER_MODE(&desc[*seq_size], cipher_mode);
- if ((cipher_mode == DRV_CIPHER_CTR) ||
- (cipher_mode == DRV_CIPHER_OFB) ) {
- HW_DESC_SET_SETUP_MODE(&desc[*seq_size],
- SETUP_LOAD_STATE1);
+ hw_desc_init(&desc[*seq_size]);
+ set_din_type(&desc[*seq_size], DMA_DLLI, iv_dma_addr, ivsize,
+ NS_BIT);
+ set_cipher_config0(&desc[*seq_size], direction);
+ set_flow_mode(&desc[*seq_size], flow_mode);
+ set_cipher_mode(&desc[*seq_size], cipher_mode);
+ if ((cipher_mode == DRV_CIPHER_CTR) ||
+ (cipher_mode == DRV_CIPHER_OFB)) {
+ set_setup_mode(&desc[*seq_size], SETUP_LOAD_STATE1);
} else {
- HW_DESC_SET_SETUP_MODE(&desc[*seq_size],
- SETUP_LOAD_STATE0);
+ set_setup_mode(&desc[*seq_size], SETUP_LOAD_STATE0);
}
(*seq_size)++;
/*FALLTHROUGH*/
case DRV_CIPHER_ECB:
/* Load key */
- HW_DESC_INIT(&desc[*seq_size]);
- HW_DESC_SET_CIPHER_MODE(&desc[*seq_size], cipher_mode);
- HW_DESC_SET_CIPHER_CONFIG0(&desc[*seq_size], direction);
+ hw_desc_init(&desc[*seq_size]);
+ set_cipher_mode(&desc[*seq_size], cipher_mode);
+ set_cipher_config0(&desc[*seq_size], direction);
if (flow_mode == S_DIN_to_AES) {
-
if (ssi_is_hw_key(tfm)) {
- HW_DESC_SET_HW_CRYPTO_KEY(&desc[*seq_size], ctx_p->hw.key1_slot);
+ set_hw_crypto_key(&desc[*seq_size],
+ ctx_p->hw.key1_slot);
} else {
- HW_DESC_SET_DIN_TYPE(&desc[*seq_size], DMA_DLLI,
- key_dma_addr,
- ((key_len == 24) ? AES_MAX_KEY_SIZE : key_len),
- NS_BIT);
+ set_din_type(&desc[*seq_size], DMA_DLLI,
+ key_dma_addr, ((key_len == 24) ?
+ AES_MAX_KEY_SIZE :
+ key_len), NS_BIT);
}
- HW_DESC_SET_KEY_SIZE_AES(&desc[*seq_size], key_len);
+ set_key_size_aes(&desc[*seq_size], key_len);
} else {
/*des*/
- HW_DESC_SET_DIN_TYPE(&desc[*seq_size], DMA_DLLI,
- key_dma_addr, key_len,
- NS_BIT);
- HW_DESC_SET_KEY_SIZE_DES(&desc[*seq_size], key_len);
+ set_din_type(&desc[*seq_size], DMA_DLLI, key_dma_addr,
+ key_len, NS_BIT);
+ set_key_size_des(&desc[*seq_size], key_len);
}
- HW_DESC_SET_FLOW_MODE(&desc[*seq_size], flow_mode);
- HW_DESC_SET_SETUP_MODE(&desc[*seq_size], SETUP_LOAD_KEY0);
+ set_flow_mode(&desc[*seq_size], flow_mode);
+ set_setup_mode(&desc[*seq_size], SETUP_LOAD_KEY0);
(*seq_size)++;
break;
case DRV_CIPHER_XTS:
case DRV_CIPHER_ESSIV:
case DRV_CIPHER_BITLOCKER:
/* Load AES key */
- HW_DESC_INIT(&desc[*seq_size]);
- HW_DESC_SET_CIPHER_MODE(&desc[*seq_size], cipher_mode);
- HW_DESC_SET_CIPHER_CONFIG0(&desc[*seq_size], direction);
+ hw_desc_init(&desc[*seq_size]);
+ set_cipher_mode(&desc[*seq_size], cipher_mode);
+ set_cipher_config0(&desc[*seq_size], direction);
if (ssi_is_hw_key(tfm)) {
- HW_DESC_SET_HW_CRYPTO_KEY(&desc[*seq_size], ctx_p->hw.key1_slot);
+ set_hw_crypto_key(&desc[*seq_size],
+ ctx_p->hw.key1_slot);
} else {
- HW_DESC_SET_DIN_TYPE(&desc[*seq_size], DMA_DLLI,
- key_dma_addr, key_len/2,
- NS_BIT);
+ set_din_type(&desc[*seq_size], DMA_DLLI, key_dma_addr,
+ (key_len / 2), NS_BIT);
}
- HW_DESC_SET_KEY_SIZE_AES(&desc[*seq_size], key_len/2);
- HW_DESC_SET_FLOW_MODE(&desc[*seq_size], flow_mode);
- HW_DESC_SET_SETUP_MODE(&desc[*seq_size], SETUP_LOAD_KEY0);
+ set_key_size_aes(&desc[*seq_size], (key_len / 2));
+ set_flow_mode(&desc[*seq_size], flow_mode);
+ set_setup_mode(&desc[*seq_size], SETUP_LOAD_KEY0);
(*seq_size)++;
/* load XEX key */
- HW_DESC_INIT(&desc[*seq_size]);
- HW_DESC_SET_CIPHER_MODE(&desc[*seq_size], cipher_mode);
- HW_DESC_SET_CIPHER_CONFIG0(&desc[*seq_size], direction);
+ hw_desc_init(&desc[*seq_size]);
+ set_cipher_mode(&desc[*seq_size], cipher_mode);
+ set_cipher_config0(&desc[*seq_size], direction);
if (ssi_is_hw_key(tfm)) {
- HW_DESC_SET_HW_CRYPTO_KEY(&desc[*seq_size], ctx_p->hw.key2_slot);
+ set_hw_crypto_key(&desc[*seq_size],
+ ctx_p->hw.key2_slot);
} else {
- HW_DESC_SET_DIN_TYPE(&desc[*seq_size], DMA_DLLI,
- (key_dma_addr+key_len/2), key_len/2,
- NS_BIT);
+ set_din_type(&desc[*seq_size], DMA_DLLI,
+ (key_dma_addr + (key_len / 2)),
+ (key_len / 2), NS_BIT);
}
- HW_DESC_SET_XEX_DATA_UNIT_SIZE(&desc[*seq_size], du_size);
- HW_DESC_SET_FLOW_MODE(&desc[*seq_size], S_DIN_to_AES2);
- HW_DESC_SET_KEY_SIZE_AES(&desc[*seq_size], key_len/2);
- HW_DESC_SET_SETUP_MODE(&desc[*seq_size], SETUP_LOAD_XEX_KEY);
+ set_xex_data_unit_size(&desc[*seq_size], du_size);
+ set_flow_mode(&desc[*seq_size], S_DIN_to_AES2);
+ set_key_size_aes(&desc[*seq_size], (key_len / 2));
+ set_setup_mode(&desc[*seq_size], SETUP_LOAD_XEX_KEY);
(*seq_size)++;
-
+
/* Set state */
- HW_DESC_INIT(&desc[*seq_size]);
- HW_DESC_SET_SETUP_MODE(&desc[*seq_size], SETUP_LOAD_STATE1);
- HW_DESC_SET_CIPHER_MODE(&desc[*seq_size], cipher_mode);
- HW_DESC_SET_CIPHER_CONFIG0(&desc[*seq_size], direction);
- HW_DESC_SET_KEY_SIZE_AES(&desc[*seq_size], key_len/2);
- HW_DESC_SET_FLOW_MODE(&desc[*seq_size], flow_mode);
- HW_DESC_SET_DIN_TYPE(&desc[*seq_size], DMA_DLLI,
- iv_dma_addr, CC_AES_BLOCK_SIZE,
- NS_BIT);
+ hw_desc_init(&desc[*seq_size]);
+ set_setup_mode(&desc[*seq_size], SETUP_LOAD_STATE1);
+ set_cipher_mode(&desc[*seq_size], cipher_mode);
+ set_cipher_config0(&desc[*seq_size], direction);
+ set_key_size_aes(&desc[*seq_size], (key_len / 2));
+ set_flow_mode(&desc[*seq_size], flow_mode);
+ set_din_type(&desc[*seq_size], DMA_DLLI, iv_dma_addr,
+ CC_AES_BLOCK_SIZE, NS_BIT);
(*seq_size)++;
break;
default:
@@ -592,49 +566,43 @@ static inline void ssi_blkcipher_create_multi2_setup_desc(
struct crypto_tfm *tfm,
struct blkcipher_req_ctx *req_ctx,
unsigned int ivsize,
- HwDesc_s desc[],
+ struct cc_hw_desc desc[],
unsigned int *seq_size)
{
struct ssi_ablkcipher_ctx *ctx_p = crypto_tfm_ctx(tfm);
-
+
int direction = req_ctx->gen_ctx.op_type;
/* Load system key */
- HW_DESC_INIT(&desc[*seq_size]);
- HW_DESC_SET_CIPHER_MODE(&desc[*seq_size], ctx_p->cipher_mode);
- HW_DESC_SET_CIPHER_CONFIG0(&desc[*seq_size], direction);
- HW_DESC_SET_DIN_TYPE(&desc[*seq_size], DMA_DLLI, ctx_p->user.key_dma_addr,
- CC_MULTI2_SYSTEM_KEY_SIZE,
- NS_BIT);
- HW_DESC_SET_FLOW_MODE(&desc[*seq_size], ctx_p->flow_mode);
- HW_DESC_SET_SETUP_MODE(&desc[*seq_size], SETUP_LOAD_KEY0);
+ hw_desc_init(&desc[*seq_size]);
+ set_cipher_mode(&desc[*seq_size], ctx_p->cipher_mode);
+ set_cipher_config0(&desc[*seq_size], direction);
+ set_din_type(&desc[*seq_size], DMA_DLLI, ctx_p->user.key_dma_addr,
+ CC_MULTI2_SYSTEM_KEY_SIZE, NS_BIT);
+ set_flow_mode(&desc[*seq_size], ctx_p->flow_mode);
+ set_setup_mode(&desc[*seq_size], SETUP_LOAD_KEY0);
(*seq_size)++;
/* load data key */
- HW_DESC_INIT(&desc[*seq_size]);
- HW_DESC_SET_DIN_TYPE(&desc[*seq_size], DMA_DLLI,
- (ctx_p->user.key_dma_addr +
- CC_MULTI2_SYSTEM_KEY_SIZE),
- CC_MULTI2_DATA_KEY_SIZE, NS_BIT);
- HW_DESC_SET_MULTI2_NUM_ROUNDS(&desc[*seq_size],
- ctx_p->key_round_number);
- HW_DESC_SET_FLOW_MODE(&desc[*seq_size], ctx_p->flow_mode);
- HW_DESC_SET_CIPHER_MODE(&desc[*seq_size], ctx_p->cipher_mode);
- HW_DESC_SET_CIPHER_CONFIG0(&desc[*seq_size], direction);
- HW_DESC_SET_SETUP_MODE(&desc[*seq_size], SETUP_LOAD_STATE0 );
+ hw_desc_init(&desc[*seq_size]);
+ set_din_type(&desc[*seq_size], DMA_DLLI,
+ (ctx_p->user.key_dma_addr + CC_MULTI2_SYSTEM_KEY_SIZE),
+ CC_MULTI2_DATA_KEY_SIZE, NS_BIT);
+ set_multi2_num_rounds(&desc[*seq_size], ctx_p->key_round_number);
+ set_flow_mode(&desc[*seq_size], ctx_p->flow_mode);
+ set_cipher_mode(&desc[*seq_size], ctx_p->cipher_mode);
+ set_cipher_config0(&desc[*seq_size], direction);
+ set_setup_mode(&desc[*seq_size], SETUP_LOAD_STATE0);
(*seq_size)++;
-
-
+
/* Set state */
- HW_DESC_INIT(&desc[*seq_size]);
- HW_DESC_SET_DIN_TYPE(&desc[*seq_size], DMA_DLLI,
- req_ctx->gen_ctx.iv_dma_addr,
- ivsize, NS_BIT);
- HW_DESC_SET_CIPHER_CONFIG0(&desc[*seq_size], direction);
- HW_DESC_SET_FLOW_MODE(&desc[*seq_size], ctx_p->flow_mode);
- HW_DESC_SET_CIPHER_MODE(&desc[*seq_size], ctx_p->cipher_mode);
- HW_DESC_SET_SETUP_MODE(&desc[*seq_size], SETUP_LOAD_STATE1);
+ hw_desc_init(&desc[*seq_size]);
+ set_din_type(&desc[*seq_size], DMA_DLLI, req_ctx->gen_ctx.iv_dma_addr,
+ ivsize, NS_BIT);
+ set_cipher_config0(&desc[*seq_size], direction);
+ set_flow_mode(&desc[*seq_size], ctx_p->flow_mode);
+ set_cipher_mode(&desc[*seq_size], ctx_p->cipher_mode);
+ set_setup_mode(&desc[*seq_size], SETUP_LOAD_STATE1);
(*seq_size)++;
-
}
#endif /*SSI_CC_HAS_MULTI2*/
@@ -645,7 +613,7 @@ ssi_blkcipher_create_data_desc(
struct scatterlist *dst, struct scatterlist *src,
unsigned int nbytes,
void *areq,
- HwDesc_s desc[],
+ struct cc_hw_desc desc[],
unsigned int *seq_size)
{
struct ssi_ablkcipher_ctx *ctx_p = crypto_tfm_ctx(tfm);
@@ -668,25 +636,22 @@ ssi_blkcipher_create_data_desc(
return;
}
/* Process */
- if (likely(req_ctx->dma_buf_type == SSI_DMA_BUF_DLLI)){
+ if (likely(req_ctx->dma_buf_type == SSI_DMA_BUF_DLLI)) {
SSI_LOG_DEBUG(" data params addr 0x%llX length 0x%X \n",
(unsigned long long)sg_dma_address(src),
nbytes);
SSI_LOG_DEBUG(" data params addr 0x%llX length 0x%X \n",
(unsigned long long)sg_dma_address(dst),
nbytes);
- HW_DESC_INIT(&desc[*seq_size]);
- HW_DESC_SET_DIN_TYPE(&desc[*seq_size], DMA_DLLI,
- sg_dma_address(src),
- nbytes, NS_BIT);
- HW_DESC_SET_DOUT_DLLI(&desc[*seq_size],
- sg_dma_address(dst),
- nbytes,
- NS_BIT, (areq == NULL)? 0:1);
- if (areq != NULL) {
- HW_DESC_SET_QUEUE_LAST_IND(&desc[*seq_size]);
- }
- HW_DESC_SET_FLOW_MODE(&desc[*seq_size], flow_mode);
+ hw_desc_init(&desc[*seq_size]);
+ set_din_type(&desc[*seq_size], DMA_DLLI, sg_dma_address(src),
+ nbytes, NS_BIT);
+ set_dout_dlli(&desc[*seq_size], sg_dma_address(dst),
+ nbytes, NS_BIT, (!areq ? 0 : 1));
+ if (areq)
+ set_queue_last_ind(&desc[*seq_size]);
+
+ set_flow_mode(&desc[*seq_size], flow_mode);
(*seq_size)++;
} else {
/* bypass */
@@ -695,77 +660,72 @@ ssi_blkcipher_create_data_desc(
(unsigned long long)req_ctx->mlli_params.mlli_dma_addr,
req_ctx->mlli_params.mlli_len,
(unsigned int)ctx_p->drvdata->mlli_sram_addr);
- HW_DESC_INIT(&desc[*seq_size]);
- HW_DESC_SET_DIN_TYPE(&desc[*seq_size], DMA_DLLI,
- req_ctx->mlli_params.mlli_dma_addr,
- req_ctx->mlli_params.mlli_len,
- NS_BIT);
- HW_DESC_SET_DOUT_SRAM(&desc[*seq_size],
- ctx_p->drvdata->mlli_sram_addr,
- req_ctx->mlli_params.mlli_len);
- HW_DESC_SET_FLOW_MODE(&desc[*seq_size], BYPASS);
+ hw_desc_init(&desc[*seq_size]);
+ set_din_type(&desc[*seq_size], DMA_DLLI,
+ req_ctx->mlli_params.mlli_dma_addr,
+ req_ctx->mlli_params.mlli_len, NS_BIT);
+ set_dout_sram(&desc[*seq_size],
+ ctx_p->drvdata->mlli_sram_addr,
+ req_ctx->mlli_params.mlli_len);
+ set_flow_mode(&desc[*seq_size], BYPASS);
(*seq_size)++;
- HW_DESC_INIT(&desc[*seq_size]);
- HW_DESC_SET_DIN_TYPE(&desc[*seq_size], DMA_MLLI,
- ctx_p->drvdata->mlli_sram_addr,
- req_ctx->in_mlli_nents, NS_BIT);
+ hw_desc_init(&desc[*seq_size]);
+ set_din_type(&desc[*seq_size], DMA_MLLI,
+ ctx_p->drvdata->mlli_sram_addr,
+ req_ctx->in_mlli_nents, NS_BIT);
if (req_ctx->out_nents == 0) {
SSI_LOG_DEBUG(" din/dout params addr 0x%08X "
"addr 0x%08X\n",
(unsigned int)ctx_p->drvdata->mlli_sram_addr,
(unsigned int)ctx_p->drvdata->mlli_sram_addr);
- HW_DESC_SET_DOUT_MLLI(&desc[*seq_size],
- ctx_p->drvdata->mlli_sram_addr,
- req_ctx->in_mlli_nents,
- NS_BIT,(areq == NULL)? 0:1);
+ set_dout_mlli(&desc[*seq_size],
+ ctx_p->drvdata->mlli_sram_addr,
+ req_ctx->in_mlli_nents, NS_BIT,
+ (!areq ? 0 : 1));
} else {
SSI_LOG_DEBUG(" din/dout params "
"addr 0x%08X addr 0x%08X\n",
(unsigned int)ctx_p->drvdata->mlli_sram_addr,
- (unsigned int)ctx_p->drvdata->mlli_sram_addr +
- (uint32_t)LLI_ENTRY_BYTE_SIZE *
+ (unsigned int)ctx_p->drvdata->mlli_sram_addr +
+ (u32)LLI_ENTRY_BYTE_SIZE *
req_ctx->in_nents);
- HW_DESC_SET_DOUT_MLLI(&desc[*seq_size],
- (ctx_p->drvdata->mlli_sram_addr +
- LLI_ENTRY_BYTE_SIZE *
- req_ctx->in_mlli_nents),
- req_ctx->out_mlli_nents, NS_BIT,(areq == NULL)? 0:1);
+ set_dout_mlli(&desc[*seq_size],
+ (ctx_p->drvdata->mlli_sram_addr +
+ (LLI_ENTRY_BYTE_SIZE *
+ req_ctx->in_mlli_nents)),
+ req_ctx->out_mlli_nents, NS_BIT,
+ (!areq ? 0 : 1));
}
- if (areq != NULL) {
- HW_DESC_SET_QUEUE_LAST_IND(&desc[*seq_size]);
- }
- HW_DESC_SET_FLOW_MODE(&desc[*seq_size], flow_mode);
+ if (areq)
+ set_queue_last_ind(&desc[*seq_size]);
+
+ set_flow_mode(&desc[*seq_size], flow_mode);
(*seq_size)++;
}
}
static int ssi_blkcipher_complete(struct device *dev,
- struct ssi_ablkcipher_ctx *ctx_p,
- struct blkcipher_req_ctx *req_ctx,
- struct scatterlist *dst, struct scatterlist *src,
- void *info, //req info
- unsigned int ivsize,
- void *areq,
- void __iomem *cc_base)
+ struct ssi_ablkcipher_ctx *ctx_p,
+ struct blkcipher_req_ctx *req_ctx,
+ struct scatterlist *dst,
+ struct scatterlist *src,
+ unsigned int ivsize,
+ void *areq,
+ void __iomem *cc_base)
{
int completion_error = 0;
- uint32_t inflight_counter;
- DECL_CYCLE_COUNT_RESOURCES;
+ u32 inflight_counter;
- START_CYCLE_COUNT();
ssi_buffer_mgr_unmap_blkcipher_request(dev, req_ctx, ivsize, src, dst);
- info = req_ctx->backup_info;
- END_CYCLE_COUNT(STAT_OP_TYPE_GENERIC, STAT_PHASE_4);
-
/*Set the inflight couter value to local variable*/
inflight_counter = ctx_p->drvdata->inflight_counter;
/*Decrease the inflight counter*/
- if(ctx_p->flow_mode == BYPASS && ctx_p->drvdata->inflight_counter > 0)
+ if (ctx_p->flow_mode == BYPASS && ctx_p->drvdata->inflight_counter > 0)
ctx_p->drvdata->inflight_counter--;
- if(areq){
+ if (areq) {
ablkcipher_request_complete(areq, completion_error);
return 0;
}
@@ -779,24 +739,22 @@ static int ssi_blkcipher_process(
unsigned int nbytes,
void *info, //req info
unsigned int ivsize,
- void *areq,
+ void *areq,
enum drv_crypto_direction direction)
{
struct ssi_ablkcipher_ctx *ctx_p = crypto_tfm_ctx(tfm);
struct device *dev = &ctx_p->drvdata->plat_dev->dev;
- HwDesc_s desc[MAX_ABLKCIPHER_SEQ_LEN];
+ struct cc_hw_desc desc[MAX_ABLKCIPHER_SEQ_LEN];
struct ssi_crypto_req ssi_req = {};
- int rc, seq_len = 0,cts_restore_flag = 0;
- DECL_CYCLE_COUNT_RESOURCES;
+ int rc, seq_len = 0, cts_restore_flag = 0;
SSI_LOG_DEBUG("%s areq=%p info=%p nbytes=%d\n",
- ((direction==DRV_CRYPTO_DIRECTION_ENCRYPT)?"Encrypt":"Decrypt"),
+ ((direction == DRV_CRYPTO_DIRECTION_ENCRYPT) ? "Encrypt" : "Decrypt"),
areq, info, nbytes);
CHECK_AND_RETURN_UPON_FIPS_ERROR();
/* STAT_PHASE_0: Init and sanity checks */
- START_CYCLE_COUNT();
-
+
/* TODO: check data length according to mode */
if (unlikely(validate_data_size(ctx_p, nbytes))) {
SSI_LOG_ERR("Unsupported data size %d.\n", nbytes);
@@ -807,9 +765,8 @@ static int ssi_blkcipher_process(
/* No data to process is valid */
return 0;
}
- /*For CTS in case of data size aligned to 16 use CBC mode*/
- if (((nbytes % AES_BLOCK_SIZE) == 0) && (ctx_p->cipher_mode == DRV_CIPHER_CBC_CTS)){
-
+ /*For CTS in case of data size aligned to 16 use CBC mode*/
+ if (((nbytes % AES_BLOCK_SIZE) == 0) && (ctx_p->cipher_mode == DRV_CIPHER_CBC_CTS)) {
ctx_p->cipher_mode = DRV_CIPHER_CBC;
cts_restore_flag = 1;
}
@@ -826,83 +783,65 @@ static int ssi_blkcipher_process(
/* Setup request context */
req_ctx->gen_ctx.op_type = direction;
-
- END_CYCLE_COUNT(ssi_req.op_type, STAT_PHASE_0);
/* STAT_PHASE_1: Map buffers */
- START_CYCLE_COUNT();
-
+
rc = ssi_buffer_mgr_map_blkcipher_request(ctx_p->drvdata, req_ctx, ivsize, nbytes, info, src, dst);
if (unlikely(rc != 0)) {
SSI_LOG_ERR("map_request() failed\n");
goto exit_process;
}
- END_CYCLE_COUNT(ssi_req.op_type, STAT_PHASE_1);
-
/* STAT_PHASE_2: Create sequence */
- START_CYCLE_COUNT();
/* Setup processing */
#if SSI_CC_HAS_MULTI2
- if (ctx_p->flow_mode == S_DIN_to_MULTI2) {
- ssi_blkcipher_create_multi2_setup_desc(tfm,
- req_ctx,
- ivsize,
- desc,
- &seq_len);
- } else
+ if (ctx_p->flow_mode == S_DIN_to_MULTI2)
+ ssi_blkcipher_create_multi2_setup_desc(tfm, req_ctx, ivsize,
+ desc, &seq_len);
+ else
#endif /*SSI_CC_HAS_MULTI2*/
- {
- ssi_blkcipher_create_setup_desc(tfm,
- req_ctx,
- ivsize,
- nbytes,
- desc,
- &seq_len);
- }
+ ssi_blkcipher_create_setup_desc(tfm, req_ctx, ivsize, nbytes,
+ desc, &seq_len);
/* Data processing */
ssi_blkcipher_create_data_desc(tfm,
- req_ctx,
+ req_ctx,
dst, src,
nbytes,
areq,
desc, &seq_len);
/* do we need to generate IV? */
- if (req_ctx->is_giv == true) {
+ if (req_ctx->is_giv) {
ssi_req.ivgen_dma_addr[0] = req_ctx->gen_ctx.iv_dma_addr;
ssi_req.ivgen_dma_addr_len = 1;
/* set the IV size (8/16 B long)*/
ssi_req.ivgen_size = ivsize;
}
- END_CYCLE_COUNT(ssi_req.op_type, STAT_PHASE_2);
/* STAT_PHASE_3: Lock HW and push sequence */
- START_CYCLE_COUNT();
-
- rc = send_request(ctx_p->drvdata, &ssi_req, desc, seq_len, (areq == NULL)? 0:1);
- if(areq != NULL) {
+
+ rc = send_request(ctx_p->drvdata, &ssi_req, desc, seq_len, (!areq) ? 0 : 1);
+ if (areq) {
if (unlikely(rc != -EINPROGRESS)) {
/* Failed to send the request or request completed synchronously */
ssi_buffer_mgr_unmap_blkcipher_request(dev, req_ctx, ivsize, src, dst);
}
- END_CYCLE_COUNT(ssi_req.op_type, STAT_PHASE_3);
} else {
if (rc != 0) {
ssi_buffer_mgr_unmap_blkcipher_request(dev, req_ctx, ivsize, src, dst);
- END_CYCLE_COUNT(ssi_req.op_type, STAT_PHASE_3);
} else {
- END_CYCLE_COUNT(ssi_req.op_type, STAT_PHASE_3);
- rc = ssi_blkcipher_complete(dev, ctx_p, req_ctx, dst, src, info, ivsize, NULL, ctx_p->drvdata->cc_base);
- }
+ rc = ssi_blkcipher_complete(dev, ctx_p, req_ctx, dst,
+ src, ivsize, NULL,
+ ctx_p->drvdata->cc_base);
+ }
}
exit_process:
if (cts_restore_flag != 0)
ctx_p->cipher_mode = DRV_CIPHER_CBC_CTS;
-
+
return rc;
}
@@ -916,86 +855,23 @@ static void ssi_ablkcipher_complete(struct device *dev, void *ssi_req, void __io
CHECK_AND_RETURN_VOID_UPON_FIPS_ERROR();
- ssi_blkcipher_complete(dev, ctx_p, req_ctx, areq->dst, areq->src, areq->info, ivsize, areq, cc_base);
-}
-
-
-
-static int ssi_sblkcipher_init(struct crypto_tfm *tfm)
-{
- struct ssi_ablkcipher_ctx *ctx_p = crypto_tfm_ctx(tfm);
-
- /* Allocate sync ctx buffer */
- ctx_p->sync_ctx = kmalloc(sizeof(struct blkcipher_req_ctx), GFP_KERNEL|GFP_DMA);
- if (!ctx_p->sync_ctx) {
- SSI_LOG_ERR("Allocating sync ctx buffer in context failed\n");
- return -ENOMEM;
- }
- SSI_LOG_DEBUG("Allocated sync ctx buffer in context ctx_p->sync_ctx=@%p\n",
- ctx_p->sync_ctx);
-
- return ssi_blkcipher_init(tfm);
-}
-
-
-static void ssi_sblkcipher_exit(struct crypto_tfm *tfm)
-{
- struct ssi_ablkcipher_ctx *ctx_p = crypto_tfm_ctx(tfm);
-
- kfree(ctx_p->sync_ctx);
- SSI_LOG_DEBUG("Free sync ctx buffer in context ctx_p->sync_ctx=@%p\n", ctx_p->sync_ctx);
-
- ssi_blkcipher_exit(tfm);
-}
-
-#ifdef SYNC_ALGS
-static int ssi_sblkcipher_encrypt(struct blkcipher_desc *desc,
- struct scatterlist *dst, struct scatterlist *src,
- unsigned int nbytes)
-{
- struct crypto_blkcipher *blk_tfm = desc->tfm;
- struct crypto_tfm *tfm = crypto_blkcipher_tfm(blk_tfm);
- struct ssi_ablkcipher_ctx *ctx_p = crypto_tfm_ctx(tfm);
- struct blkcipher_req_ctx *req_ctx = ctx_p->sync_ctx;
- unsigned int ivsize = crypto_blkcipher_ivsize(blk_tfm);
-
- req_ctx->backup_info = desc->info;
- req_ctx->is_giv = false;
-
- return ssi_blkcipher_process(tfm, req_ctx, dst, src, nbytes, desc->info, ivsize, NULL, DRV_CRYPTO_DIRECTION_ENCRYPT);
-}
-
-static int ssi_sblkcipher_decrypt(struct blkcipher_desc *desc,
- struct scatterlist *dst, struct scatterlist *src,
- unsigned int nbytes)
-{
- struct crypto_blkcipher *blk_tfm = desc->tfm;
- struct crypto_tfm *tfm = crypto_blkcipher_tfm(blk_tfm);
- struct ssi_ablkcipher_ctx *ctx_p = crypto_tfm_ctx(tfm);
- struct blkcipher_req_ctx *req_ctx = ctx_p->sync_ctx;
- unsigned int ivsize = crypto_blkcipher_ivsize(blk_tfm);
-
- req_ctx->backup_info = desc->info;
- req_ctx->is_giv = false;
-
- return ssi_blkcipher_process(tfm, req_ctx, dst, src, nbytes, desc->info, ivsize, NULL, DRV_CRYPTO_DIRECTION_DECRYPT);
+ ssi_blkcipher_complete(dev, ctx_p, req_ctx, areq->dst, areq->src,
+ ivsize, areq, cc_base);
}
-#endif
/* Async wrap functions */
static int ssi_ablkcipher_init(struct crypto_tfm *tfm)
{
struct ablkcipher_tfm *ablktfm = &tfm->crt_ablkcipher;
-
+
ablktfm->reqsize = sizeof(struct blkcipher_req_ctx);
return ssi_blkcipher_init(tfm);
}
-
-static int ssi_ablkcipher_setkey(struct crypto_ablkcipher *tfm,
- const u8 *key,
+static int ssi_ablkcipher_setkey(struct crypto_ablkcipher *tfm,
+ const u8 *key,
unsigned int keylen)
{
return ssi_blkcipher_setkey(crypto_ablkcipher_tfm(tfm), key, keylen);
@@ -1026,7 +902,6 @@ static int ssi_ablkcipher_decrypt(struct ablkcipher_request *req)
return ssi_blkcipher_process(tfm, req_ctx, req->dst, req->src, req->nbytes, req->info, ivsize, (void *)req, DRV_CRYPTO_DIRECTION_DECRYPT);
}
-
/* DX Block cipher alg */
static struct ssi_alg_template blkcipher_algs[] = {
/* Async template */
@@ -1047,7 +922,6 @@ static struct ssi_alg_template blkcipher_algs[] = {
},
.cipher_mode = DRV_CIPHER_XTS,
.flow_mode = S_DIN_to_AES,
- .synchronous = false,
},
{
.name = "xts(aes)",
@@ -1064,7 +938,6 @@ static struct ssi_alg_template blkcipher_algs[] = {
},
.cipher_mode = DRV_CIPHER_XTS,
.flow_mode = S_DIN_to_AES,
- .synchronous = false,
},
{
.name = "xts(aes)",
@@ -1081,7 +954,6 @@ static struct ssi_alg_template blkcipher_algs[] = {
},
.cipher_mode = DRV_CIPHER_XTS,
.flow_mode = S_DIN_to_AES,
- .synchronous = false,
},
#endif /*SSI_CC_HAS_AES_XTS*/
#if SSI_CC_HAS_AES_ESSIV
@@ -1100,7 +972,6 @@ static struct ssi_alg_template blkcipher_algs[] = {
},
.cipher_mode = DRV_CIPHER_ESSIV,
.flow_mode = S_DIN_to_AES,
- .synchronous = false,
},
{
.name = "essiv(aes)",
@@ -1117,7 +988,6 @@ static struct ssi_alg_template blkcipher_algs[] = {
},
.cipher_mode = DRV_CIPHER_ESSIV,
.flow_mode = S_DIN_to_AES,
- .synchronous = false,
},
{
.name = "essiv(aes)",
@@ -1134,7 +1004,6 @@ static struct ssi_alg_template blkcipher_algs[] = {
},
.cipher_mode = DRV_CIPHER_ESSIV,
.flow_mode = S_DIN_to_AES,
- .synchronous = false,
},
#endif /*SSI_CC_HAS_AES_ESSIV*/
#if SSI_CC_HAS_AES_BITLOCKER
@@ -1153,7 +1022,6 @@ static struct ssi_alg_template blkcipher_algs[] = {
},
.cipher_mode = DRV_CIPHER_BITLOCKER,
.flow_mode = S_DIN_to_AES,
- .synchronous = false,
},
{
.name = "bitlocker(aes)",
@@ -1170,7 +1038,6 @@ static struct ssi_alg_template blkcipher_algs[] = {
},
.cipher_mode = DRV_CIPHER_BITLOCKER,
.flow_mode = S_DIN_to_AES,
- .synchronous = false,
},
{
.name = "bitlocker(aes)",
@@ -1187,7 +1054,6 @@ static struct ssi_alg_template blkcipher_algs[] = {
},
.cipher_mode = DRV_CIPHER_BITLOCKER,
.flow_mode = S_DIN_to_AES,
- .synchronous = false,
},
#endif /*SSI_CC_HAS_AES_BITLOCKER*/
{
@@ -1205,7 +1071,6 @@ static struct ssi_alg_template blkcipher_algs[] = {
},
.cipher_mode = DRV_CIPHER_ECB,
.flow_mode = S_DIN_to_AES,
- .synchronous = false,
},
{
.name = "cbc(aes)",
@@ -1219,10 +1084,9 @@ static struct ssi_alg_template blkcipher_algs[] = {
.min_keysize = AES_MIN_KEY_SIZE,
.max_keysize = AES_MAX_KEY_SIZE,
.ivsize = AES_BLOCK_SIZE,
- },
+ },
.cipher_mode = DRV_CIPHER_CBC,
.flow_mode = S_DIN_to_AES,
- .synchronous = false,
},
{
.name = "ofb(aes)",
@@ -1239,7 +1103,6 @@ static struct ssi_alg_template blkcipher_algs[] = {
},
.cipher_mode = DRV_CIPHER_OFB,
.flow_mode = S_DIN_to_AES,
- .synchronous = false,
},
#if SSI_CC_HAS_AES_CTS
{
@@ -1257,7 +1120,6 @@ static struct ssi_alg_template blkcipher_algs[] = {
},
.cipher_mode = DRV_CIPHER_CBC_CTS,
.flow_mode = S_DIN_to_AES,
- .synchronous = false,
},
#endif
{
@@ -1275,7 +1137,6 @@ static struct ssi_alg_template blkcipher_algs[] = {
},
.cipher_mode = DRV_CIPHER_CTR,
.flow_mode = S_DIN_to_AES,
- .synchronous = false,
},
{
.name = "cbc(des3_ede)",
@@ -1292,7 +1153,6 @@ static struct ssi_alg_template blkcipher_algs[] = {
},
.cipher_mode = DRV_CIPHER_CBC,
.flow_mode = S_DIN_to_DES,
- .synchronous = false,
},
{
.name = "ecb(des3_ede)",
@@ -1309,7 +1169,6 @@ static struct ssi_alg_template blkcipher_algs[] = {
},
.cipher_mode = DRV_CIPHER_ECB,
.flow_mode = S_DIN_to_DES,
- .synchronous = false,
},
{
.name = "cbc(des)",
@@ -1326,7 +1185,6 @@ static struct ssi_alg_template blkcipher_algs[] = {
},
.cipher_mode = DRV_CIPHER_CBC,
.flow_mode = S_DIN_to_DES,
- .synchronous = false,
},
{
.name = "ecb(des)",
@@ -1343,7 +1201,6 @@ static struct ssi_alg_template blkcipher_algs[] = {
},
.cipher_mode = DRV_CIPHER_ECB,
.flow_mode = S_DIN_to_DES,
- .synchronous = false,
},
#if SSI_CC_HAS_MULTI2
{
@@ -1361,7 +1218,6 @@ static struct ssi_alg_template blkcipher_algs[] = {
},
.cipher_mode = DRV_MULTI2_CBC,
.flow_mode = S_DIN_to_MULTI2,
- .synchronous = false,
},
{
.name = "ofb(multi2)",
@@ -1378,12 +1234,11 @@ static struct ssi_alg_template blkcipher_algs[] = {
},
.cipher_mode = DRV_MULTI2_OFB,
.flow_mode = S_DIN_to_MULTI2,
- .synchronous = false,
},
#endif /*SSI_CC_HAS_MULTI2*/
};
-static
+static
struct ssi_crypto_alg *ssi_ablkcipher_create_alg(struct ssi_alg_template *template)
{
struct ssi_crypto_alg *t_alg;
@@ -1405,19 +1260,13 @@ struct ssi_crypto_alg *ssi_ablkcipher_create_alg(struct ssi_alg_template *templa
alg->cra_blocksize = template->blocksize;
alg->cra_alignmask = 0;
alg->cra_ctxsize = sizeof(struct ssi_ablkcipher_ctx);
-
- alg->cra_init = template->synchronous? ssi_sblkcipher_init:ssi_ablkcipher_init;
- alg->cra_exit = template->synchronous? ssi_sblkcipher_exit:ssi_blkcipher_exit;
- alg->cra_type = template->synchronous? &crypto_blkcipher_type:&crypto_ablkcipher_type;
- if(template->synchronous) {
- alg->cra_blkcipher = template->template_sblkcipher;
- alg->cra_flags = CRYPTO_ALG_KERN_DRIVER_ONLY |
- template->type;
- } else {
- alg->cra_ablkcipher = template->template_ablkcipher;
- alg->cra_flags = CRYPTO_ALG_ASYNC | CRYPTO_ALG_KERN_DRIVER_ONLY |
+
+ alg->cra_init = ssi_ablkcipher_init;
+ alg->cra_exit = ssi_blkcipher_exit;
+ alg->cra_type = &crypto_ablkcipher_type;
+ alg->cra_ablkcipher = template->template_ablkcipher;
+ alg->cra_flags = CRYPTO_ALG_ASYNC | CRYPTO_ALG_KERN_DRIVER_ONLY |
template->type;
- }
t_alg->cipher_mode = template->cipher_mode;
t_alg->flow_mode = template->flow_mode;
@@ -1428,12 +1277,13 @@ struct ssi_crypto_alg *ssi_ablkcipher_create_alg(struct ssi_alg_template *templa
int ssi_ablkcipher_free(struct ssi_drvdata *drvdata)
{
struct ssi_crypto_alg *t_alg, *n;
- struct ssi_blkcipher_handle *blkcipher_handle =
+ struct ssi_blkcipher_handle *blkcipher_handle =
drvdata->blkcipher_handle;
struct device *dev;
+
dev = &drvdata->plat_dev->dev;
- if (blkcipher_handle != NULL) {
+ if (blkcipher_handle) {
/* Remove registered algs */
list_for_each_entry_safe(t_alg, n,
&blkcipher_handle->blkcipher_alg_list,
@@ -1448,8 +1298,6 @@ int ssi_ablkcipher_free(struct ssi_drvdata *drvdata)
return 0;
}
-
-
int ssi_ablkcipher_alloc(struct ssi_drvdata *drvdata)
{
struct ssi_blkcipher_handle *ablkcipher_handle;
@@ -1459,7 +1307,7 @@ int ssi_ablkcipher_alloc(struct ssi_drvdata *drvdata)
ablkcipher_handle = kmalloc(sizeof(struct ssi_blkcipher_handle),
GFP_KERNEL);
- if (ablkcipher_handle == NULL)
+ if (!ablkcipher_handle)
return -ENOMEM;
drvdata->blkcipher_handle = ablkcipher_handle;
@@ -1489,9 +1337,9 @@ int ssi_ablkcipher_alloc(struct ssi_drvdata *drvdata)
kfree(t_alg);
goto fail0;
} else {
- list_add_tail(&t_alg->entry,
+ list_add_tail(&t_alg->entry,
&ablkcipher_handle->blkcipher_alg_list);
- SSI_LOG_DEBUG("Registered %s\n",
+ SSI_LOG_DEBUG("Registered %s\n",
t_alg->crypto_alg.cra_driver_name);
}
}
diff --git a/drivers/staging/ccree/ssi_cipher.h b/drivers/staging/ccree/ssi_cipher.h
index ba4eb7c4893f..296b375d5d89 100644
--- a/drivers/staging/ccree/ssi_cipher.h
+++ b/drivers/staging/ccree/ssi_cipher.h
@@ -1,21 +1,21 @@
/*
* Copyright (C) 2012-2017 ARM Limited or its affiliates.
- *
+ *
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
- *
+ *
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
- *
+ *
* You should have received a copy of the GNU General Public License
* along with this program; if not, see <http://www.gnu.org/licenses/>.
*/
/* \file ssi_cipher.h
- ARM CryptoCell Cipher Crypto API
+ * ARM CryptoCell Cipher Crypto API
*/
#ifndef __SSI_CIPHER_H__
@@ -26,7 +26,6 @@
#include "ssi_driver.h"
#include "ssi_buffer_mgr.h"
-
/* Crypto cipher flags */
#define CC_CRYPTO_CIPHER_KEY_KFDE0 (1 << 0)
#define CC_CRYPTO_CIPHER_KEY_KFDE1 (1 << 1)
@@ -36,21 +35,18 @@
#define CC_CRYPTO_CIPHER_KEY_KFDE_MASK (CC_CRYPTO_CIPHER_KEY_KFDE0 | CC_CRYPTO_CIPHER_KEY_KFDE1 | CC_CRYPTO_CIPHER_KEY_KFDE2 | CC_CRYPTO_CIPHER_KEY_KFDE3)
-
struct blkcipher_req_ctx {
struct async_gen_req_ctx gen_ctx;
enum ssi_req_dma_buf_type dma_buf_type;
- uint32_t in_nents;
- uint32_t in_mlli_nents;
- uint32_t out_nents;
- uint32_t out_mlli_nents;
- uint8_t *backup_info; /*store iv for generated IV flow*/
+ u32 in_nents;
+ u32 in_mlli_nents;
+ u32 out_nents;
+ u32 out_mlli_nents;
+ u8 *backup_info; /*store iv for generated IV flow*/
bool is_giv;
struct mlli_params mlli_params;
};
-
-
int ssi_ablkcipher_alloc(struct ssi_drvdata *drvdata);
int ssi_ablkcipher_free(struct ssi_drvdata *drvdata);
@@ -63,7 +59,6 @@ int ssi_ablkcipher_free(struct ssi_drvdata *drvdata);
CRYPTO_ALG_BULK_DU_4096)
#endif /* CRYPTO_ALG_BULK_MASK */
-
#ifdef CRYPTO_TFM_REQ_HW_KEY
static inline bool ssi_is_hw_key(struct crypto_tfm *tfm)
@@ -71,7 +66,7 @@ static inline bool ssi_is_hw_key(struct crypto_tfm *tfm)
return (crypto_tfm_get_flags(tfm) & CRYPTO_TFM_REQ_HW_KEY);
}
-#else
+#else
struct arm_hw_key_info {
int hw_key1;
@@ -85,5 +80,4 @@ static inline bool ssi_is_hw_key(struct crypto_tfm *tfm)
#endif /* CRYPTO_TFM_REQ_HW_KEY */
-
#endif /*__SSI_CIPHER_H__*/
diff --git a/drivers/staging/ccree/ssi_config.h b/drivers/staging/ccree/ssi_config.h
index d96a5436f6d7..ff7597c2d77e 100644
--- a/drivers/staging/ccree/ssi_config.h
+++ b/drivers/staging/ccree/ssi_config.h
@@ -1,21 +1,21 @@
/*
* Copyright (C) 2012-2017 ARM Limited or its affiliates.
- *
+ *
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
- *
+ *
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
- *
+ *
* You should have received a copy of the GNU General Public License
* along with this program; if not, see <http://www.gnu.org/licenses/>.
*/
/* \file ssi_config.h
- Definitions for ARM CryptoCell Linux Crypto Driver
+ * Definitions for ARM CryptoCell Linux Crypto Driver
*/
#ifndef __SSI_CONFIG_H__
@@ -23,39 +23,14 @@
#include <linux/version.h>
-#define DISABLE_COHERENT_DMA_OPS
//#define FLUSH_CACHE_ALL
//#define COMPLETION_DELAY
//#define DX_DUMP_DESCS
// #define DX_DUMP_BYTES
// #define CC_DEBUG
#define ENABLE_CC_SYSFS /* Enable sysfs interface for debugging REE driver */
-//#define ENABLE_CC_CYCLE_COUNT
//#define DX_IRQ_DELAY 100000
#define DMA_BIT_MASK_LEN 48 /* was 32 bit, but for juno's sake it was enlarged to 48 bit */
-#if defined ENABLE_CC_CYCLE_COUNT && defined ENABLE_CC_SYSFS
-#define CC_CYCLE_COUNT
-#endif
-
-
-#if defined (CONFIG_ARM64) // TODO currently only this mode was test on Juno (which is ARM64), need to enable coherent also.
-#define DISABLE_COHERENT_DMA_OPS
-#endif
-
-/* Define the CryptoCell DMA cache coherency signals configuration */
-#if defined (DISABLE_COHERENT_DMA_OPS)
- /* Software Controlled Cache Coherency (SCCC) */
- #define SSI_CACHE_PARAMS (0x000)
- /* CC attached to NONE-ACP such as HPP/ACE/AMBA4.
- * The customer is responsible to enable/disable this feature
- * according to his platform type. */
- #define DX_HAS_ACP 0
-#else
- #define SSI_CACHE_PARAMS (0xEEE)
- /* CC attached to ACP */
- #define DX_HAS_ACP 1
-#endif
-
#endif /*__DX_CONFIG_H__*/
diff --git a/drivers/staging/ccree/ssi_driver.c b/drivers/staging/ccree/ssi_driver.c
index bc19adce6dee..78709b92736d 100644
--- a/drivers/staging/ccree/ssi_driver.c
+++ b/drivers/staging/ccree/ssi_driver.c
@@ -1,15 +1,15 @@
/*
* Copyright (C) 2012-2017 ARM Limited or its affiliates.
- *
+ *
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
- *
+ *
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
- *
+ *
* You should have received a copy of the GNU General Public License
* along with this program; if not, see <http://www.gnu.org/licenses/>.
*/
@@ -57,6 +57,8 @@
#include <linux/sched.h>
#include <linux/random.h>
#include <linux/of.h>
+#include <linux/clk.h>
+#include <linux/of_address.h>
#include "ssi_config.h"
#include "ssi_driver.h"
@@ -71,15 +73,14 @@
#include "ssi_pm.h"
#include "ssi_fips_local.h"
-
#ifdef DX_DUMP_BYTES
-void dump_byte_array(const char *name, const uint8_t *the_array, unsigned long size)
+void dump_byte_array(const char *name, const u8 *the_array, unsigned long size)
{
- int i , line_offset = 0, ret = 0;
- const uint8_t *cur_byte;
+ int i, line_offset = 0, ret = 0;
+ const u8 *cur_byte;
char line_buf[80];
- if (the_array == NULL) {
+ if (!the_array) {
SSI_LOG_ERR("cannot dump_byte_array - NULL pointer\n");
return;
}
@@ -87,17 +88,17 @@ void dump_byte_array(const char *name, const uint8_t *the_array, unsigned long s
ret = snprintf(line_buf, sizeof(line_buf), "%s[%lu]: ",
name, size);
if (ret < 0) {
- SSI_LOG_ERR("snprintf returned %d . aborting buffer array dump\n",ret);
+ SSI_LOG_ERR("snprintf returned %d . aborting buffer array dump\n", ret);
return;
}
line_offset = ret;
- for (i = 0 , cur_byte = the_array;
+ for (i = 0, cur_byte = the_array;
(i < size) && (line_offset < sizeof(line_buf)); i++, cur_byte++) {
ret = snprintf(line_buf + line_offset,
sizeof(line_buf) - line_offset,
"0x%02X ", *cur_byte);
if (ret < 0) {
- SSI_LOG_ERR("snprintf returned %d . aborting buffer array dump\n",ret);
+ SSI_LOG_ERR("snprintf returned %d . aborting buffer array dump\n", ret);
return;
}
line_offset += ret;
@@ -116,12 +117,10 @@ static irqreturn_t cc_isr(int irq, void *dev_id)
{
struct ssi_drvdata *drvdata = (struct ssi_drvdata *)dev_id;
void __iomem *cc_base = drvdata->cc_base;
- uint32_t irr;
- uint32_t imr;
- DECL_CYCLE_COUNT_RESOURCES;
+ u32 irr;
+ u32 imr;
/* STAT_OP_TYPE_GENERIC STAT_PHASE_0: Interrupt */
- START_CYCLE_COUNT();
/* read the interrupt status */
irr = CC_HAL_READ_REGISTER(CC_REG_OFFSET(HOST_RGF, HOST_IRR));
@@ -154,12 +153,12 @@ static irqreturn_t cc_isr(int irq, void *dev_id)
#endif
/* AXI error interrupt */
if (unlikely((irr & SSI_AXI_ERR_IRQ_MASK) != 0)) {
- uint32_t axi_err;
-
+ u32 axi_err;
+
/* Read the AXI error ID */
axi_err = CC_HAL_READ_REGISTER(CC_REG_OFFSET(CRY_KERNEL, AXIM_MON_ERR));
SSI_LOG_DEBUG("AXI completion error: axim_mon_err=0x%08X\n", axi_err);
-
+
irr &= ~SSI_AXI_ERR_IRQ_MASK;
}
@@ -168,15 +167,12 @@ static irqreturn_t cc_isr(int irq, void *dev_id)
/* Just warning */
}
- END_CYCLE_COUNT(STAT_OP_TYPE_GENERIC, STAT_PHASE_0);
- START_CYCLE_COUNT_AT(drvdata->isr_exit_cycles);
-
return IRQ_HANDLED;
}
int init_cc_regs(struct ssi_drvdata *drvdata, bool is_probe)
{
- unsigned int val;
+ unsigned int val, cache_params;
void __iomem *cc_base = drvdata->cc_base;
/* Unmask all AXI interrupt sources AXI_CFG1 register */
@@ -192,7 +188,7 @@ int init_cc_regs(struct ssi_drvdata *drvdata, bool is_probe)
/* Unmask relevant interrupt cause */
val = (~(SSI_COMP_IRQ_MASK | SSI_AXI_ERR_IRQ_MASK | SSI_GPR0_IRQ_MASK));
CC_HAL_WRITE_REGISTER(CC_REG_OFFSET(HOST_RGF, HOST_IMR), val);
-
+
#ifdef DX_HOST_IRQ_TIMER_INIT_VAL_REG_OFFSET
#ifdef DX_IRQ_DELAY
/* Set CC IRQ delay */
@@ -205,15 +201,20 @@ int init_cc_regs(struct ssi_drvdata *drvdata, bool is_probe)
}
#endif
+ cache_params = (drvdata->coherent ? CC_COHERENT_CACHE_PARAMS : 0x0);
+
val = CC_HAL_READ_REGISTER(CC_REG_OFFSET(CRY_KERNEL, AXIM_CACHE_PARAMS));
- if (is_probe == true) {
+
+ if (is_probe)
SSI_LOG_INFO("Cache params previous: 0x%08X\n", val);
- }
- CC_HAL_WRITE_REGISTER(CC_REG_OFFSET(CRY_KERNEL, AXIM_CACHE_PARAMS), SSI_CACHE_PARAMS);
+
+ CC_HAL_WRITE_REGISTER(CC_REG_OFFSET(CRY_KERNEL, AXIM_CACHE_PARAMS),
+ cache_params);
val = CC_HAL_READ_REGISTER(CC_REG_OFFSET(CRY_KERNEL, AXIM_CACHE_PARAMS));
- if (is_probe == true) {
- SSI_LOG_INFO("Cache params current: 0x%08X (expected: 0x%08X)\n", val, SSI_CACHE_PARAMS);
- }
+
+ if (is_probe)
+ SSI_LOG_INFO("Cache params current: 0x%08X (expect: 0x%08X)\n",
+ val, cache_params);
return 0;
}
@@ -224,15 +225,20 @@ static int init_cc_resources(struct platform_device *plat_dev)
void __iomem *cc_base = NULL;
bool irq_registered = false;
struct ssi_drvdata *new_drvdata = kzalloc(sizeof(struct ssi_drvdata), GFP_KERNEL);
- uint32_t signature_val;
+ struct device *dev = &plat_dev->dev;
+ struct device_node *np = dev->of_node;
+ u32 signature_val;
int rc = 0;
- if (unlikely(new_drvdata == NULL)) {
+ if (unlikely(!new_drvdata)) {
SSI_LOG_ERR("Failed to allocate drvdata");
rc = -ENOMEM;
goto init_cc_res_err;
}
+ new_drvdata->clk = of_clk_get(np, 0);
+ new_drvdata->coherent = of_dma_is_coherent(np);
+
/*Initialize inflight counter used in dx_ablkcipher_secure_complete used for count of BYSPASS blocks operations*/
new_drvdata->inflight_counter = 0;
@@ -240,7 +246,7 @@ static int init_cc_resources(struct platform_device *plat_dev)
/* Get device resources */
/* First CC registers space */
new_drvdata->res_mem = platform_get_resource(plat_dev, IORESOURCE_MEM, 0);
- if (unlikely(new_drvdata->res_mem == NULL)) {
+ if (unlikely(!new_drvdata->res_mem)) {
SSI_LOG_ERR("Failed getting IO memory resource\n");
rc = -ENODEV;
goto init_cc_res_err;
@@ -251,14 +257,14 @@ static int init_cc_resources(struct platform_device *plat_dev)
(unsigned long long)new_drvdata->res_mem->end);
/* Map registers space */
req_mem_cc_regs = request_mem_region(new_drvdata->res_mem->start, resource_size(new_drvdata->res_mem), "arm_cc7x_regs");
- if (unlikely(req_mem_cc_regs == NULL)) {
+ if (unlikely(!req_mem_cc_regs)) {
SSI_LOG_ERR("Couldn't allocate registers memory region at "
"0x%08X\n", (unsigned int)new_drvdata->res_mem->start);
rc = -EBUSY;
goto init_cc_res_err;
}
cc_base = ioremap(new_drvdata->res_mem->start, resource_size(new_drvdata->res_mem));
- if (unlikely(cc_base == NULL)) {
+ if (unlikely(!cc_base)) {
SSI_LOG_ERR("ioremap[CC](0x%08X,0x%08X) failed\n",
(unsigned int)new_drvdata->res_mem->start, (unsigned int)resource_size(new_drvdata->res_mem));
rc = -ENOMEM;
@@ -266,11 +272,10 @@ static int init_cc_resources(struct platform_device *plat_dev)
}
SSI_LOG_DEBUG("CC registers mapped from %pa to 0x%p\n", &new_drvdata->res_mem->start, cc_base);
new_drvdata->cc_base = cc_base;
-
/* Then IRQ */
new_drvdata->res_irq = platform_get_resource(plat_dev, IORESOURCE_IRQ, 0);
- if (unlikely(new_drvdata->res_irq == NULL)) {
+ if (unlikely(!new_drvdata->res_irq)) {
SSI_LOG_ERR("Failed getting IRQ resource\n");
rc = -ENODEV;
goto init_cc_res_err;
@@ -291,9 +296,13 @@ static int init_cc_resources(struct platform_device *plat_dev)
new_drvdata->plat_dev = plat_dev;
- if(new_drvdata->plat_dev->dev.dma_mask == NULL)
+ rc = cc_clk_on(new_drvdata);
+ if (rc)
+ goto init_cc_res_err;
+
+ if (!new_drvdata->plat_dev->dev.dma_mask)
{
- new_drvdata->plat_dev->dev.dma_mask = & new_drvdata->plat_dev->dev.coherent_dma_mask;
+ new_drvdata->plat_dev->dev.dma_mask = &new_drvdata->plat_dev->dev.coherent_dma_mask;
}
if (!new_drvdata->plat_dev->dev.coherent_dma_mask)
{
@@ -304,7 +313,7 @@ static int init_cc_resources(struct platform_device *plat_dev)
signature_val = CC_HAL_READ_REGISTER(CC_REG_OFFSET(HOST_RGF, HOST_SIGNATURE));
if (signature_val != DX_DEV_SIGNATURE) {
SSI_LOG_ERR("Invalid CC signature: SIGNATURE=0x%08X != expected=0x%08X\n",
- signature_val, (uint32_t)DX_DEV_SIGNATURE);
+ signature_val, (u32)DX_DEV_SIGNATURE);
rc = -EINVAL;
goto init_cc_res_err;
}
@@ -396,8 +405,8 @@ static int init_cc_resources(struct platform_device *plat_dev)
init_cc_res_err:
SSI_LOG_ERR("Freeing CC HW resources!\n");
-
- if (new_drvdata != NULL) {
+
+ if (new_drvdata) {
ssi_aead_free(new_drvdata);
ssi_hash_free(new_drvdata);
ssi_ablkcipher_free(new_drvdata);
@@ -410,8 +419,8 @@ init_cc_res_err:
#ifdef ENABLE_CC_SYSFS
ssi_sysfs_fini();
#endif
-
- if (req_mem_cc_regs != NULL) {
+
+ if (req_mem_cc_regs) {
if (irq_registered) {
free_irq(new_drvdata->res_irq->start, new_drvdata);
new_drvdata->res_irq = NULL;
@@ -432,9 +441,8 @@ init_cc_res_err:
void fini_cc_regs(struct ssi_drvdata *drvdata)
{
/* Mask all interrupts */
- WRITE_REGISTER(drvdata->cc_base +
+ WRITE_REGISTER(drvdata->cc_base +
CC_REG_OFFSET(HOST_RGF, HOST_IMR), 0xFFFFFFFF);
-
}
static void cleanup_cc_resources(struct platform_device *plat_dev)
@@ -442,9 +450,9 @@ static void cleanup_cc_resources(struct platform_device *plat_dev)
struct ssi_drvdata *drvdata =
(struct ssi_drvdata *)dev_get_drvdata(&plat_dev->dev);
- ssi_aead_free(drvdata);
- ssi_hash_free(drvdata);
- ssi_ablkcipher_free(drvdata);
+ ssi_aead_free(drvdata);
+ ssi_hash_free(drvdata);
+ ssi_ablkcipher_free(drvdata);
ssi_ivgen_fini(drvdata);
ssi_power_mgr_fini(drvdata);
ssi_buffer_mgr_fini(drvdata);
@@ -455,15 +463,12 @@ static void cleanup_cc_resources(struct platform_device *plat_dev)
ssi_sysfs_fini();
#endif
- /* Mask all interrupts */
- WRITE_REGISTER(drvdata->cc_base + CC_REG_OFFSET(HOST_RGF, HOST_IMR),
- 0xFFFFFFFF);
+ fini_cc_regs(drvdata);
+ cc_clk_off(drvdata);
free_irq(drvdata->res_irq->start, drvdata);
drvdata->res_irq = NULL;
- fini_cc_regs(drvdata);
-
- if (drvdata->cc_base != NULL) {
+ if (drvdata->cc_base) {
iounmap(drvdata->cc_base);
release_mem_region(drvdata->res_mem->start,
resource_size(drvdata->res_mem));
@@ -475,11 +480,38 @@ static void cleanup_cc_resources(struct platform_device *plat_dev)
dev_set_drvdata(&plat_dev->dev, NULL);
}
+int cc_clk_on(struct ssi_drvdata *drvdata)
+{
+ struct clk *clk = drvdata->clk;
+ int rc;
+
+ if (IS_ERR(clk))
+ /* Not all devices have a clock associated with CCREE */
+ return 0;
+
+ rc = clk_prepare_enable(clk);
+ if (rc)
+ return rc;
+
+ return 0;
+}
+
+void cc_clk_off(struct ssi_drvdata *drvdata)
+{
+ struct clk *clk = drvdata->clk;
+
+ if (IS_ERR(clk))
+ /* Not all devices have a clock associated with CCREE */
+ return;
+
+ clk_disable_unprepare(clk);
+}
+
static int cc7x_probe(struct platform_device *plat_dev)
{
int rc;
#if defined(CONFIG_ARM) && defined(CC_DEBUG)
- uint32_t ctr, cacheline_size;
+ u32 ctr, cacheline_size;
asm volatile("mrc p15, 0, %0, c0, c0, 1" : "=r" (ctr));
cacheline_size = 4 << ((ctr >> 16) & 0xf);
@@ -489,7 +521,7 @@ static int cc7x_probe(struct platform_device *plat_dev)
asm volatile("mrc p15, 0, %0, c0, c0, 0" : "=r" (ctr));
SSI_LOG_DEBUG("Main ID register (MIDR): Implementer 0x%02X, Arch 0x%01X,"
" Part 0x%03X, Rev r%dp%d\n",
- (ctr>>24), (ctr>>16)&0xF, (ctr>>4)&0xFFF, (ctr>>20)&0xF, ctr&0xF);
+ (ctr >> 24), (ctr >> 16) & 0xF, (ctr >> 4) & 0xFFF, (ctr >> 20) & 0xF, ctr & 0xF);
#endif
/* Map registers space */
@@ -505,29 +537,26 @@ static int cc7x_probe(struct platform_device *plat_dev)
static int cc7x_remove(struct platform_device *plat_dev)
{
SSI_LOG_DEBUG("Releasing cc7x resources...\n");
-
+
cleanup_cc_resources(plat_dev);
SSI_LOG(KERN_INFO, "ARM cc7x_ree device terminated\n");
-#ifdef ENABLE_CYCLE_COUNT
- display_all_stat_db();
-#endif
-
+
return 0;
}
-#if defined (CONFIG_PM_RUNTIME) || defined (CONFIG_PM_SLEEP)
+
+#if defined(CONFIG_PM_RUNTIME) || defined(CONFIG_PM_SLEEP)
static struct dev_pm_ops arm_cc7x_driver_pm = {
SET_RUNTIME_PM_OPS(ssi_power_mgr_runtime_suspend, ssi_power_mgr_runtime_resume, NULL)
};
#endif
-#if defined (CONFIG_PM_RUNTIME) || defined (CONFIG_PM_SLEEP)
+#if defined(CONFIG_PM_RUNTIME) || defined(CONFIG_PM_SLEEP)
#define DX_DRIVER_RUNTIME_PM (&arm_cc7x_driver_pm)
#else
#define DX_DRIVER_RUNTIME_PM NULL
#endif
-
#ifdef CONFIG_OF
static const struct of_device_id arm_cc7x_dev_of_match[] = {
{.compatible = "arm,cryptocell-712-ree"},
diff --git a/drivers/staging/ccree/ssi_driver.h b/drivers/staging/ccree/ssi_driver.h
index 891958b99634..c1ed61f1a202 100644
--- a/drivers/staging/ccree/ssi_driver.h
+++ b/drivers/staging/ccree/ssi_driver.h
@@ -1,21 +1,21 @@
/*
* Copyright (C) 2012-2017 ARM Limited or its affiliates.
- *
+ *
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
- *
+ *
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
- *
+ *
* You should have received a copy of the GNU General Public License
* along with this program; if not, see <http://www.gnu.org/licenses/>.
*/
/* \file ssi_driver.h
- ARM CryptoCell Linux Crypto Driver
+ * ARM CryptoCell Linux Crypto Driver
*/
#ifndef __SSI_DRIVER_H__
@@ -36,29 +36,27 @@
#include <crypto/authenc.h>
#include <crypto/hash.h>
#include <linux/version.h>
-
-#ifndef INT32_MAX /* Missing in Linux kernel */
-#define INT32_MAX 0x7FFFFFFFL
-#endif
+#include <linux/clk.h>
/* Registers definitions from shared/hw/ree_include */
#include "dx_reg_base_host.h"
#include "dx_host.h"
-#define DX_CC_HOST_VIRT /* must be defined before including dx_cc_regs.h */
-#include "cc_hw_queue_defs.h"
#include "cc_regs.h"
#include "dx_reg_common.h"
#include "cc_hal.h"
-#include "ssi_sram_mgr.h"
#define CC_SUPPORT_SHA DX_DEV_SHA_MAX
#include "cc_crypto_ctx.h"
#include "ssi_sysfs.h"
#include "hash_defs.h"
#include "ssi_fips_local.h"
+#include "cc_hw_queue_defs.h"
+#include "ssi_sram_mgr.h"
#define DRV_MODULE_VERSION "3.0"
#define SSI_DEV_NAME_STR "cc715ree"
+#define CC_COHERENT_CACHE_PARAMS 0xEEE
+
#define SSI_CC_HAS_AES_CCM 1
#define SSI_CC_HAS_AES_GCM 1
#define SSI_CC_HAS_AES_XTS 1
@@ -89,12 +87,13 @@
/* Definitions for HW descriptors DIN/DOUT fields */
#define NS_BIT 1
#define AXI_ID 0
-/* AXI_ID is not actually the AXI ID of the transaction but the value of AXI_ID
- field in the HW descriptor. The DMA engine +8 that value. */
+/* AXI_ID is not actually the AXI ID of the transaction but the value of AXI_ID
+ * field in the HW descriptor. The DMA engine +8 that value.
+ */
/* Logging macros */
#define SSI_LOG(level, format, ...) \
- printk(level "cc715ree::%s: " format , __func__, ##__VA_ARGS__)
+ printk(level "cc715ree::%s: " format, __func__, ##__VA_ARGS__)
#define SSI_LOG_ERR(format, ...) SSI_LOG(KERN_ERR, format, ##__VA_ARGS__)
#define SSI_LOG_WARNING(format, ...) SSI_LOG(KERN_WARNING, format, ##__VA_ARGS__)
#define SSI_LOG_NOTICE(format, ...) SSI_LOG(KERN_NOTICE, format, ##__VA_ARGS__)
@@ -108,21 +107,18 @@
#define MIN(a, b) (((a) < (b)) ? (a) : (b))
#define MAX(a, b) (((a) > (b)) ? (a) : (b))
-#define SSI_MAX_IVGEN_DMA_ADDRESSES 3
+#define SSI_MAX_IVGEN_DMA_ADDRESSES 3
struct ssi_crypto_req {
void (*user_cb)(struct device *dev, void *req, void __iomem *cc_base);
void *user_arg;
- dma_addr_t ivgen_dma_addr[SSI_MAX_IVGEN_DMA_ADDRESSES]; /* For the first 'ivgen_dma_addr_len' addresses of this array,
- generated IV would be placed in it by send_request().
- Same generated IV for all addresses! */
+ dma_addr_t ivgen_dma_addr[SSI_MAX_IVGEN_DMA_ADDRESSES];
+ /* For the first 'ivgen_dma_addr_len' addresses of this array,
+ * generated IV would be placed in it by send_request().
+ * Same generated IV for all addresses!
+ */
unsigned int ivgen_dma_addr_len; /* Amount of 'ivgen_dma_addr' elements to be filled. */
unsigned int ivgen_size; /* The generated IV size required, 8/16 B allowed. */
struct completion seq_compl; /* request completion */
-#ifdef ENABLE_CYCLE_COUNT
- enum stat_op op_type;
- cycles_t submit_cycle;
- bool is_monitored_p;
-#endif
};
/**
@@ -136,15 +132,13 @@ struct ssi_drvdata {
struct resource *res_mem;
struct resource *res_irq;
void __iomem *cc_base;
-#ifdef DX_BASE_ENV_REGS
- void __iomem *env_base; /* ARM CryptoCell development FPGAs only */
-#endif
unsigned int irq;
- uint32_t irq_mask;
- uint32_t fw_ver;
+ u32 irq_mask;
+ u32 fw_ver;
/* Calibration time of start/stop
- * monitor descriptors */
- uint32_t monitor_null_cycles;
+ * monitor descriptors
+ */
+ u32 monitor_null_cycles;
struct platform_device *plat_dev;
ssi_sram_addr_t mlli_sram_addr;
struct completion icache_setup_completion;
@@ -156,12 +150,9 @@ struct ssi_drvdata {
void *fips_handle;
void *ivgen_handle;
void *sram_mgr_handle;
-
-#ifdef ENABLE_CYCLE_COUNT
- cycles_t isr_exit_cycles; /* Save for isr-to-tasklet latency */
-#endif
- uint32_t inflight_counter;
-
+ u32 inflight_counter;
+ struct clk *clk;
+ bool coherent;
};
struct ssi_crypto_alg {
@@ -189,7 +180,6 @@ struct ssi_alg_template {
int cipher_mode;
int flow_mode; /* Note: currently, refers to the cipher mode only. */
int auth_mode;
- bool synchronous;
struct ssi_drvdata *drvdata;
};
@@ -199,30 +189,16 @@ struct async_gen_req_ctx {
};
#ifdef DX_DUMP_BYTES
-void dump_byte_array(const char *name, const uint8_t *the_array, unsigned long size);
+void dump_byte_array(const char *name, const u8 *the_array, unsigned long size);
#else
#define dump_byte_array(name, array, size) do { \
} while (0);
#endif
-#ifdef ENABLE_CYCLE_COUNT
-#define DECL_CYCLE_COUNT_RESOURCES cycles_t _last_cycles_read
-#define START_CYCLE_COUNT() do { _last_cycles_read = get_cycles(); } while (0)
-#define END_CYCLE_COUNT(_stat_op_type, _stat_phase) update_host_stat(_stat_op_type, _stat_phase, get_cycles() - _last_cycles_read)
-#define GET_START_CYCLE_COUNT() _last_cycles_read
-#define START_CYCLE_COUNT_AT(_var) do { _var = get_cycles(); } while(0)
-#define END_CYCLE_COUNT_AT(_var, _stat_op_type, _stat_phase) update_host_stat(_stat_op_type, _stat_phase, get_cycles() - _var)
-#else
-#define DECL_CYCLE_COUNT_RESOURCES
-#define START_CYCLE_COUNT() do { } while (0)
-#define END_CYCLE_COUNT(_stat_op_type, _stat_phase) do { } while (0)
-#define GET_START_CYCLE_COUNT() 0
-#define START_CYCLE_COUNT_AT(_var) do { } while (0)
-#define END_CYCLE_COUNT_AT(_var, _stat_op_type, _stat_phase) do { } while (0)
-#endif /*ENABLE_CYCLE_COUNT*/
-
int init_cc_regs(struct ssi_drvdata *drvdata, bool is_probe);
void fini_cc_regs(struct ssi_drvdata *drvdata);
+int cc_clk_on(struct ssi_drvdata *drvdata);
+void cc_clk_off(struct ssi_drvdata *drvdata);
#endif /*__SSI_DRIVER_H__*/
diff --git a/drivers/staging/ccree/ssi_fips.c b/drivers/staging/ccree/ssi_fips.c
index 50f748511979..fdc40f38332a 100644
--- a/drivers/staging/ccree/ssi_fips.c
+++ b/drivers/staging/ccree/ssi_fips.c
@@ -1,42 +1,39 @@
/*
* Copyright (C) 2012-2017 ARM Limited or its affiliates.
- *
+ *
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
- *
+ *
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
- *
+ *
* You should have received a copy of the GNU General Public License
* along with this program; if not, see <http://www.gnu.org/licenses/>.
*/
-
/**************************************************************
-This file defines the driver FIPS APIs *
-***************************************************************/
+ * This file defines the driver FIPS APIs *
+ **************************************************************/
#include <linux/module.h>
#include "ssi_fips.h"
-
-extern int ssi_fips_ext_get_state(ssi_fips_state_t *p_state);
-extern int ssi_fips_ext_get_error(ssi_fips_error_t *p_err);
+extern int ssi_fips_ext_get_state(enum cc_fips_state_t *p_state);
+extern int ssi_fips_ext_get_error(enum cc_fips_error *p_err);
/*
-This function returns the REE FIPS state.
-It should be called by kernel module.
-*/
-int ssi_fips_get_state(ssi_fips_state_t *p_state)
+ * This function returns the REE FIPS state.
+ * It should be called by kernel module.
+ */
+int ssi_fips_get_state(enum cc_fips_state_t *p_state)
{
- int rc = 0;
+ int rc = 0;
- if (p_state == NULL) {
+ if (!p_state)
return -EINVAL;
- }
rc = ssi_fips_ext_get_state(p_state);
@@ -46,16 +43,15 @@ int ssi_fips_get_state(ssi_fips_state_t *p_state)
EXPORT_SYMBOL(ssi_fips_get_state);
/*
-This function returns the REE FIPS error.
-It should be called by kernel module.
-*/
-int ssi_fips_get_error(ssi_fips_error_t *p_err)
+ * This function returns the REE FIPS error.
+ * It should be called by kernel module.
+ */
+int ssi_fips_get_error(enum cc_fips_error *p_err)
{
- int rc = 0;
+ int rc = 0;
- if (p_err == NULL) {
+ if (!p_err)
return -EINVAL;
- }
rc = ssi_fips_ext_get_error(p_err);
diff --git a/drivers/staging/ccree/ssi_fips.h b/drivers/staging/ccree/ssi_fips.h
index 19bcdeb34308..4f5c6a9a8363 100644
--- a/drivers/staging/ccree/ssi_fips.h
+++ b/drivers/staging/ccree/ssi_fips.h
@@ -1,15 +1,15 @@
/*
* Copyright (C) 2012-2017 ARM Limited or its affiliates.
- *
+ *
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
- *
+ *
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
- *
+ *
* You should have received a copy of the GNU General Public License
* along with this program; if not, see <http://www.gnu.org/licenses/>.
*/
@@ -17,26 +17,19 @@
#ifndef __SSI_FIPS_H__
#define __SSI_FIPS_H__
+/*!
+ * @file
+ * @brief This file contains FIPS related defintions and APIs.
+ */
-#ifndef INT32_MAX /* Missing in Linux kernel */
-#define INT32_MAX 0x7FFFFFFFL
-#endif
-
-
-/*!
-@file
-@brief This file contains FIPS related defintions and APIs.
-*/
-
-typedef enum ssi_fips_state {
- CC_FIPS_STATE_NOT_SUPPORTED = 0,
- CC_FIPS_STATE_SUPPORTED,
- CC_FIPS_STATE_ERROR,
- CC_FIPS_STATE_RESERVE32B = INT32_MAX
-} ssi_fips_state_t;
-
+enum cc_fips_state {
+ CC_FIPS_STATE_NOT_SUPPORTED = 0,
+ CC_FIPS_STATE_SUPPORTED,
+ CC_FIPS_STATE_ERROR,
+ CC_FIPS_STATE_RESERVE32B = S32_MAX
+};
-typedef enum ssi_fips_error {
+enum cc_fips_error {
CC_REE_FIPS_ERROR_OK = 0,
CC_REE_FIPS_ERROR_GENERAL,
CC_REE_FIPS_ERROR_FROM_TEE,
@@ -58,13 +51,11 @@ typedef enum ssi_fips_error {
CC_REE_FIPS_ERROR_HMAC_SHA256_PUT,
CC_REE_FIPS_ERROR_HMAC_SHA512_PUT,
CC_REE_FIPS_ERROR_ROM_CHECKSUM,
- CC_REE_FIPS_ERROR_RESERVE32B = INT32_MAX
-} ssi_fips_error_t;
-
-
+ CC_REE_FIPS_ERROR_RESERVE32B = S32_MAX
+};
-int ssi_fips_get_state(ssi_fips_state_t *p_state);
-int ssi_fips_get_error(ssi_fips_error_t *p_err);
+int ssi_fips_get_state(enum cc_fips_state *p_state);
+int ssi_fips_get_error(enum cc_fips_error *p_err);
#endif /*__SSI_FIPS_H__*/
diff --git a/drivers/staging/ccree/ssi_fips_data.h b/drivers/staging/ccree/ssi_fips_data.h
index 3fddd8f74e07..c41671dbee40 100644
--- a/drivers/staging/ccree/ssi_fips_data.h
+++ b/drivers/staging/ccree/ssi_fips_data.h
@@ -1,67 +1,66 @@
/*
* Copyright (C) 2012-2017 ARM Limited or its affiliates.
- *
+ *
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
- *
+ *
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
- *
+ *
* You should have received a copy of the GNU General Public License
* along with this program; if not, see <http://www.gnu.org/licenses/>.
*/
/*
-The test vectors were taken from:
-
-* AES
-NIST Special Publication 800-38A 2001 Edition
-Recommendation for Block Cipher Modes of Operation
-http://csrc.nist.gov/publications/nistpubs/800-38a/sp800-38a.pdf
-Appendix F: Example Vectors for Modes of Operation of the AES
-
-* AES CTS
-Advanced Encryption Standard (AES) Encryption for Kerberos 5
-February 2005
-https://tools.ietf.org/html/rfc3962#appendix-B
-B. Sample Test Vectors
-
-* AES XTS
-http://csrc.nist.gov/groups/STM/cavp/#08
-http://csrc.nist.gov/groups/STM/cavp/documents/aes/XTSTestVectors.zip
-
-* AES CMAC
-http://csrc.nist.gov/groups/STM/cavp/index.html#07
-http://csrc.nist.gov/groups/STM/cavp/documents/mac/cmactestvectors.zip
-
-* AES-CCM
-http://csrc.nist.gov/groups/STM/cavp/#07
-http://csrc.nist.gov/groups/STM/cavp/documents/mac/ccmtestvectors.zip
-
-* AES-GCM
-http://csrc.nist.gov/groups/STM/cavp/documents/mac/gcmtestvectors.zip
-
-* Triple-DES
-NIST Special Publication 800-67 January 2012
-Recommendation for the Triple Data Encryption Algorithm (TDEA) Block Cipher
-http://csrc.nist.gov/publications/nistpubs/800-67-Rev1/SP-800-67-Rev1.pdf
-APPENDIX B: EXAMPLE OF TDEA FORWARD AND INVERSE CIPHER OPERATIONS
-and
-http://csrc.nist.gov/groups/STM/cavp/#01
-http://csrc.nist.gov/groups/STM/cavp/documents/des/tdesmct_intermediate.zip
-
-* HASH
-http://csrc.nist.gov/groups/STM/cavp/#03
-http://csrc.nist.gov/groups/STM/cavp/documents/shs/shabytetestvectors.zip
-
-* HMAC
-http://csrc.nist.gov/groups/STM/cavp/#07
-http://csrc.nist.gov/groups/STM/cavp/documents/mac/hmactestvectors.zip
-
-*/
+ * The test vectors were taken from:
+ *
+ * * AES
+ * NIST Special Publication 800-38A 2001 Edition
+ * Recommendation for Block Cipher Modes of Operation
+ * http://csrc.nist.gov/publications/nistpubs/800-38a/sp800-38a.pdf
+ * Appendix F: Example Vectors for Modes of Operation of the AES
+ *
+ * * AES CTS
+ * Advanced Encryption Standard (AES) Encryption for Kerberos 5
+ * February 2005
+ * https://tools.ietf.org/html/rfc3962#appendix-B
+ * B. Sample Test Vectors
+ *
+ * * AES XTS
+ * http://csrc.nist.gov/groups/STM/cavp/#08
+ * http://csrc.nist.gov/groups/STM/cavp/documents/aes/XTSTestVectors.zip
+ *
+ * * AES CMAC
+ * http://csrc.nist.gov/groups/STM/cavp/index.html#07
+ * http://csrc.nist.gov/groups/STM/cavp/documents/mac/cmactestvectors.zip
+ *
+ * * AES-CCM
+ * http://csrc.nist.gov/groups/STM/cavp/#07
+ * http://csrc.nist.gov/groups/STM/cavp/documents/mac/ccmtestvectors.zip
+ *
+ * * AES-GCM
+ * http://csrc.nist.gov/groups/STM/cavp/documents/mac/gcmtestvectors.zip
+ *
+ * * Triple-DES
+ * NIST Special Publication 800-67 January 2012
+ * Recommendation for the Triple Data Encryption Algorithm (TDEA) Block Cipher
+ * http://csrc.nist.gov/publications/nistpubs/800-67-Rev1/SP-800-67-Rev1.pdf
+ * APPENDIX B: EXAMPLE OF TDEA FORWARD AND INVERSE CIPHER OPERATIONS
+ * and
+ * http://csrc.nist.gov/groups/STM/cavp/#01
+ * http://csrc.nist.gov/groups/STM/cavp/documents/des/tdesmct_intermediate.zip
+ *
+ * * HASH
+ * http://csrc.nist.gov/groups/STM/cavp/#03
+ * http://csrc.nist.gov/groups/STM/cavp/documents/shs/shabytetestvectors.zip
+ *
+ * * HMAC
+ * http://csrc.nist.gov/groups/STM/cavp/#07
+ * http://csrc.nist.gov/groups/STM/cavp/documents/mac/hmactestvectors.zip
+ */
/* NIST AES */
#define AES_128_BIT_KEY_SIZE 16
@@ -86,19 +85,18 @@ http://csrc.nist.gov/groups/STM/cavp/documents/mac/hmactestvectors.zip
#define NIST_AES_CBC_IV { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f }
#define NIST_AES_128_CBC_CIPHER { 0x76, 0x49, 0xab, 0xac, 0x81, 0x19, 0xb2, 0x46, 0xce, 0xe9, 0x8e, 0x9b, 0x12, 0xe9, 0x19, 0x7d }
-#define NIST_AES_192_CBC_CIPHER { 0x4f, 0x02, 0x1d, 0xb2, 0x43, 0xbc, 0x63, 0x3d, 0x71, 0x78, 0x18, 0x3a, 0x9f, 0xa0, 0x71, 0xe8 }
-#define NIST_AES_256_CBC_CIPHER { 0xf5, 0x8c, 0x4c, 0x04, 0xd6, 0xe5, 0xf1, 0xba, 0x77, 0x9e, 0xab, 0xfb, 0x5f, 0x7b, 0xfb, 0xd6 }
+#define NIST_AES_192_CBC_CIPHER { 0x4f, 0x02, 0x1d, 0xb2, 0x43, 0xbc, 0x63, 0x3d, 0x71, 0x78, 0x18, 0x3a, 0x9f, 0xa0, 0x71, 0xe8 }
+#define NIST_AES_256_CBC_CIPHER { 0xf5, 0x8c, 0x4c, 0x04, 0xd6, 0xe5, 0xf1, 0xba, 0x77, 0x9e, 0xab, 0xfb, 0x5f, 0x7b, 0xfb, 0xd6 }
#define NIST_AES_OFB_IV { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f }
#define NIST_AES_128_OFB_CIPHER { 0x3b, 0x3f, 0xd9, 0x2e, 0xb7, 0x2d, 0xad, 0x20, 0x33, 0x34, 0x49, 0xf8, 0xe8, 0x3c, 0xfb, 0x4a }
-#define NIST_AES_192_OFB_CIPHER { 0xcd, 0xc8, 0x0d, 0x6f, 0xdd, 0xf1, 0x8c, 0xab, 0x34, 0xc2, 0x59, 0x09, 0xc9, 0x9a, 0x41, 0x74 }
+#define NIST_AES_192_OFB_CIPHER { 0xcd, 0xc8, 0x0d, 0x6f, 0xdd, 0xf1, 0x8c, 0xab, 0x34, 0xc2, 0x59, 0x09, 0xc9, 0x9a, 0x41, 0x74 }
#define NIST_AES_256_OFB_CIPHER { 0xdc, 0x7e, 0x84, 0xbf, 0xda, 0x79, 0x16, 0x4b, 0x7e, 0xcd, 0x84, 0x86, 0x98, 0x5d, 0x38, 0x60 }
#define NIST_AES_CTR_IV { 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff }
#define NIST_AES_128_CTR_CIPHER { 0x87, 0x4d, 0x61, 0x91, 0xb6, 0x20, 0xe3, 0x26, 0x1b, 0xef, 0x68, 0x64, 0x99, 0x0d, 0xb6, 0xce }
-#define NIST_AES_192_CTR_CIPHER { 0x1a, 0xbc, 0x93, 0x24, 0x17, 0x52, 0x1c, 0xa2, 0x4f, 0x2b, 0x04, 0x59, 0xfe, 0x7e, 0x6e, 0x0b }
-#define NIST_AES_256_CTR_CIPHER { 0x60, 0x1e, 0xc3, 0x13, 0x77, 0x57, 0x89, 0xa5, 0xb7, 0xa7, 0xf5, 0x04, 0xbb, 0xf3, 0xd2, 0x28 }
-
+#define NIST_AES_192_CTR_CIPHER { 0x1a, 0xbc, 0x93, 0x24, 0x17, 0x52, 0x1c, 0xa2, 0x4f, 0x2b, 0x04, 0x59, 0xfe, 0x7e, 0x6e, 0x0b }
+#define NIST_AES_256_CTR_CIPHER { 0x60, 0x1e, 0xc3, 0x13, 0x77, 0x57, 0x89, 0xa5, 0xb7, 0xa7, 0xf5, 0x04, 0xbb, 0xf3, 0xd2, 0x28 }
#define RFC3962_AES_128_KEY { 0x63, 0x68, 0x69, 0x63, 0x6b, 0x65, 0x6e, 0x20, 0x74, 0x65, 0x72, 0x69, 0x79, 0x61, 0x6b, 0x69 }
#define RFC3962_AES_VECTOR_SIZE 17
@@ -106,13 +104,12 @@ http://csrc.nist.gov/groups/STM/cavp/documents/mac/hmactestvectors.zip
#define RFC3962_AES_CBC_CTS_IV { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }
#define RFC3962_AES_128_CBC_CTS_CIPHER { 0xc6, 0x35, 0x35, 0x68, 0xf2, 0xbf, 0x8c, 0xb4, 0xd8, 0xa5, 0x80, 0x36, 0x2d, 0xa7, 0xff, 0x7f, 0x97 }
-
#define NIST_AES_256_XTS_KEY { 0xa1, 0xb9, 0x0c, 0xba, 0x3f, 0x06, 0xac, 0x35, 0x3b, 0x2c, 0x34, 0x38, 0x76, 0x08, 0x17, 0x62, \
0x09, 0x09, 0x23, 0x02, 0x6e, 0x91, 0x77, 0x18, 0x15, 0xf2, 0x9d, 0xab, 0x01, 0x93, 0x2f, 0x2f }
#define NIST_AES_256_XTS_IV { 0x4f, 0xae, 0xf7, 0x11, 0x7c, 0xda, 0x59, 0xc6, 0x6e, 0x4b, 0x92, 0x01, 0x3e, 0x76, 0x8a, 0xd5 }
#define NIST_AES_256_XTS_VECTOR_SIZE 16
-#define NIST_AES_256_XTS_PLAIN { 0xeb, 0xab, 0xce, 0x95, 0xb1, 0x4d, 0x3c, 0x8d, 0x6f, 0xb3, 0x50, 0x39, 0x07, 0x90, 0x31, 0x1c }
-#define NIST_AES_256_XTS_CIPHER { 0x77, 0x8a, 0xe8, 0xb4, 0x3c, 0xb9, 0x8d, 0x5a, 0x82, 0x50, 0x81, 0xd5, 0xbe, 0x47, 0x1c, 0x63 }
+#define NIST_AES_256_XTS_PLAIN { 0xeb, 0xab, 0xce, 0x95, 0xb1, 0x4d, 0x3c, 0x8d, 0x6f, 0xb3, 0x50, 0x39, 0x07, 0x90, 0x31, 0x1c }
+#define NIST_AES_256_XTS_CIPHER { 0x77, 0x8a, 0xe8, 0xb4, 0x3c, 0xb9, 0x8d, 0x5a, 0x82, 0x50, 0x81, 0xd5, 0xbe, 0x47, 0x1c, 0x63 }
#define NIST_AES_512_XTS_KEY { 0x1e, 0xa6, 0x61, 0xc5, 0x8d, 0x94, 0x3a, 0x0e, 0x48, 0x01, 0xe4, 0x2f, 0x4b, 0x09, 0x47, 0x14, \
0x9e, 0x7f, 0x9f, 0x8e, 0x3e, 0x68, 0xd0, 0xc7, 0x50, 0x52, 0x10, 0xbd, 0x31, 0x1a, 0x0e, 0x7c, \
@@ -121,10 +118,9 @@ http://csrc.nist.gov/groups/STM/cavp/documents/mac/hmactestvectors.zip
#define NIST_AES_512_XTS_IV { 0xad, 0xf8, 0xd9, 0x26, 0x27, 0x46, 0x4a, 0xd2, 0xf0, 0x42, 0x8e, 0x84, 0xa9, 0xf8, 0x75, 0x64, }
#define NIST_AES_512_XTS_VECTOR_SIZE 32
#define NIST_AES_512_XTS_PLAIN { 0x2e, 0xed, 0xea, 0x52, 0xcd, 0x82, 0x15, 0xe1, 0xac, 0xc6, 0x47, 0xe8, 0x10, 0xbb, 0xc3, 0x64, \
- 0x2e, 0x87, 0x28, 0x7f, 0x8d, 0x2e, 0x57, 0xe3, 0x6c, 0x0a, 0x24, 0xfb, 0xc1, 0x2a, 0x20, 0x2e }
+ 0x2e, 0x87, 0x28, 0x7f, 0x8d, 0x2e, 0x57, 0xe3, 0x6c, 0x0a, 0x24, 0xfb, 0xc1, 0x2a, 0x20, 0x2e }
#define NIST_AES_512_XTS_CIPHER { 0xcb, 0xaa, 0xd0, 0xe2, 0xf6, 0xce, 0xa3, 0xf5, 0x0b, 0x37, 0xf9, 0x34, 0xd4, 0x6a, 0x9b, 0x13, \
- 0x0b, 0x9d, 0x54, 0xf0, 0x7e, 0x34, 0xf3, 0x6a, 0xf7, 0x93, 0xe8, 0x6f, 0x73, 0xc6, 0xd7, 0xdb }
-
+ 0x0b, 0x9d, 0x54, 0xf0, 0x7e, 0x34, 0xf3, 0x6a, 0xf7, 0x93, 0xe8, 0x6f, 0x73, 0xc6, 0xd7, 0xdb }
/* NIST AES-CMAC */
#define NIST_AES_128_CMAC_KEY { 0x67, 0x08, 0xc9, 0x88, 0x7b, 0x84, 0x70, 0x84, 0xf1, 0x23, 0xd3, 0xdd, 0x9c, 0x3a, 0x81, 0x36 }
@@ -148,27 +144,25 @@ http://csrc.nist.gov/groups/STM/cavp/documents/mac/hmactestvectors.zip
#define NIST_AES_256_CMAC_VECTOR_SIZE 16
#define NIST_AES_256_CMAC_OUTPUT_SIZE 10
-
/* NIST TDES */
#define TDES_NUM_OF_KEYS 3
#define NIST_TDES_VECTOR_SIZE 8
#define NIST_TDES_IV_SIZE 8
-#define NIST_TDES_ECB_IV { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }
+#define NIST_TDES_ECB_IV { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }
#define NIST_TDES_ECB3_KEY { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, \
0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, 0x01, \
0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, 0x01, 0x23 }
-#define NIST_TDES_ECB3_PLAIN_DATA { 0x54, 0x68, 0x65, 0x20, 0x71, 0x75, 0x66, 0x63 }
-#define NIST_TDES_ECB3_CIPHER { 0xa8, 0x26, 0xfd, 0x8c, 0xe5, 0x3b, 0x85, 0x5f }
+#define NIST_TDES_ECB3_PLAIN_DATA { 0x54, 0x68, 0x65, 0x20, 0x71, 0x75, 0x66, 0x63 }
+#define NIST_TDES_ECB3_CIPHER { 0xa8, 0x26, 0xfd, 0x8c, 0xe5, 0x3b, 0x85, 0x5f }
-#define NIST_TDES_CBC3_IV { 0xf8, 0xee, 0xe1, 0x35, 0x9c, 0x6e, 0x54, 0x40 }
+#define NIST_TDES_CBC3_IV { 0xf8, 0xee, 0xe1, 0x35, 0x9c, 0x6e, 0x54, 0x40 }
#define NIST_TDES_CBC3_KEY { 0xe9, 0xda, 0x37, 0xf8, 0xdc, 0x97, 0x6d, 0x5b, \
0xb6, 0x8c, 0x04, 0xe3, 0xec, 0x98, 0x20, 0x15, \
0xf4, 0x0e, 0x08, 0xb5, 0x97, 0x29, 0xf2, 0x8f }
-#define NIST_TDES_CBC3_PLAIN_DATA { 0x3b, 0xb7, 0xa7, 0xdb, 0xa3, 0xd5, 0x92, 0x91 }
-#define NIST_TDES_CBC3_CIPHER { 0x5b, 0x84, 0x24, 0xd2, 0x39, 0x3e, 0x55, 0xa2 }
-
+#define NIST_TDES_CBC3_PLAIN_DATA { 0x3b, 0xb7, 0xa7, 0xdb, 0xa3, 0xd5, 0x92, 0x91 }
+#define NIST_TDES_CBC3_CIPHER { 0x5b, 0x84, 0x24, 0xd2, 0x39, 0x3e, 0x55, 0xa2 }
/* NIST AES-CCM */
#define NIST_AESCCM_128_BIT_KEY_SIZE 16
@@ -208,7 +202,6 @@ http://csrc.nist.gov/groups/STM/cavp/documents/mac/hmactestvectors.zip
#define NIST_AESCCM_256_CIPHER { 0xcc, 0x17, 0xbf, 0x87, 0x94, 0xc8, 0x43, 0x45, 0x7d, 0x89, 0x93, 0x91, 0x89, 0x8e, 0xd2, 0x2a }
#define NIST_AESCCM_256_MAC { 0x6f, 0x9d, 0x28, 0xfc, 0xb6, 0x42, 0x34, 0xe1, 0xcd, 0x79, 0x3c, 0x41, 0x44, 0xf1, 0xda, 0x50 }
-
/* NIST AES-GCM */
#define NIST_AESGCM_128_BIT_KEY_SIZE 16
#define NIST_AESGCM_192_BIT_KEY_SIZE 24
@@ -242,7 +235,6 @@ http://csrc.nist.gov/groups/STM/cavp/documents/mac/hmactestvectors.zip
#define NIST_AESGCM_256_CIPHER { 0x42, 0x6e, 0x0e, 0xfc, 0x69, 0x3b, 0x7b, 0xe1, 0xf3, 0x01, 0x8d, 0xb7, 0xdd, 0xbb, 0x7e, 0x4d }
#define NIST_AESGCM_256_MAC { 0xee, 0x82, 0x57, 0x79, 0x5b, 0xe6, 0xa1, 0x16, 0x4d, 0x7e, 0x1d, 0x2d, 0x6c, 0xac, 0x77, 0xa7 }
-
/* NIST HASH */
#define NIST_SHA_MSG_SIZE 16
@@ -260,7 +252,6 @@ http://csrc.nist.gov/groups/STM/cavp/documents/mac/hmactestvectors.zip
0x8f, 0x2b, 0xa9, 0x1c, 0x3a, 0x9f, 0x0c, 0x16, 0x53, 0xc4, 0xbf, 0x0a, 0xda, 0x35, 0x64, 0x55, \
0xea, 0x36, 0xfd, 0x31, 0xf8, 0xe7, 0x3e, 0x39, 0x51, 0xca, 0xd4, 0xeb, 0xba, 0x8c, 0x6e, 0x04 }
-
/* NIST HMAC */
#define NIST_HMAC_MSG_SIZE 128
diff --git a/drivers/staging/ccree/ssi_fips_ext.c b/drivers/staging/ccree/ssi_fips_ext.c
index 2ac432fe1233..e7bf1843f60c 100644
--- a/drivers/staging/ccree/ssi_fips_ext.c
+++ b/drivers/staging/ccree/ssi_fips_ext.c
@@ -1,49 +1,47 @@
/*
* Copyright (C) 2012-2017 ARM Limited or its affiliates.
- *
+ *
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
- *
+ *
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
- *
+ *
* You should have received a copy of the GNU General Public License
* along with this program; if not, see <http://www.gnu.org/licenses/>.
*/
/**************************************************************
-This file defines the driver FIPS functions that should be
-implemented by the driver user. Current implementation is sample code only.
-***************************************************************/
+ * This file defines the driver FIPS functions that should be
+ * implemented by the driver user. Current implementation is sample code only.
+ ***************************************************************/
#include <linux/module.h>
#include "ssi_fips_local.h"
#include "ssi_driver.h"
-
static bool tee_error;
module_param(tee_error, bool, 0644);
MODULE_PARM_DESC(tee_error, "Simulate TEE library failure flag: 0 - no error (default), 1 - TEE error occured ");
-static ssi_fips_state_t fips_state = CC_FIPS_STATE_NOT_SUPPORTED;
-static ssi_fips_error_t fips_error = CC_REE_FIPS_ERROR_OK;
+static enum cc_fips_state_t fips_state = CC_FIPS_STATE_NOT_SUPPORTED;
+static enum cc_fips_error fips_error = CC_REE_FIPS_ERROR_OK;
/*
-This function returns the FIPS REE state.
-The function should be implemented by the driver user, depends on where .
-the state value is stored.
-The reference code uses global variable.
-*/
-int ssi_fips_ext_get_state(ssi_fips_state_t *p_state)
+ * This function returns the FIPS REE state.
+ * The function should be implemented by the driver user, depends on where
+ * the state value is stored.
+ * The reference code uses global variable.
+ */
+int ssi_fips_ext_get_state(enum cc_fips_state_t *p_state)
{
- int rc = 0;
+ int rc = 0;
- if (p_state == NULL) {
+ if (!p_state)
return -EINVAL;
- }
*p_state = fips_state;
@@ -51,18 +49,17 @@ int ssi_fips_ext_get_state(ssi_fips_state_t *p_state)
}
/*
-This function returns the FIPS REE error.
-The function should be implemented by the driver user, depends on where .
-the error value is stored.
-The reference code uses global variable.
-*/
-int ssi_fips_ext_get_error(ssi_fips_error_t *p_err)
+ * This function returns the FIPS REE error.
+ * The function should be implemented by the driver user, depends on where
+ * the error value is stored.
+ * The reference code uses global variable.
+ */
+int ssi_fips_ext_get_error(enum cc_fips_error *p_err)
{
- int rc = 0;
+ int rc = 0;
- if (p_err == NULL) {
+ if (!p_err)
return -EINVAL;
- }
*p_err = fips_error;
@@ -70,27 +67,26 @@ int ssi_fips_ext_get_error(ssi_fips_error_t *p_err)
}
/*
-This function sets the FIPS REE state.
-The function should be implemented by the driver user, depends on where .
-the state value is stored.
-The reference code uses global variable.
-*/
-int ssi_fips_ext_set_state(ssi_fips_state_t state)
+ * This function sets the FIPS REE state.
+ * The function should be implemented by the driver user, depends on where
+ * the state value is stored.
+ * The reference code uses global variable.
+ */
+int ssi_fips_ext_set_state(enum cc_fips_state_t state)
{
fips_state = state;
return 0;
}
/*
-This function sets the FIPS REE error.
-The function should be implemented by the driver user, depends on where .
-the error value is stored.
-The reference code uses global variable.
-*/
-int ssi_fips_ext_set_error(ssi_fips_error_t err)
+ * This function sets the FIPS REE error.
+ * The function should be implemented by the driver user, depends on where
+ * the error value is stored.
+ * The reference code uses global variable.
+ */
+int ssi_fips_ext_set_error(enum cc_fips_error err)
{
fips_error = err;
return 0;
}
-
diff --git a/drivers/staging/ccree/ssi_fips_ll.c b/drivers/staging/ccree/ssi_fips_ll.c
index d573574bbb98..3557e20c9e36 100644
--- a/drivers/staging/ccree/ssi_fips_ll.c
+++ b/drivers/staging/ccree/ssi_fips_ll.c
@@ -1,23 +1,23 @@
/*
* Copyright (C) 2012-2017 ARM Limited or its affiliates.
- *
+ *
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
- *
+ *
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
- *
+ *
* You should have received a copy of the GNU General Public License
* along with this program; if not, see <http://www.gnu.org/licenses/>.
*/
/**************************************************************
-This file defines the driver FIPS Low Level implmentaion functions,
-that executes the KAT.
-***************************************************************/
+ * This file defines the driver FIPS Low Level implmentaion functions,
+ * that executes the KAT.
+ ***************************************************************/
#include <linux/kernel.h>
#include "ssi_driver.h"
@@ -27,151 +27,143 @@ that executes the KAT.
#include "ssi_hash.h"
#include "ssi_request_mgr.h"
-
-static const uint32_t digest_len_init[] = {
+static const u32 digest_len_init[] = {
0x00000040, 0x00000000, 0x00000000, 0x00000000 };
-static const uint32_t sha1_init[] = {
+static const u32 sha1_init[] = {
SHA1_H4, SHA1_H3, SHA1_H2, SHA1_H1, SHA1_H0 };
-static const uint32_t sha256_init[] = {
+static const u32 sha256_init[] = {
SHA256_H7, SHA256_H6, SHA256_H5, SHA256_H4,
SHA256_H3, SHA256_H2, SHA256_H1, SHA256_H0 };
#if (CC_SUPPORT_SHA > 256)
-static const uint32_t digest_len_sha512_init[] = {
+static const u32 digest_len_sha512_init[] = {
0x00000080, 0x00000000, 0x00000000, 0x00000000 };
-static const uint64_t sha512_init[] = {
+static const u64 sha512_init[] = {
SHA512_H7, SHA512_H6, SHA512_H5, SHA512_H4,
SHA512_H3, SHA512_H2, SHA512_H1, SHA512_H0 };
#endif
-
#define NIST_CIPHER_AES_MAX_VECTOR_SIZE 32
struct fips_cipher_ctx {
- uint8_t iv[CC_AES_IV_SIZE];
- uint8_t key[AES_512_BIT_KEY_SIZE];
- uint8_t din[NIST_CIPHER_AES_MAX_VECTOR_SIZE];
- uint8_t dout[NIST_CIPHER_AES_MAX_VECTOR_SIZE];
+ u8 iv[CC_AES_IV_SIZE];
+ u8 key[AES_512_BIT_KEY_SIZE];
+ u8 din[NIST_CIPHER_AES_MAX_VECTOR_SIZE];
+ u8 dout[NIST_CIPHER_AES_MAX_VECTOR_SIZE];
};
typedef struct _FipsCipherData {
- uint8_t isAes;
- uint8_t key[AES_512_BIT_KEY_SIZE];
+ u8 isAes;
+ u8 key[AES_512_BIT_KEY_SIZE];
size_t keySize;
- uint8_t iv[CC_AES_IV_SIZE];
+ u8 iv[CC_AES_IV_SIZE];
enum drv_crypto_direction direction;
enum drv_cipher_mode oprMode;
- uint8_t dataIn[NIST_CIPHER_AES_MAX_VECTOR_SIZE];
- uint8_t dataOut[NIST_CIPHER_AES_MAX_VECTOR_SIZE];
+ u8 dataIn[NIST_CIPHER_AES_MAX_VECTOR_SIZE];
+ u8 dataOut[NIST_CIPHER_AES_MAX_VECTOR_SIZE];
size_t dataInSize;
} FipsCipherData;
-
struct fips_cmac_ctx {
- uint8_t key[AES_256_BIT_KEY_SIZE];
- uint8_t din[NIST_CIPHER_AES_MAX_VECTOR_SIZE];
- uint8_t mac_res[CC_DIGEST_SIZE_MAX];
+ u8 key[AES_256_BIT_KEY_SIZE];
+ u8 din[NIST_CIPHER_AES_MAX_VECTOR_SIZE];
+ u8 mac_res[CC_DIGEST_SIZE_MAX];
};
typedef struct _FipsCmacData {
enum drv_crypto_direction direction;
- uint8_t key[AES_256_BIT_KEY_SIZE];
+ u8 key[AES_256_BIT_KEY_SIZE];
size_t key_size;
- uint8_t data_in[NIST_CIPHER_AES_MAX_VECTOR_SIZE];
+ u8 data_in[NIST_CIPHER_AES_MAX_VECTOR_SIZE];
size_t data_in_size;
- uint8_t mac_res[CC_DIGEST_SIZE_MAX];
+ u8 mac_res[CC_DIGEST_SIZE_MAX];
size_t mac_res_size;
} FipsCmacData;
-
struct fips_hash_ctx {
- uint8_t initial_digest[CC_DIGEST_SIZE_MAX];
- uint8_t din[NIST_SHA_MSG_SIZE];
- uint8_t mac_res[CC_DIGEST_SIZE_MAX];
+ u8 initial_digest[CC_DIGEST_SIZE_MAX];
+ u8 din[NIST_SHA_MSG_SIZE];
+ u8 mac_res[CC_DIGEST_SIZE_MAX];
};
typedef struct _FipsHashData {
enum drv_hash_mode hash_mode;
- uint8_t data_in[NIST_SHA_MSG_SIZE];
+ u8 data_in[NIST_SHA_MSG_SIZE];
size_t data_in_size;
- uint8_t mac_res[CC_DIGEST_SIZE_MAX];
+ u8 mac_res[CC_DIGEST_SIZE_MAX];
} FipsHashData;
-
/* note that the hmac key length must be equal or less than block size (block size is 64 up to sha256 and 128 for sha384/512) */
struct fips_hmac_ctx {
- uint8_t initial_digest[CC_DIGEST_SIZE_MAX];
- uint8_t key[CC_HMAC_BLOCK_SIZE_MAX];
- uint8_t k0[CC_HMAC_BLOCK_SIZE_MAX];
- uint8_t digest_bytes_len[HASH_LEN_SIZE];
- uint8_t tmp_digest[CC_DIGEST_SIZE_MAX];
- uint8_t din[NIST_HMAC_MSG_SIZE];
- uint8_t mac_res[CC_DIGEST_SIZE_MAX];
+ u8 initial_digest[CC_DIGEST_SIZE_MAX];
+ u8 key[CC_HMAC_BLOCK_SIZE_MAX];
+ u8 k0[CC_HMAC_BLOCK_SIZE_MAX];
+ u8 digest_bytes_len[HASH_LEN_SIZE];
+ u8 tmp_digest[CC_DIGEST_SIZE_MAX];
+ u8 din[NIST_HMAC_MSG_SIZE];
+ u8 mac_res[CC_DIGEST_SIZE_MAX];
};
typedef struct _FipsHmacData {
enum drv_hash_mode hash_mode;
- uint8_t key[CC_HMAC_BLOCK_SIZE_MAX];
+ u8 key[CC_HMAC_BLOCK_SIZE_MAX];
size_t key_size;
- uint8_t data_in[NIST_HMAC_MSG_SIZE];
+ u8 data_in[NIST_HMAC_MSG_SIZE];
size_t data_in_size;
- uint8_t mac_res[CC_DIGEST_SIZE_MAX];
+ u8 mac_res[CC_DIGEST_SIZE_MAX];
} FipsHmacData;
-
#define FIPS_CCM_B0_A0_ADATA_SIZE (NIST_AESCCM_IV_SIZE + NIST_AESCCM_IV_SIZE + NIST_AESCCM_ADATA_SIZE)
struct fips_ccm_ctx {
- uint8_t b0_a0_adata[FIPS_CCM_B0_A0_ADATA_SIZE];
- uint8_t iv[NIST_AESCCM_IV_SIZE];
- uint8_t ctr_cnt_0[NIST_AESCCM_IV_SIZE];
- uint8_t key[CC_AES_KEY_SIZE_MAX];
- uint8_t din[NIST_AESCCM_TEXT_SIZE];
- uint8_t dout[NIST_AESCCM_TEXT_SIZE];
- uint8_t mac_res[NIST_AESCCM_TAG_SIZE];
+ u8 b0_a0_adata[FIPS_CCM_B0_A0_ADATA_SIZE];
+ u8 iv[NIST_AESCCM_IV_SIZE];
+ u8 ctr_cnt_0[NIST_AESCCM_IV_SIZE];
+ u8 key[CC_AES_KEY_SIZE_MAX];
+ u8 din[NIST_AESCCM_TEXT_SIZE];
+ u8 dout[NIST_AESCCM_TEXT_SIZE];
+ u8 mac_res[NIST_AESCCM_TAG_SIZE];
};
typedef struct _FipsCcmData {
enum drv_crypto_direction direction;
- uint8_t key[CC_AES_KEY_SIZE_MAX];
+ u8 key[CC_AES_KEY_SIZE_MAX];
size_t keySize;
- uint8_t nonce[NIST_AESCCM_NONCE_SIZE];
- uint8_t adata[NIST_AESCCM_ADATA_SIZE];
+ u8 nonce[NIST_AESCCM_NONCE_SIZE];
+ u8 adata[NIST_AESCCM_ADATA_SIZE];
size_t adataSize;
- uint8_t dataIn[NIST_AESCCM_TEXT_SIZE];
+ u8 dataIn[NIST_AESCCM_TEXT_SIZE];
size_t dataInSize;
- uint8_t dataOut[NIST_AESCCM_TEXT_SIZE];
- uint8_t tagSize;
- uint8_t macResOut[NIST_AESCCM_TAG_SIZE];
+ u8 dataOut[NIST_AESCCM_TEXT_SIZE];
+ u8 tagSize;
+ u8 macResOut[NIST_AESCCM_TAG_SIZE];
} FipsCcmData;
-
struct fips_gcm_ctx {
- uint8_t adata[NIST_AESGCM_ADATA_SIZE];
- uint8_t key[CC_AES_KEY_SIZE_MAX];
- uint8_t hkey[CC_AES_KEY_SIZE_MAX];
- uint8_t din[NIST_AESGCM_TEXT_SIZE];
- uint8_t dout[NIST_AESGCM_TEXT_SIZE];
- uint8_t mac_res[NIST_AESGCM_TAG_SIZE];
- uint8_t len_block[AES_BLOCK_SIZE];
- uint8_t iv_inc1[AES_BLOCK_SIZE];
- uint8_t iv_inc2[AES_BLOCK_SIZE];
+ u8 adata[NIST_AESGCM_ADATA_SIZE];
+ u8 key[CC_AES_KEY_SIZE_MAX];
+ u8 hkey[CC_AES_KEY_SIZE_MAX];
+ u8 din[NIST_AESGCM_TEXT_SIZE];
+ u8 dout[NIST_AESGCM_TEXT_SIZE];
+ u8 mac_res[NIST_AESGCM_TAG_SIZE];
+ u8 len_block[AES_BLOCK_SIZE];
+ u8 iv_inc1[AES_BLOCK_SIZE];
+ u8 iv_inc2[AES_BLOCK_SIZE];
};
typedef struct _FipsGcmData {
enum drv_crypto_direction direction;
- uint8_t key[CC_AES_KEY_SIZE_MAX];
+ u8 key[CC_AES_KEY_SIZE_MAX];
size_t keySize;
- uint8_t iv[NIST_AESGCM_IV_SIZE];
- uint8_t adata[NIST_AESGCM_ADATA_SIZE];
+ u8 iv[NIST_AESGCM_IV_SIZE];
+ u8 adata[NIST_AESGCM_ADATA_SIZE];
size_t adataSize;
- uint8_t dataIn[NIST_AESGCM_TEXT_SIZE];
+ u8 dataIn[NIST_AESGCM_TEXT_SIZE];
size_t dataInSize;
- uint8_t dataOut[NIST_AESGCM_TEXT_SIZE];
- uint8_t tagSize;
- uint8_t macResOut[NIST_AESGCM_TAG_SIZE];
+ u8 dataOut[NIST_AESGCM_TEXT_SIZE];
+ u8 tagSize;
+ u8 macResOut[NIST_AESGCM_TAG_SIZE];
} FipsGcmData;
-
typedef union _fips_ctx {
struct fips_cipher_ctx cipher;
struct fips_cmac_ctx cmac;
@@ -181,7 +173,6 @@ typedef union _fips_ctx {
struct fips_gcm_ctx gcm;
} fips_ctx;
-
/* test data tables */
static const FipsCipherData FipsCipherDataTable[] = {
/* AES */
@@ -214,8 +205,8 @@ static const FipsCipherData FipsCipherDataTable[] = {
{ 1, NIST_AES_256_XTS_KEY, CC_AES_256_BIT_KEY_SIZE, NIST_AES_256_XTS_IV, DRV_CRYPTO_DIRECTION_ENCRYPT, DRV_CIPHER_XTS, NIST_AES_256_XTS_PLAIN, NIST_AES_256_XTS_CIPHER, NIST_AES_256_XTS_VECTOR_SIZE },
{ 1, NIST_AES_256_XTS_KEY, CC_AES_256_BIT_KEY_SIZE, NIST_AES_256_XTS_IV, DRV_CRYPTO_DIRECTION_DECRYPT, DRV_CIPHER_XTS, NIST_AES_256_XTS_CIPHER, NIST_AES_256_XTS_PLAIN, NIST_AES_256_XTS_VECTOR_SIZE },
#if (CC_SUPPORT_SHA > 256)
- { 1, NIST_AES_512_XTS_KEY, 2*CC_AES_256_BIT_KEY_SIZE, NIST_AES_512_XTS_IV, DRV_CRYPTO_DIRECTION_ENCRYPT, DRV_CIPHER_XTS, NIST_AES_512_XTS_PLAIN, NIST_AES_512_XTS_CIPHER, NIST_AES_512_XTS_VECTOR_SIZE },
- { 1, NIST_AES_512_XTS_KEY, 2*CC_AES_256_BIT_KEY_SIZE, NIST_AES_512_XTS_IV, DRV_CRYPTO_DIRECTION_DECRYPT, DRV_CIPHER_XTS, NIST_AES_512_XTS_CIPHER, NIST_AES_512_XTS_PLAIN, NIST_AES_512_XTS_VECTOR_SIZE },
+ { 1, NIST_AES_512_XTS_KEY, 2 * CC_AES_256_BIT_KEY_SIZE, NIST_AES_512_XTS_IV, DRV_CRYPTO_DIRECTION_ENCRYPT, DRV_CIPHER_XTS, NIST_AES_512_XTS_PLAIN, NIST_AES_512_XTS_CIPHER, NIST_AES_512_XTS_VECTOR_SIZE },
+ { 1, NIST_AES_512_XTS_KEY, 2 * CC_AES_256_BIT_KEY_SIZE, NIST_AES_512_XTS_IV, DRV_CRYPTO_DIRECTION_DECRYPT, DRV_CIPHER_XTS, NIST_AES_512_XTS_CIPHER, NIST_AES_512_XTS_PLAIN, NIST_AES_512_XTS_VECTOR_SIZE },
#endif
/* DES */
{ 0, NIST_TDES_ECB3_KEY, CC_DRV_DES_TRIPLE_KEY_SIZE, NIST_TDES_ECB_IV, DRV_CRYPTO_DIRECTION_ENCRYPT, DRV_CIPHER_ECB, NIST_TDES_ECB3_PLAIN_DATA, NIST_TDES_ECB3_CIPHER, NIST_TDES_VECTOR_SIZE },
@@ -223,6 +214,7 @@ static const FipsCipherData FipsCipherDataTable[] = {
{ 0, NIST_TDES_CBC3_KEY, CC_DRV_DES_TRIPLE_KEY_SIZE, NIST_TDES_CBC3_IV, DRV_CRYPTO_DIRECTION_ENCRYPT, DRV_CIPHER_CBC, NIST_TDES_CBC3_PLAIN_DATA, NIST_TDES_CBC3_CIPHER, NIST_TDES_VECTOR_SIZE },
{ 0, NIST_TDES_CBC3_KEY, CC_DRV_DES_TRIPLE_KEY_SIZE, NIST_TDES_CBC3_IV, DRV_CRYPTO_DIRECTION_DECRYPT, DRV_CIPHER_CBC, NIST_TDES_CBC3_CIPHER, NIST_TDES_CBC3_PLAIN_DATA, NIST_TDES_VECTOR_SIZE },
};
+
#define FIPS_CIPHER_NUM_OF_TESTS (sizeof(FipsCipherDataTable) / sizeof(FipsCipherData))
static const FipsCmacData FipsCmacDataTable[] = {
@@ -230,56 +222,60 @@ static const FipsCmacData FipsCmacDataTable[] = {
{ DRV_CRYPTO_DIRECTION_ENCRYPT, NIST_AES_192_CMAC_KEY, AES_192_BIT_KEY_SIZE, NIST_AES_192_CMAC_PLAIN_DATA, NIST_AES_192_CMAC_VECTOR_SIZE, NIST_AES_192_CMAC_MAC, NIST_AES_192_CMAC_OUTPUT_SIZE },
{ DRV_CRYPTO_DIRECTION_ENCRYPT, NIST_AES_256_CMAC_KEY, AES_256_BIT_KEY_SIZE, NIST_AES_256_CMAC_PLAIN_DATA, NIST_AES_256_CMAC_VECTOR_SIZE, NIST_AES_256_CMAC_MAC, NIST_AES_256_CMAC_OUTPUT_SIZE },
};
+
#define FIPS_CMAC_NUM_OF_TESTS (sizeof(FipsCmacDataTable) / sizeof(FipsCmacData))
static const FipsHashData FipsHashDataTable[] = {
- { DRV_HASH_SHA1, NIST_SHA_1_MSG, NIST_SHA_MSG_SIZE, NIST_SHA_1_MD },
- { DRV_HASH_SHA256, NIST_SHA_256_MSG, NIST_SHA_MSG_SIZE, NIST_SHA_256_MD },
+ { DRV_HASH_SHA1, NIST_SHA_1_MSG, NIST_SHA_MSG_SIZE, NIST_SHA_1_MD },
+ { DRV_HASH_SHA256, NIST_SHA_256_MSG, NIST_SHA_MSG_SIZE, NIST_SHA_256_MD },
#if (CC_SUPPORT_SHA > 256)
// { DRV_HASH_SHA512, NIST_SHA_512_MSG, NIST_SHA_MSG_SIZE, NIST_SHA_512_MD },
#endif
};
+
#define FIPS_HASH_NUM_OF_TESTS (sizeof(FipsHashDataTable) / sizeof(FipsHashData))
static const FipsHmacData FipsHmacDataTable[] = {
- { DRV_HASH_SHA1, NIST_HMAC_SHA1_KEY, NIST_HMAC_SHA1_KEY_SIZE, NIST_HMAC_SHA1_MSG, NIST_HMAC_MSG_SIZE, NIST_HMAC_SHA1_MD },
- { DRV_HASH_SHA256, NIST_HMAC_SHA256_KEY, NIST_HMAC_SHA256_KEY_SIZE, NIST_HMAC_SHA256_MSG, NIST_HMAC_MSG_SIZE, NIST_HMAC_SHA256_MD },
+ { DRV_HASH_SHA1, NIST_HMAC_SHA1_KEY, NIST_HMAC_SHA1_KEY_SIZE, NIST_HMAC_SHA1_MSG, NIST_HMAC_MSG_SIZE, NIST_HMAC_SHA1_MD },
+ { DRV_HASH_SHA256, NIST_HMAC_SHA256_KEY, NIST_HMAC_SHA256_KEY_SIZE, NIST_HMAC_SHA256_MSG, NIST_HMAC_MSG_SIZE, NIST_HMAC_SHA256_MD },
#if (CC_SUPPORT_SHA > 256)
// { DRV_HASH_SHA512, NIST_HMAC_SHA512_KEY, NIST_HMAC_SHA512_KEY_SIZE, NIST_HMAC_SHA512_MSG, NIST_HMAC_MSG_SIZE, NIST_HMAC_SHA512_MD },
#endif
};
+
#define FIPS_HMAC_NUM_OF_TESTS (sizeof(FipsHmacDataTable) / sizeof(FipsHmacData))
static const FipsCcmData FipsCcmDataTable[] = {
- { DRV_CRYPTO_DIRECTION_ENCRYPT, NIST_AESCCM_128_KEY, NIST_AESCCM_128_BIT_KEY_SIZE, NIST_AESCCM_128_NONCE, NIST_AESCCM_128_ADATA, NIST_AESCCM_ADATA_SIZE, NIST_AESCCM_128_PLAIN_TEXT, NIST_AESCCM_TEXT_SIZE, NIST_AESCCM_128_CIPHER, NIST_AESCCM_TAG_SIZE, NIST_AESCCM_128_MAC },
- { DRV_CRYPTO_DIRECTION_DECRYPT, NIST_AESCCM_128_KEY, NIST_AESCCM_128_BIT_KEY_SIZE, NIST_AESCCM_128_NONCE, NIST_AESCCM_128_ADATA, NIST_AESCCM_ADATA_SIZE, NIST_AESCCM_128_CIPHER, NIST_AESCCM_TEXT_SIZE, NIST_AESCCM_128_PLAIN_TEXT, NIST_AESCCM_TAG_SIZE, NIST_AESCCM_128_MAC },
- { DRV_CRYPTO_DIRECTION_ENCRYPT, NIST_AESCCM_192_KEY, NIST_AESCCM_192_BIT_KEY_SIZE, NIST_AESCCM_192_NONCE, NIST_AESCCM_192_ADATA, NIST_AESCCM_ADATA_SIZE, NIST_AESCCM_192_PLAIN_TEXT, NIST_AESCCM_TEXT_SIZE, NIST_AESCCM_192_CIPHER, NIST_AESCCM_TAG_SIZE, NIST_AESCCM_192_MAC },
- { DRV_CRYPTO_DIRECTION_DECRYPT, NIST_AESCCM_192_KEY, NIST_AESCCM_192_BIT_KEY_SIZE, NIST_AESCCM_192_NONCE, NIST_AESCCM_192_ADATA, NIST_AESCCM_ADATA_SIZE, NIST_AESCCM_192_CIPHER, NIST_AESCCM_TEXT_SIZE, NIST_AESCCM_192_PLAIN_TEXT, NIST_AESCCM_TAG_SIZE, NIST_AESCCM_192_MAC },
- { DRV_CRYPTO_DIRECTION_ENCRYPT, NIST_AESCCM_256_KEY, NIST_AESCCM_256_BIT_KEY_SIZE, NIST_AESCCM_256_NONCE, NIST_AESCCM_256_ADATA, NIST_AESCCM_ADATA_SIZE, NIST_AESCCM_256_PLAIN_TEXT, NIST_AESCCM_TEXT_SIZE, NIST_AESCCM_256_CIPHER, NIST_AESCCM_TAG_SIZE, NIST_AESCCM_256_MAC },
- { DRV_CRYPTO_DIRECTION_DECRYPT, NIST_AESCCM_256_KEY, NIST_AESCCM_256_BIT_KEY_SIZE, NIST_AESCCM_256_NONCE, NIST_AESCCM_256_ADATA, NIST_AESCCM_ADATA_SIZE, NIST_AESCCM_256_CIPHER, NIST_AESCCM_TEXT_SIZE, NIST_AESCCM_256_PLAIN_TEXT, NIST_AESCCM_TAG_SIZE, NIST_AESCCM_256_MAC },
+ { DRV_CRYPTO_DIRECTION_ENCRYPT, NIST_AESCCM_128_KEY, NIST_AESCCM_128_BIT_KEY_SIZE, NIST_AESCCM_128_NONCE, NIST_AESCCM_128_ADATA, NIST_AESCCM_ADATA_SIZE, NIST_AESCCM_128_PLAIN_TEXT, NIST_AESCCM_TEXT_SIZE, NIST_AESCCM_128_CIPHER, NIST_AESCCM_TAG_SIZE, NIST_AESCCM_128_MAC },
+ { DRV_CRYPTO_DIRECTION_DECRYPT, NIST_AESCCM_128_KEY, NIST_AESCCM_128_BIT_KEY_SIZE, NIST_AESCCM_128_NONCE, NIST_AESCCM_128_ADATA, NIST_AESCCM_ADATA_SIZE, NIST_AESCCM_128_CIPHER, NIST_AESCCM_TEXT_SIZE, NIST_AESCCM_128_PLAIN_TEXT, NIST_AESCCM_TAG_SIZE, NIST_AESCCM_128_MAC },
+ { DRV_CRYPTO_DIRECTION_ENCRYPT, NIST_AESCCM_192_KEY, NIST_AESCCM_192_BIT_KEY_SIZE, NIST_AESCCM_192_NONCE, NIST_AESCCM_192_ADATA, NIST_AESCCM_ADATA_SIZE, NIST_AESCCM_192_PLAIN_TEXT, NIST_AESCCM_TEXT_SIZE, NIST_AESCCM_192_CIPHER, NIST_AESCCM_TAG_SIZE, NIST_AESCCM_192_MAC },
+ { DRV_CRYPTO_DIRECTION_DECRYPT, NIST_AESCCM_192_KEY, NIST_AESCCM_192_BIT_KEY_SIZE, NIST_AESCCM_192_NONCE, NIST_AESCCM_192_ADATA, NIST_AESCCM_ADATA_SIZE, NIST_AESCCM_192_CIPHER, NIST_AESCCM_TEXT_SIZE, NIST_AESCCM_192_PLAIN_TEXT, NIST_AESCCM_TAG_SIZE, NIST_AESCCM_192_MAC },
+ { DRV_CRYPTO_DIRECTION_ENCRYPT, NIST_AESCCM_256_KEY, NIST_AESCCM_256_BIT_KEY_SIZE, NIST_AESCCM_256_NONCE, NIST_AESCCM_256_ADATA, NIST_AESCCM_ADATA_SIZE, NIST_AESCCM_256_PLAIN_TEXT, NIST_AESCCM_TEXT_SIZE, NIST_AESCCM_256_CIPHER, NIST_AESCCM_TAG_SIZE, NIST_AESCCM_256_MAC },
+ { DRV_CRYPTO_DIRECTION_DECRYPT, NIST_AESCCM_256_KEY, NIST_AESCCM_256_BIT_KEY_SIZE, NIST_AESCCM_256_NONCE, NIST_AESCCM_256_ADATA, NIST_AESCCM_ADATA_SIZE, NIST_AESCCM_256_CIPHER, NIST_AESCCM_TEXT_SIZE, NIST_AESCCM_256_PLAIN_TEXT, NIST_AESCCM_TAG_SIZE, NIST_AESCCM_256_MAC },
};
+
#define FIPS_CCM_NUM_OF_TESTS (sizeof(FipsCcmDataTable) / sizeof(FipsCcmData))
static const FipsGcmData FipsGcmDataTable[] = {
- { DRV_CRYPTO_DIRECTION_ENCRYPT, NIST_AESGCM_128_KEY, NIST_AESGCM_128_BIT_KEY_SIZE, NIST_AESGCM_128_IV, NIST_AESGCM_128_ADATA, NIST_AESGCM_ADATA_SIZE, NIST_AESGCM_128_PLAIN_TEXT, NIST_AESGCM_TEXT_SIZE, NIST_AESGCM_128_CIPHER, NIST_AESGCM_TAG_SIZE, NIST_AESGCM_128_MAC },
- { DRV_CRYPTO_DIRECTION_DECRYPT, NIST_AESGCM_128_KEY, NIST_AESGCM_128_BIT_KEY_SIZE, NIST_AESGCM_128_IV, NIST_AESGCM_128_ADATA, NIST_AESGCM_ADATA_SIZE, NIST_AESGCM_128_CIPHER, NIST_AESGCM_TEXT_SIZE, NIST_AESGCM_128_PLAIN_TEXT, NIST_AESGCM_TAG_SIZE, NIST_AESGCM_128_MAC },
- { DRV_CRYPTO_DIRECTION_ENCRYPT, NIST_AESGCM_192_KEY, NIST_AESGCM_192_BIT_KEY_SIZE, NIST_AESGCM_192_IV, NIST_AESGCM_192_ADATA, NIST_AESGCM_ADATA_SIZE, NIST_AESGCM_192_PLAIN_TEXT, NIST_AESGCM_TEXT_SIZE, NIST_AESGCM_192_CIPHER, NIST_AESGCM_TAG_SIZE, NIST_AESGCM_192_MAC },
- { DRV_CRYPTO_DIRECTION_DECRYPT, NIST_AESGCM_192_KEY, NIST_AESGCM_192_BIT_KEY_SIZE, NIST_AESGCM_192_IV, NIST_AESGCM_192_ADATA, NIST_AESGCM_ADATA_SIZE, NIST_AESGCM_192_CIPHER, NIST_AESGCM_TEXT_SIZE, NIST_AESGCM_192_PLAIN_TEXT, NIST_AESGCM_TAG_SIZE, NIST_AESGCM_192_MAC },
- { DRV_CRYPTO_DIRECTION_ENCRYPT, NIST_AESGCM_256_KEY, NIST_AESGCM_256_BIT_KEY_SIZE, NIST_AESGCM_256_IV, NIST_AESGCM_256_ADATA, NIST_AESGCM_ADATA_SIZE, NIST_AESGCM_256_PLAIN_TEXT, NIST_AESGCM_TEXT_SIZE, NIST_AESGCM_256_CIPHER, NIST_AESGCM_TAG_SIZE, NIST_AESGCM_256_MAC },
- { DRV_CRYPTO_DIRECTION_DECRYPT, NIST_AESGCM_256_KEY, NIST_AESGCM_256_BIT_KEY_SIZE, NIST_AESGCM_256_IV, NIST_AESGCM_256_ADATA, NIST_AESGCM_ADATA_SIZE, NIST_AESGCM_256_CIPHER, NIST_AESGCM_TEXT_SIZE, NIST_AESGCM_256_PLAIN_TEXT, NIST_AESGCM_TAG_SIZE, NIST_AESGCM_256_MAC },
+ { DRV_CRYPTO_DIRECTION_ENCRYPT, NIST_AESGCM_128_KEY, NIST_AESGCM_128_BIT_KEY_SIZE, NIST_AESGCM_128_IV, NIST_AESGCM_128_ADATA, NIST_AESGCM_ADATA_SIZE, NIST_AESGCM_128_PLAIN_TEXT, NIST_AESGCM_TEXT_SIZE, NIST_AESGCM_128_CIPHER, NIST_AESGCM_TAG_SIZE, NIST_AESGCM_128_MAC },
+ { DRV_CRYPTO_DIRECTION_DECRYPT, NIST_AESGCM_128_KEY, NIST_AESGCM_128_BIT_KEY_SIZE, NIST_AESGCM_128_IV, NIST_AESGCM_128_ADATA, NIST_AESGCM_ADATA_SIZE, NIST_AESGCM_128_CIPHER, NIST_AESGCM_TEXT_SIZE, NIST_AESGCM_128_PLAIN_TEXT, NIST_AESGCM_TAG_SIZE, NIST_AESGCM_128_MAC },
+ { DRV_CRYPTO_DIRECTION_ENCRYPT, NIST_AESGCM_192_KEY, NIST_AESGCM_192_BIT_KEY_SIZE, NIST_AESGCM_192_IV, NIST_AESGCM_192_ADATA, NIST_AESGCM_ADATA_SIZE, NIST_AESGCM_192_PLAIN_TEXT, NIST_AESGCM_TEXT_SIZE, NIST_AESGCM_192_CIPHER, NIST_AESGCM_TAG_SIZE, NIST_AESGCM_192_MAC },
+ { DRV_CRYPTO_DIRECTION_DECRYPT, NIST_AESGCM_192_KEY, NIST_AESGCM_192_BIT_KEY_SIZE, NIST_AESGCM_192_IV, NIST_AESGCM_192_ADATA, NIST_AESGCM_ADATA_SIZE, NIST_AESGCM_192_CIPHER, NIST_AESGCM_TEXT_SIZE, NIST_AESGCM_192_PLAIN_TEXT, NIST_AESGCM_TAG_SIZE, NIST_AESGCM_192_MAC },
+ { DRV_CRYPTO_DIRECTION_ENCRYPT, NIST_AESGCM_256_KEY, NIST_AESGCM_256_BIT_KEY_SIZE, NIST_AESGCM_256_IV, NIST_AESGCM_256_ADATA, NIST_AESGCM_ADATA_SIZE, NIST_AESGCM_256_PLAIN_TEXT, NIST_AESGCM_TEXT_SIZE, NIST_AESGCM_256_CIPHER, NIST_AESGCM_TAG_SIZE, NIST_AESGCM_256_MAC },
+ { DRV_CRYPTO_DIRECTION_DECRYPT, NIST_AESGCM_256_KEY, NIST_AESGCM_256_BIT_KEY_SIZE, NIST_AESGCM_256_IV, NIST_AESGCM_256_ADATA, NIST_AESGCM_ADATA_SIZE, NIST_AESGCM_256_CIPHER, NIST_AESGCM_TEXT_SIZE, NIST_AESGCM_256_PLAIN_TEXT, NIST_AESGCM_TAG_SIZE, NIST_AESGCM_256_MAC },
};
-#define FIPS_GCM_NUM_OF_TESTS (sizeof(FipsGcmDataTable) / sizeof(FipsGcmData))
+#define FIPS_GCM_NUM_OF_TESTS (sizeof(FipsGcmDataTable) / sizeof(FipsGcmData))
-static inline ssi_fips_error_t
+static inline enum cc_fips_error
FIPS_CipherToFipsError(enum drv_cipher_mode mode, bool is_aes)
{
switch (mode)
{
case DRV_CIPHER_ECB:
- return is_aes ? CC_REE_FIPS_ERROR_AES_ECB_PUT : CC_REE_FIPS_ERROR_DES_ECB_PUT ;
+ return is_aes ? CC_REE_FIPS_ERROR_AES_ECB_PUT : CC_REE_FIPS_ERROR_DES_ECB_PUT;
case DRV_CIPHER_CBC:
- return is_aes ? CC_REE_FIPS_ERROR_AES_CBC_PUT : CC_REE_FIPS_ERROR_DES_CBC_PUT ;
+ return is_aes ? CC_REE_FIPS_ERROR_AES_CBC_PUT : CC_REE_FIPS_ERROR_DES_CBC_PUT;
case DRV_CIPHER_OFB:
return CC_REE_FIPS_ERROR_AES_OFB_PUT;
case DRV_CIPHER_CTR:
@@ -295,8 +291,7 @@ FIPS_CipherToFipsError(enum drv_cipher_mode mode, bool is_aes)
return CC_REE_FIPS_ERROR_GENERAL;
}
-
-static inline int
+static inline int
ssi_cipher_fips_run_test(struct ssi_drvdata *drvdata,
bool is_aes,
int cipher_mode,
@@ -314,7 +309,7 @@ ssi_cipher_fips_run_test(struct ssi_drvdata *drvdata,
int rc;
struct ssi_crypto_req ssi_req = {0};
- HwDesc_s desc[FIPS_CIPHER_MAX_SEQ_LEN];
+ struct cc_hw_desc desc[FIPS_CIPHER_MAX_SEQ_LEN];
int idx = 0;
int s_flow_mode = is_aes ? S_DIN_to_AES : S_DIN_to_DES;
@@ -325,74 +320,73 @@ ssi_cipher_fips_run_test(struct ssi_drvdata *drvdata,
case DRV_CIPHER_CTR:
case DRV_CIPHER_OFB:
/* Load cipher state */
- HW_DESC_INIT(&desc[idx]);
- HW_DESC_SET_DIN_TYPE(&desc[idx], DMA_DLLI,
- iv_dma_addr, iv_len, NS_BIT);
- HW_DESC_SET_CIPHER_CONFIG0(&desc[idx], direction);
- HW_DESC_SET_FLOW_MODE(&desc[idx], s_flow_mode);
- HW_DESC_SET_CIPHER_MODE(&desc[idx], cipher_mode);
- if ((cipher_mode == DRV_CIPHER_CTR) ||
- (cipher_mode == DRV_CIPHER_OFB) ) {
- HW_DESC_SET_SETUP_MODE(&desc[idx], SETUP_LOAD_STATE1);
+ hw_desc_init(&desc[idx]);
+ set_din_type(&desc[idx], DMA_DLLI,
+ iv_dma_addr, iv_len, NS_BIT);
+ set_cipher_config0(&desc[idx], direction);
+ set_flow_mode(&desc[idx], s_flow_mode);
+ set_cipher_mode(&desc[idx], cipher_mode);
+ if ((cipher_mode == DRV_CIPHER_CTR) ||
+ (cipher_mode == DRV_CIPHER_OFB)) {
+ set_setup_mode(&desc[idx], SETUP_LOAD_STATE1);
} else {
- HW_DESC_SET_SETUP_MODE(&desc[idx], SETUP_LOAD_STATE0);
+ set_setup_mode(&desc[idx], SETUP_LOAD_STATE0);
}
idx++;
/*FALLTHROUGH*/
case DRV_CIPHER_ECB:
/* Load key */
- HW_DESC_INIT(&desc[idx]);
- HW_DESC_SET_CIPHER_MODE(&desc[idx], cipher_mode);
- HW_DESC_SET_CIPHER_CONFIG0(&desc[idx], direction);
+ hw_desc_init(&desc[idx]);
+ set_cipher_mode(&desc[idx], cipher_mode);
+ set_cipher_config0(&desc[idx], direction);
if (is_aes) {
- HW_DESC_SET_DIN_TYPE(&desc[idx], DMA_DLLI,
- key_dma_addr,
- ((key_len == 24) ? AES_MAX_KEY_SIZE : key_len),
- NS_BIT);
- HW_DESC_SET_KEY_SIZE_AES(&desc[idx], key_len);
+ set_din_type(&desc[idx], DMA_DLLI, key_dma_addr,
+ ((key_len == 24) ? AES_MAX_KEY_SIZE :
+ key_len), NS_BIT);
+ set_key_size_aes(&desc[idx], key_len);
} else {/*des*/
- HW_DESC_SET_DIN_TYPE(&desc[idx], DMA_DLLI,
- key_dma_addr, key_len,
- NS_BIT);
- HW_DESC_SET_KEY_SIZE_DES(&desc[idx], key_len);
+ set_din_type(&desc[idx], DMA_DLLI, key_dma_addr,
+ key_len, NS_BIT);
+ set_key_size_des(&desc[idx], key_len);
}
- HW_DESC_SET_FLOW_MODE(&desc[idx], s_flow_mode);
- HW_DESC_SET_SETUP_MODE(&desc[idx], SETUP_LOAD_KEY0);
+ set_flow_mode(&desc[idx], s_flow_mode);
+ set_setup_mode(&desc[idx], SETUP_LOAD_KEY0);
idx++;
break;
case DRV_CIPHER_XTS:
/* Load AES key */
- HW_DESC_INIT(&desc[idx]);
- HW_DESC_SET_CIPHER_MODE(&desc[idx], cipher_mode);
- HW_DESC_SET_CIPHER_CONFIG0(&desc[idx], direction);
- HW_DESC_SET_DIN_TYPE(&desc[idx], DMA_DLLI,
- key_dma_addr, key_len/2, NS_BIT);
- HW_DESC_SET_KEY_SIZE_AES(&desc[idx], key_len/2);
- HW_DESC_SET_FLOW_MODE(&desc[idx], s_flow_mode);
- HW_DESC_SET_SETUP_MODE(&desc[idx], SETUP_LOAD_KEY0);
+ hw_desc_init(&desc[idx]);
+ set_cipher_mode(&desc[idx], cipher_mode);
+ set_cipher_config0(&desc[idx], direction);
+ set_din_type(&desc[idx], DMA_DLLI, key_dma_addr, (key_len / 2),
+ NS_BIT);
+ set_key_size_aes(&desc[idx], (key_len / 2));
+ set_flow_mode(&desc[idx], s_flow_mode);
+ set_setup_mode(&desc[idx], SETUP_LOAD_KEY0);
idx++;
/* load XEX key */
- HW_DESC_INIT(&desc[idx]);
- HW_DESC_SET_CIPHER_MODE(&desc[idx], cipher_mode);
- HW_DESC_SET_CIPHER_CONFIG0(&desc[idx], direction);
- HW_DESC_SET_DIN_TYPE(&desc[idx], DMA_DLLI,
- (key_dma_addr+key_len/2), key_len/2, NS_BIT);
- HW_DESC_SET_XEX_DATA_UNIT_SIZE(&desc[idx], data_size);
- HW_DESC_SET_FLOW_MODE(&desc[idx], s_flow_mode);
- HW_DESC_SET_KEY_SIZE_AES(&desc[idx], key_len/2);
- HW_DESC_SET_SETUP_MODE(&desc[idx], SETUP_LOAD_XEX_KEY);
+ hw_desc_init(&desc[idx]);
+ set_cipher_mode(&desc[idx], cipher_mode);
+ set_cipher_config0(&desc[idx], direction);
+ set_din_type(&desc[idx], DMA_DLLI,
+ (key_dma_addr + (key_len / 2)),
+ (key_len / 2), NS_BIT);
+ set_xex_data_unit_size(&desc[idx], data_size);
+ set_flow_mode(&desc[idx], s_flow_mode);
+ set_key_size_aes(&desc[idx], (key_len / 2));
+ set_setup_mode(&desc[idx], SETUP_LOAD_XEX_KEY);
idx++;
/* Set state */
- HW_DESC_INIT(&desc[idx]);
- HW_DESC_SET_SETUP_MODE(&desc[idx], SETUP_LOAD_STATE1);
- HW_DESC_SET_CIPHER_MODE(&desc[idx], cipher_mode);
- HW_DESC_SET_CIPHER_CONFIG0(&desc[idx], direction);
- HW_DESC_SET_KEY_SIZE_AES(&desc[idx], key_len/2);
- HW_DESC_SET_FLOW_MODE(&desc[idx], s_flow_mode);
- HW_DESC_SET_DIN_TYPE(&desc[idx], DMA_DLLI,
- iv_dma_addr, CC_AES_BLOCK_SIZE, NS_BIT);
+ hw_desc_init(&desc[idx]);
+ set_setup_mode(&desc[idx], SETUP_LOAD_STATE1);
+ set_cipher_mode(&desc[idx], cipher_mode);
+ set_cipher_config0(&desc[idx], direction);
+ set_key_size_aes(&desc[idx], (key_len / 2));
+ set_flow_mode(&desc[idx], s_flow_mode);
+ set_din_type(&desc[idx], DMA_DLLI, iv_dma_addr,
+ CC_AES_BLOCK_SIZE, NS_BIT);
idx++;
break;
default:
@@ -401,10 +395,10 @@ ssi_cipher_fips_run_test(struct ssi_drvdata *drvdata,
}
/* create data descriptor */
- HW_DESC_INIT(&desc[idx]);
- HW_DESC_SET_DIN_TYPE(&desc[idx], DMA_DLLI, din_dma_addr, data_size, NS_BIT);
- HW_DESC_SET_DOUT_DLLI(&desc[idx], dout_dma_addr, data_size, NS_BIT, 0);
- HW_DESC_SET_FLOW_MODE(&desc[idx], is_aes ? DIN_AES_DOUT : DIN_DES_DOUT);
+ hw_desc_init(&desc[idx]);
+ set_din_type(&desc[idx], DMA_DLLI, din_dma_addr, data_size, NS_BIT);
+ set_dout_dlli(&desc[idx], dout_dma_addr, data_size, NS_BIT, 0);
+ set_flow_mode(&desc[idx], is_aes ? DIN_AES_DOUT : DIN_DES_DOUT);
idx++;
/* perform the operation - Lock HW and push sequence */
@@ -415,11 +409,10 @@ ssi_cipher_fips_run_test(struct ssi_drvdata *drvdata,
return rc;
}
-
-ssi_fips_error_t
+enum cc_fips_error
ssi_cipher_fips_power_up_tests(struct ssi_drvdata *drvdata, void *cpu_addr_buffer, dma_addr_t dma_coherent_buffer)
{
- ssi_fips_error_t error = CC_REE_FIPS_ERROR_OK;
+ enum cc_fips_error error = CC_REE_FIPS_ERROR_OK;
size_t i;
struct fips_cipher_ctx *virt_ctx = (struct fips_cipher_ctx *)cpu_addr_buffer;
@@ -431,9 +424,9 @@ ssi_cipher_fips_power_up_tests(struct ssi_drvdata *drvdata, void *cpu_addr_buffe
for (i = 0; i < FIPS_CIPHER_NUM_OF_TESTS; ++i)
{
- FipsCipherData *cipherData = (FipsCipherData*)&FipsCipherDataTable[i];
+ FipsCipherData *cipherData = (FipsCipherData *)&FipsCipherDataTable[i];
int rc = 0;
- size_t iv_size = cipherData->isAes ? NIST_AES_IV_SIZE : NIST_TDES_IV_SIZE ;
+ size_t iv_size = cipherData->isAes ? NIST_AES_IV_SIZE : NIST_TDES_IV_SIZE;
memset(cpu_addr_buffer, 0, sizeof(struct fips_cipher_ctx));
@@ -480,8 +473,7 @@ ssi_cipher_fips_power_up_tests(struct ssi_drvdata *drvdata, void *cpu_addr_buffe
return error;
}
-
-static inline int
+static inline int
ssi_cmac_fips_run_test(struct ssi_drvdata *drvdata,
dma_addr_t key_dma_addr,
size_t key_len,
@@ -495,46 +487,45 @@ ssi_cmac_fips_run_test(struct ssi_drvdata *drvdata,
int rc;
struct ssi_crypto_req ssi_req = {0};
- HwDesc_s desc[FIPS_CMAC_MAX_SEQ_LEN];
+ struct cc_hw_desc desc[FIPS_CMAC_MAX_SEQ_LEN];
int idx = 0;
/* Setup CMAC Key */
- HW_DESC_INIT(&desc[idx]);
- HW_DESC_SET_DIN_TYPE(&desc[idx], DMA_DLLI, key_dma_addr,
- ((key_len == 24) ? AES_MAX_KEY_SIZE : key_len), NS_BIT);
- HW_DESC_SET_SETUP_MODE(&desc[idx], SETUP_LOAD_KEY0);
- HW_DESC_SET_CIPHER_MODE(&desc[idx], DRV_CIPHER_CMAC);
- HW_DESC_SET_CIPHER_CONFIG0(&desc[idx], DESC_DIRECTION_ENCRYPT_ENCRYPT);
- HW_DESC_SET_KEY_SIZE_AES(&desc[idx], key_len);
- HW_DESC_SET_FLOW_MODE(&desc[idx], S_DIN_to_AES);
+ hw_desc_init(&desc[idx]);
+ set_din_type(&desc[idx], DMA_DLLI, key_dma_addr,
+ ((key_len == 24) ? AES_MAX_KEY_SIZE : key_len), NS_BIT);
+ set_setup_mode(&desc[idx], SETUP_LOAD_KEY0);
+ set_cipher_mode(&desc[idx], DRV_CIPHER_CMAC);
+ set_cipher_config0(&desc[idx], DESC_DIRECTION_ENCRYPT_ENCRYPT);
+ set_key_size_aes(&desc[idx], key_len);
+ set_flow_mode(&desc[idx], S_DIN_to_AES);
idx++;
/* Load MAC state */
- HW_DESC_INIT(&desc[idx]);
- HW_DESC_SET_DIN_TYPE(&desc[idx], DMA_DLLI, digest_dma_addr, CC_AES_BLOCK_SIZE, NS_BIT);
- HW_DESC_SET_SETUP_MODE(&desc[idx], SETUP_LOAD_STATE0);
- HW_DESC_SET_CIPHER_MODE(&desc[idx], DRV_CIPHER_CMAC);
- HW_DESC_SET_CIPHER_CONFIG0(&desc[idx], DESC_DIRECTION_ENCRYPT_ENCRYPT);
- HW_DESC_SET_KEY_SIZE_AES(&desc[idx], key_len);
- HW_DESC_SET_FLOW_MODE(&desc[idx], S_DIN_to_AES);
+ hw_desc_init(&desc[idx]);
+ set_din_type(&desc[idx], DMA_DLLI, digest_dma_addr, CC_AES_BLOCK_SIZE,
+ NS_BIT);
+ set_setup_mode(&desc[idx], SETUP_LOAD_STATE0);
+ set_cipher_mode(&desc[idx], DRV_CIPHER_CMAC);
+ set_cipher_config0(&desc[idx], DESC_DIRECTION_ENCRYPT_ENCRYPT);
+ set_key_size_aes(&desc[idx], key_len);
+ set_flow_mode(&desc[idx], S_DIN_to_AES);
idx++;
-
//ssi_hash_create_data_desc(state, ctx, DIN_AES_DOUT, desc, false, &idx);
- HW_DESC_INIT(&desc[idx]);
- HW_DESC_SET_DIN_TYPE(&desc[idx], DMA_DLLI,
- din_dma_addr,
- din_len, NS_BIT);
- HW_DESC_SET_FLOW_MODE(&desc[idx], DIN_AES_DOUT);
+ hw_desc_init(&desc[idx]);
+ set_din_type(&desc[idx], DMA_DLLI, din_dma_addr, din_len, NS_BIT);
+ set_flow_mode(&desc[idx], DIN_AES_DOUT);
idx++;
-
+
/* Get final MAC result */
- HW_DESC_INIT(&desc[idx]);
- HW_DESC_SET_DOUT_DLLI(&desc[idx], digest_dma_addr, CC_AES_BLOCK_SIZE, NS_BIT, 0);
- HW_DESC_SET_FLOW_MODE(&desc[idx], S_AES_to_DOUT);
- HW_DESC_SET_SETUP_MODE(&desc[idx], SETUP_WRITE_STATE0);
- HW_DESC_SET_CIPHER_CONFIG0(&desc[idx], DESC_DIRECTION_ENCRYPT_ENCRYPT);
- HW_DESC_SET_CIPHER_MODE(&desc[idx], DRV_CIPHER_CMAC);
+ hw_desc_init(&desc[idx]);
+ set_dout_dlli(&desc[idx], digest_dma_addr, CC_AES_BLOCK_SIZE, NS_BIT,
+ 0);
+ set_flow_mode(&desc[idx], S_AES_to_DOUT);
+ set_setup_mode(&desc[idx], SETUP_WRITE_STATE0);
+ set_cipher_config0(&desc[idx], DESC_DIRECTION_ENCRYPT_ENCRYPT);
+ set_cipher_mode(&desc[idx], DRV_CIPHER_CMAC);
idx++;
/* perform the operation - Lock HW and push sequence */
@@ -545,10 +536,10 @@ ssi_cmac_fips_run_test(struct ssi_drvdata *drvdata,
return rc;
}
-ssi_fips_error_t
+enum cc_fips_error
ssi_cmac_fips_power_up_tests(struct ssi_drvdata *drvdata, void *cpu_addr_buffer, dma_addr_t dma_coherent_buffer)
{
- ssi_fips_error_t error = CC_REE_FIPS_ERROR_OK;
+ enum cc_fips_error error = CC_REE_FIPS_ERROR_OK;
size_t i;
struct fips_cmac_ctx *virt_ctx = (struct fips_cmac_ctx *)cpu_addr_buffer;
@@ -559,7 +550,7 @@ ssi_cmac_fips_power_up_tests(struct ssi_drvdata *drvdata, void *cpu_addr_buffer,
for (i = 0; i < FIPS_CMAC_NUM_OF_TESTS; ++i)
{
- FipsCmacData *cmac_data = (FipsCmacData*)&FipsCmacDataTable[i];
+ FipsCmacData *cmac_data = (FipsCmacData *)&FipsCmacDataTable[i];
int rc = 0;
memset(cpu_addr_buffer, 0, sizeof(struct fips_cmac_ctx));
@@ -604,8 +595,7 @@ ssi_cmac_fips_power_up_tests(struct ssi_drvdata *drvdata, void *cpu_addr_buffer,
return error;
}
-
-static inline ssi_fips_error_t
+static inline enum cc_fips_error
FIPS_HashToFipsError(enum drv_hash_mode hash_mode)
{
switch (hash_mode) {
@@ -624,7 +614,7 @@ FIPS_HashToFipsError(enum drv_hash_mode hash_mode)
return CC_REE_FIPS_ERROR_GENERAL;
}
-static inline int
+static inline int
ssi_hash_fips_run_test(struct ssi_drvdata *drvdata,
dma_addr_t initial_digest_dma_addr,
dma_addr_t din_dma_addr,
@@ -640,45 +630,47 @@ ssi_hash_fips_run_test(struct ssi_drvdata *drvdata,
int rc;
struct ssi_crypto_req ssi_req = {0};
- HwDesc_s desc[FIPS_HASH_MAX_SEQ_LEN];
+ struct cc_hw_desc desc[FIPS_HASH_MAX_SEQ_LEN];
int idx = 0;
/* Load initial digest */
- HW_DESC_INIT(&desc[idx]);
- HW_DESC_SET_CIPHER_MODE(&desc[idx], hw_mode);
- HW_DESC_SET_DIN_TYPE(&desc[idx], DMA_DLLI, initial_digest_dma_addr, inter_digestsize, NS_BIT);
- HW_DESC_SET_FLOW_MODE(&desc[idx], S_DIN_to_HASH);
- HW_DESC_SET_SETUP_MODE(&desc[idx], SETUP_LOAD_STATE0);
+ hw_desc_init(&desc[idx]);
+ set_cipher_mode(&desc[idx], hw_mode);
+ set_din_type(&desc[idx], DMA_DLLI, initial_digest_dma_addr,
+ inter_digestsize, NS_BIT);
+ set_flow_mode(&desc[idx], S_DIN_to_HASH);
+ set_setup_mode(&desc[idx], SETUP_LOAD_STATE0);
idx++;
/* Load the hash current length */
- HW_DESC_INIT(&desc[idx]);
- HW_DESC_SET_CIPHER_MODE(&desc[idx], hw_mode);
- HW_DESC_SET_DIN_CONST(&desc[idx], 0, HASH_LEN_SIZE);
- HW_DESC_SET_CIPHER_CONFIG1(&desc[idx], HASH_PADDING_ENABLED);
- HW_DESC_SET_FLOW_MODE(&desc[idx], S_DIN_to_HASH);
- HW_DESC_SET_SETUP_MODE(&desc[idx], SETUP_LOAD_KEY0);
+ hw_desc_init(&desc[idx]);
+ set_cipher_mode(&desc[idx], hw_mode);
+ set_din_const(&desc[idx], 0, HASH_LEN_SIZE);
+ set_cipher_config1(&desc[idx], HASH_PADDING_ENABLED);
+ set_flow_mode(&desc[idx], S_DIN_to_HASH);
+ set_setup_mode(&desc[idx], SETUP_LOAD_KEY0);
idx++;
/* data descriptor */
- HW_DESC_INIT(&desc[idx]);
- HW_DESC_SET_DIN_TYPE(&desc[idx], DMA_DLLI, din_dma_addr, data_in_size, NS_BIT);
- HW_DESC_SET_FLOW_MODE(&desc[idx], DIN_HASH);
+ hw_desc_init(&desc[idx]);
+ set_din_type(&desc[idx], DMA_DLLI, din_dma_addr, data_in_size, NS_BIT);
+ set_flow_mode(&desc[idx], DIN_HASH);
idx++;
/* Get final MAC result */
- HW_DESC_INIT(&desc[idx]);
- HW_DESC_SET_CIPHER_MODE(&desc[idx], hw_mode);
- HW_DESC_SET_DOUT_DLLI(&desc[idx], mac_res_dma_addr, digest_size, NS_BIT, 0);
- HW_DESC_SET_FLOW_MODE(&desc[idx], S_HASH_to_DOUT);
- HW_DESC_SET_SETUP_MODE(&desc[idx], SETUP_WRITE_STATE0);
- HW_DESC_SET_CIPHER_CONFIG1(&desc[idx], HASH_PADDING_DISABLED);
+ hw_desc_init(&desc[idx]);
+ set_cipher_mode(&desc[idx], hw_mode);
+ set_dout_dlli(&desc[idx], mac_res_dma_addr, digest_size, NS_BIT, 0);
+ set_flow_mode(&desc[idx], S_HASH_to_DOUT);
+ set_setup_mode(&desc[idx], SETUP_WRITE_STATE0);
+ set_cipher_config1(&desc[idx], HASH_PADDING_DISABLED);
if (unlikely((hash_mode == DRV_HASH_MD5) ||
(hash_mode == DRV_HASH_SHA384) ||
(hash_mode == DRV_HASH_SHA512))) {
- HW_DESC_SET_BYTES_SWAP(&desc[idx], 1);
+ set_bytes_swap(&desc[idx], 1);
} else {
- HW_DESC_SET_CIPHER_CONFIG0(&desc[idx], HASH_DIGEST_RESULT_LITTLE_ENDIAN);
+ set_cipher_config0(&desc[idx],
+ HASH_DIGEST_RESULT_LITTLE_ENDIAN);
}
idx++;
@@ -689,10 +681,10 @@ ssi_hash_fips_run_test(struct ssi_drvdata *drvdata,
return rc;
}
-ssi_fips_error_t
+enum cc_fips_error
ssi_hash_fips_power_up_tests(struct ssi_drvdata *drvdata, void *cpu_addr_buffer, dma_addr_t dma_coherent_buffer)
{
- ssi_fips_error_t error = CC_REE_FIPS_ERROR_OK;
+ enum cc_fips_error error = CC_REE_FIPS_ERROR_OK;
size_t i;
struct fips_hash_ctx *virt_ctx = (struct fips_hash_ctx *)cpu_addr_buffer;
@@ -703,7 +695,7 @@ ssi_hash_fips_power_up_tests(struct ssi_drvdata *drvdata, void *cpu_addr_buffer,
for (i = 0; i < FIPS_HASH_NUM_OF_TESTS; ++i)
{
- FipsHashData *hash_data = (FipsHashData*)&FipsHashDataTable[i];
+ FipsHashData *hash_data = (FipsHashData *)&FipsHashDataTable[i];
int rc = 0;
enum drv_hash_hw_mode hw_mode = 0;
int digest_size = 0;
@@ -717,20 +709,20 @@ ssi_hash_fips_power_up_tests(struct ssi_drvdata *drvdata, void *cpu_addr_buffer,
digest_size = CC_SHA1_DIGEST_SIZE;
inter_digestsize = CC_SHA1_DIGEST_SIZE;
/* copy the initial digest into the allocated cache coherent buffer */
- memcpy(virt_ctx->initial_digest, (void*)sha1_init, CC_SHA1_DIGEST_SIZE);
+ memcpy(virt_ctx->initial_digest, (void *)sha1_init, CC_SHA1_DIGEST_SIZE);
break;
case DRV_HASH_SHA256:
hw_mode = DRV_HASH_HW_SHA256;
digest_size = CC_SHA256_DIGEST_SIZE;
inter_digestsize = CC_SHA256_DIGEST_SIZE;
- memcpy(virt_ctx->initial_digest, (void*)sha256_init, CC_SHA256_DIGEST_SIZE);
+ memcpy(virt_ctx->initial_digest, (void *)sha256_init, CC_SHA256_DIGEST_SIZE);
break;
#if (CC_SUPPORT_SHA > 256)
case DRV_HASH_SHA512:
hw_mode = DRV_HASH_HW_SHA512;
digest_size = CC_SHA512_DIGEST_SIZE;
inter_digestsize = CC_SHA512_DIGEST_SIZE;
- memcpy(virt_ctx->initial_digest, (void*)sha512_init, CC_SHA512_DIGEST_SIZE);
+ memcpy(virt_ctx->initial_digest, (void *)sha512_init, CC_SHA512_DIGEST_SIZE);
break;
#endif
default:
@@ -757,7 +749,7 @@ ssi_hash_fips_power_up_tests(struct ssi_drvdata *drvdata, void *cpu_addr_buffer,
FIPS_LOG("ssi_hash_fips_run_test %d returned error - rc = %d \n", i, rc);
error = FIPS_HashToFipsError(hash_data->hash_mode);
break;
- }
+ }
/* compare actual mac result to expected */
if (memcmp(virt_ctx->mac_res, hash_data->mac_res, digest_size) != 0)
@@ -772,14 +764,13 @@ ssi_hash_fips_power_up_tests(struct ssi_drvdata *drvdata, void *cpu_addr_buffer,
error = FIPS_HashToFipsError(hash_data->hash_mode);
break;
- }
+ }
}
return error;
}
-
-static inline ssi_fips_error_t
+static inline enum cc_fips_error
FIPS_HmacToFipsError(enum drv_hash_mode hash_mode)
{
switch (hash_mode) {
@@ -798,7 +789,7 @@ FIPS_HmacToFipsError(enum drv_hash_mode hash_mode)
return CC_REE_FIPS_ERROR_GENERAL;
}
-static inline int
+static inline int
ssi_hmac_fips_run_test(struct ssi_drvdata *drvdata,
dma_addr_t initial_digest_dma_addr,
dma_addr_t key_dma_addr,
@@ -816,34 +807,34 @@ ssi_hmac_fips_run_test(struct ssi_drvdata *drvdata,
dma_addr_t digest_bytes_len_dma_addr)
{
/* The implemented flow is not the same as the one implemented in ssi_hash.c (setkey + digest flows).
- In this flow, there is no need to store and reload some of the intermidiate results. */
+ * In this flow, there is no need to store and reload some of the intermidiate results.
+ */
/* max number of descriptors used for the flow */
#define FIPS_HMAC_MAX_SEQ_LEN 12
int rc;
struct ssi_crypto_req ssi_req = {0};
- HwDesc_s desc[FIPS_HMAC_MAX_SEQ_LEN];
+ struct cc_hw_desc desc[FIPS_HMAC_MAX_SEQ_LEN];
int idx = 0;
int i;
/* calc the hash opad first and ipad only afterwards (unlike the flow in ssi_hash.c) */
unsigned int hmacPadConst[2] = { HMAC_OPAD_CONST, HMAC_IPAD_CONST };
// assume (key_size <= block_size)
- HW_DESC_INIT(&desc[idx]);
- HW_DESC_SET_DIN_TYPE(&desc[idx], DMA_DLLI, key_dma_addr, key_size, NS_BIT);
- HW_DESC_SET_FLOW_MODE(&desc[idx], BYPASS);
- HW_DESC_SET_DOUT_DLLI(&desc[idx], k0_dma_addr, key_size, NS_BIT, 0);
+ hw_desc_init(&desc[idx]);
+ set_din_type(&desc[idx], DMA_DLLI, key_dma_addr, key_size, NS_BIT);
+ set_flow_mode(&desc[idx], BYPASS);
+ set_dout_dlli(&desc[idx], k0_dma_addr, key_size, NS_BIT, 0);
idx++;
// if needed, append Key with zeros to create K0
if ((block_size - key_size) != 0) {
- HW_DESC_INIT(&desc[idx]);
- HW_DESC_SET_DIN_CONST(&desc[idx], 0, (block_size - key_size));
- HW_DESC_SET_FLOW_MODE(&desc[idx], BYPASS);
- HW_DESC_SET_DOUT_DLLI(&desc[idx],
- (k0_dma_addr + key_size), (block_size - key_size),
- NS_BIT, 0);
+ hw_desc_init(&desc[idx]);
+ set_din_const(&desc[idx], 0, (block_size - key_size));
+ set_flow_mode(&desc[idx], BYPASS);
+ set_dout_dlli(&desc[idx], (k0_dma_addr + key_size),
+ (block_size - key_size), NS_BIT, 0);
idx++;
}
@@ -858,50 +849,47 @@ ssi_hmac_fips_run_test(struct ssi_drvdata *drvdata,
/* calc derived HMAC key */
for (i = 0; i < 2; i++) {
/* Load hash initial state */
- HW_DESC_INIT(&desc[idx]);
- HW_DESC_SET_CIPHER_MODE(&desc[idx], hw_mode);
- HW_DESC_SET_DIN_TYPE(&desc[idx], DMA_DLLI, initial_digest_dma_addr, inter_digestsize, NS_BIT);
- HW_DESC_SET_FLOW_MODE(&desc[idx], S_DIN_to_HASH);
- HW_DESC_SET_SETUP_MODE(&desc[idx], SETUP_LOAD_STATE0);
+ hw_desc_init(&desc[idx]);
+ set_cipher_mode(&desc[idx], hw_mode);
+ set_din_type(&desc[idx], DMA_DLLI, initial_digest_dma_addr,
+ inter_digestsize, NS_BIT);
+ set_flow_mode(&desc[idx], S_DIN_to_HASH);
+ set_setup_mode(&desc[idx], SETUP_LOAD_STATE0);
idx++;
-
/* Load the hash current length*/
- HW_DESC_INIT(&desc[idx]);
- HW_DESC_SET_CIPHER_MODE(&desc[idx], hw_mode);
- HW_DESC_SET_DIN_CONST(&desc[idx], 0, HASH_LEN_SIZE);
- HW_DESC_SET_FLOW_MODE(&desc[idx], S_DIN_to_HASH);
- HW_DESC_SET_SETUP_MODE(&desc[idx], SETUP_LOAD_KEY0);
+ hw_desc_init(&desc[idx]);
+ set_cipher_mode(&desc[idx], hw_mode);
+ set_din_const(&desc[idx], 0, HASH_LEN_SIZE);
+ set_flow_mode(&desc[idx], S_DIN_to_HASH);
+ set_setup_mode(&desc[idx], SETUP_LOAD_KEY0);
idx++;
/* Prepare opad/ipad key */
- HW_DESC_INIT(&desc[idx]);
- HW_DESC_SET_XOR_VAL(&desc[idx], hmacPadConst[i]);
- HW_DESC_SET_CIPHER_MODE(&desc[idx], hw_mode);
- HW_DESC_SET_FLOW_MODE(&desc[idx], S_DIN_to_HASH);
- HW_DESC_SET_SETUP_MODE(&desc[idx], SETUP_LOAD_STATE1);
+ hw_desc_init(&desc[idx]);
+ set_xor_val(&desc[idx], hmacPadConst[i]);
+ set_cipher_mode(&desc[idx], hw_mode);
+ set_flow_mode(&desc[idx], S_DIN_to_HASH);
+ set_setup_mode(&desc[idx], SETUP_LOAD_STATE1);
idx++;
/* Perform HASH update */
- HW_DESC_INIT(&desc[idx]);
- HW_DESC_SET_DIN_TYPE(&desc[idx], DMA_DLLI,
- k0_dma_addr,
- block_size, NS_BIT);
- HW_DESC_SET_CIPHER_MODE(&desc[idx],hw_mode);
- HW_DESC_SET_XOR_ACTIVE(&desc[idx]);
- HW_DESC_SET_FLOW_MODE(&desc[idx], DIN_HASH);
+ hw_desc_init(&desc[idx]);
+ set_din_type(&desc[idx], DMA_DLLI, k0_dma_addr, block_size,
+ NS_BIT);
+ set_cipher_mode(&desc[idx], hw_mode);
+ set_xor_active(&desc[idx]);
+ set_flow_mode(&desc[idx], DIN_HASH);
idx++;
if (i == 0) {
/* First iteration - calc H(K0^opad) into tmp_digest_dma_addr */
- HW_DESC_INIT(&desc[idx]);
- HW_DESC_SET_CIPHER_MODE(&desc[idx], hw_mode);
- HW_DESC_SET_DOUT_DLLI(&desc[idx],
- tmp_digest_dma_addr,
- inter_digestsize,
- NS_BIT, 0);
- HW_DESC_SET_FLOW_MODE(&desc[idx], S_HASH_to_DOUT);
- HW_DESC_SET_SETUP_MODE(&desc[idx], SETUP_WRITE_STATE0);
+ hw_desc_init(&desc[idx]);
+ set_cipher_mode(&desc[idx], hw_mode);
+ set_dout_dlli(&desc[idx], tmp_digest_dma_addr,
+ inter_digestsize, NS_BIT, 0);
+ set_flow_mode(&desc[idx], S_HASH_to_DOUT);
+ set_setup_mode(&desc[idx], SETUP_WRITE_STATE0);
idx++;
// is this needed?? or continue with current descriptors??
@@ -916,85 +904,86 @@ ssi_hmac_fips_run_test(struct ssi_drvdata *drvdata,
}
/* data descriptor */
- HW_DESC_INIT(&desc[idx]);
- HW_DESC_SET_DIN_TYPE(&desc[idx], DMA_DLLI,
- din_dma_addr, data_in_size,
- NS_BIT);
- HW_DESC_SET_FLOW_MODE(&desc[idx], DIN_HASH);
+ hw_desc_init(&desc[idx]);
+ set_din_type(&desc[idx], DMA_DLLI, din_dma_addr, data_in_size, NS_BIT);
+ set_flow_mode(&desc[idx], DIN_HASH);
idx++;
/* HW last hash block padding (aka. "DO_PAD") */
- HW_DESC_INIT(&desc[idx]);
- HW_DESC_SET_CIPHER_MODE(&desc[idx], hw_mode);
- HW_DESC_SET_DOUT_DLLI(&desc[idx], k0_dma_addr, HASH_LEN_SIZE, NS_BIT, 0);
- HW_DESC_SET_FLOW_MODE(&desc[idx], S_HASH_to_DOUT);
- HW_DESC_SET_SETUP_MODE(&desc[idx], SETUP_WRITE_STATE1);
- HW_DESC_SET_CIPHER_DO(&desc[idx], DO_PAD);
+ hw_desc_init(&desc[idx]);
+ set_cipher_mode(&desc[idx], hw_mode);
+ set_dout_dlli(&desc[idx], k0_dma_addr, HASH_LEN_SIZE, NS_BIT, 0);
+ set_flow_mode(&desc[idx], S_HASH_to_DOUT);
+ set_setup_mode(&desc[idx], SETUP_WRITE_STATE1);
+ set_cipher_do(&desc[idx], DO_PAD);
idx++;
/* store the hash digest result in the context */
- HW_DESC_INIT(&desc[idx]);
- HW_DESC_SET_CIPHER_MODE(&desc[idx], hw_mode);
- HW_DESC_SET_DOUT_DLLI(&desc[idx], k0_dma_addr, digest_size, NS_BIT, 0);
- HW_DESC_SET_FLOW_MODE(&desc[idx], S_HASH_to_DOUT);
+ hw_desc_init(&desc[idx]);
+ set_cipher_mode(&desc[idx], hw_mode);
+ set_dout_dlli(&desc[idx], k0_dma_addr, digest_size, NS_BIT, 0);
+ set_flow_mode(&desc[idx], S_HASH_to_DOUT);
if (unlikely((hash_mode == DRV_HASH_MD5) ||
(hash_mode == DRV_HASH_SHA384) ||
(hash_mode == DRV_HASH_SHA512))) {
- HW_DESC_SET_BYTES_SWAP(&desc[idx], 1);
+ set_bytes_swap(&desc[idx], 1);
} else {
- HW_DESC_SET_CIPHER_CONFIG0(&desc[idx], HASH_DIGEST_RESULT_LITTLE_ENDIAN);
+ set_cipher_config0(&desc[idx],
+ HASH_DIGEST_RESULT_LITTLE_ENDIAN);
}
- HW_DESC_SET_SETUP_MODE(&desc[idx], SETUP_WRITE_STATE0);
+ set_setup_mode(&desc[idx], SETUP_WRITE_STATE0);
idx++;
/* at this point:
- tmp_digest = H(o_key_pad)
- k0 = H(i_key_pad || m)
- */
+ * tmp_digest = H(o_key_pad)
+ * k0 = H(i_key_pad || m)
+ */
/* Loading hash opad xor key state */
- HW_DESC_INIT(&desc[idx]);
- HW_DESC_SET_CIPHER_MODE(&desc[idx], hw_mode);
- HW_DESC_SET_DIN_TYPE(&desc[idx], DMA_DLLI, tmp_digest_dma_addr, inter_digestsize, NS_BIT);
- HW_DESC_SET_FLOW_MODE(&desc[idx], S_DIN_to_HASH);
- HW_DESC_SET_SETUP_MODE(&desc[idx], SETUP_LOAD_STATE0);
+ hw_desc_init(&desc[idx]);
+ set_cipher_mode(&desc[idx], hw_mode);
+ set_din_type(&desc[idx], DMA_DLLI, tmp_digest_dma_addr,
+ inter_digestsize, NS_BIT);
+ set_flow_mode(&desc[idx], S_DIN_to_HASH);
+ set_setup_mode(&desc[idx], SETUP_LOAD_STATE0);
idx++;
/* Load the hash current length */
- HW_DESC_INIT(&desc[idx]);
- HW_DESC_SET_CIPHER_MODE(&desc[idx], hw_mode);
- HW_DESC_SET_DIN_TYPE(&desc[idx], DMA_DLLI, digest_bytes_len_dma_addr, HASH_LEN_SIZE, NS_BIT);
- HW_DESC_SET_CIPHER_CONFIG1(&desc[idx], HASH_PADDING_ENABLED);
- HW_DESC_SET_FLOW_MODE(&desc[idx], S_DIN_to_HASH);
- HW_DESC_SET_SETUP_MODE(&desc[idx], SETUP_LOAD_KEY0);
+ hw_desc_init(&desc[idx]);
+ set_cipher_mode(&desc[idx], hw_mode);
+ set_din_type(&desc[idx], DMA_DLLI, digest_bytes_len_dma_addr,
+ HASH_LEN_SIZE, NS_BIT);
+ set_cipher_config1(&desc[idx], HASH_PADDING_ENABLED);
+ set_flow_mode(&desc[idx], S_DIN_to_HASH);
+ set_setup_mode(&desc[idx], SETUP_LOAD_KEY0);
idx++;
/* Memory Barrier: wait for IPAD/OPAD axi write to complete */
- HW_DESC_INIT(&desc[idx]);
- HW_DESC_SET_DIN_NO_DMA(&desc[idx], 0, 0xfffff0);
- HW_DESC_SET_DOUT_NO_DMA(&desc[idx], 0, 0, 1);
+ hw_desc_init(&desc[idx]);
+ set_din_no_dma(&desc[idx], 0, 0xfffff0);
+ set_dout_no_dma(&desc[idx], 0, 0, 1);
idx++;
/* Perform HASH update */
- HW_DESC_INIT(&desc[idx]);
- HW_DESC_SET_DIN_TYPE(&desc[idx], DMA_DLLI, k0_dma_addr, digest_size, NS_BIT);
- HW_DESC_SET_FLOW_MODE(&desc[idx], DIN_HASH);
+ hw_desc_init(&desc[idx]);
+ set_din_type(&desc[idx], DMA_DLLI, k0_dma_addr, digest_size, NS_BIT);
+ set_flow_mode(&desc[idx], DIN_HASH);
idx++;
-
/* Get final MAC result */
- HW_DESC_INIT(&desc[idx]);
- HW_DESC_SET_CIPHER_MODE(&desc[idx], hw_mode);
- HW_DESC_SET_DOUT_DLLI(&desc[idx], mac_res_dma_addr, digest_size, NS_BIT, 0);
- HW_DESC_SET_FLOW_MODE(&desc[idx], S_HASH_to_DOUT);
- HW_DESC_SET_SETUP_MODE(&desc[idx], SETUP_WRITE_STATE0);
- HW_DESC_SET_CIPHER_CONFIG1(&desc[idx], HASH_PADDING_DISABLED);
+ hw_desc_init(&desc[idx]);
+ set_cipher_mode(&desc[idx], hw_mode);
+ set_dout_dlli(&desc[idx], mac_res_dma_addr, digest_size, NS_BIT, 0);
+ set_flow_mode(&desc[idx], S_HASH_to_DOUT);
+ set_setup_mode(&desc[idx], SETUP_WRITE_STATE0);
+ set_cipher_config1(&desc[idx], HASH_PADDING_DISABLED);
if (unlikely((hash_mode == DRV_HASH_MD5) ||
(hash_mode == DRV_HASH_SHA384) ||
(hash_mode == DRV_HASH_SHA512))) {
- HW_DESC_SET_BYTES_SWAP(&desc[idx], 1);
+ set_bytes_swap(&desc[idx], 1);
} else {
- HW_DESC_SET_CIPHER_CONFIG0(&desc[idx], HASH_DIGEST_RESULT_LITTLE_ENDIAN);
+ set_cipher_config0(&desc[idx],
+ HASH_DIGEST_RESULT_LITTLE_ENDIAN);
}
idx++;
@@ -1005,10 +994,10 @@ ssi_hmac_fips_run_test(struct ssi_drvdata *drvdata,
return rc;
}
-ssi_fips_error_t
+enum cc_fips_error
ssi_hmac_fips_power_up_tests(struct ssi_drvdata *drvdata, void *cpu_addr_buffer, dma_addr_t dma_coherent_buffer)
{
- ssi_fips_error_t error = CC_REE_FIPS_ERROR_OK;
+ enum cc_fips_error error = CC_REE_FIPS_ERROR_OK;
size_t i;
struct fips_hmac_ctx *virt_ctx = (struct fips_hmac_ctx *)cpu_addr_buffer;
@@ -1023,7 +1012,7 @@ ssi_hmac_fips_power_up_tests(struct ssi_drvdata *drvdata, void *cpu_addr_buffer,
for (i = 0; i < FIPS_HMAC_NUM_OF_TESTS; ++i)
{
- FipsHmacData *hmac_data = (FipsHmacData*)&FipsHmacDataTable[i];
+ FipsHmacData *hmac_data = (FipsHmacData *)&FipsHmacDataTable[i];
int rc = 0;
enum drv_hash_hw_mode hw_mode = 0;
int digest_size = 0;
@@ -1038,7 +1027,7 @@ ssi_hmac_fips_power_up_tests(struct ssi_drvdata *drvdata, void *cpu_addr_buffer,
digest_size = CC_SHA1_DIGEST_SIZE;
block_size = CC_SHA1_BLOCK_SIZE;
inter_digestsize = CC_SHA1_DIGEST_SIZE;
- memcpy(virt_ctx->initial_digest, (void*)sha1_init, CC_SHA1_DIGEST_SIZE);
+ memcpy(virt_ctx->initial_digest, (void *)sha1_init, CC_SHA1_DIGEST_SIZE);
memcpy(virt_ctx->digest_bytes_len, digest_len_init, HASH_LEN_SIZE);
break;
case DRV_HASH_SHA256:
@@ -1046,7 +1035,7 @@ ssi_hmac_fips_power_up_tests(struct ssi_drvdata *drvdata, void *cpu_addr_buffer,
digest_size = CC_SHA256_DIGEST_SIZE;
block_size = CC_SHA256_BLOCK_SIZE;
inter_digestsize = CC_SHA256_DIGEST_SIZE;
- memcpy(virt_ctx->initial_digest, (void*)sha256_init, CC_SHA256_DIGEST_SIZE);
+ memcpy(virt_ctx->initial_digest, (void *)sha256_init, CC_SHA256_DIGEST_SIZE);
memcpy(virt_ctx->digest_bytes_len, digest_len_init, HASH_LEN_SIZE);
break;
#if (CC_SUPPORT_SHA > 256)
@@ -1055,7 +1044,7 @@ ssi_hmac_fips_power_up_tests(struct ssi_drvdata *drvdata, void *cpu_addr_buffer,
digest_size = CC_SHA512_DIGEST_SIZE;
block_size = CC_SHA512_BLOCK_SIZE;
inter_digestsize = CC_SHA512_DIGEST_SIZE;
- memcpy(virt_ctx->initial_digest, (void*)sha512_init, CC_SHA512_DIGEST_SIZE);
+ memcpy(virt_ctx->initial_digest, (void *)sha512_init, CC_SHA512_DIGEST_SIZE);
memcpy(virt_ctx->digest_bytes_len, digest_len_sha512_init, HASH_LEN_SIZE);
break;
#endif
@@ -1111,8 +1100,7 @@ ssi_hmac_fips_power_up_tests(struct ssi_drvdata *drvdata, void *cpu_addr_buffer,
return error;
}
-
-static inline int
+static inline int
ssi_ccm_fips_run_test(struct ssi_drvdata *drvdata,
enum drv_crypto_direction direction,
dma_addr_t key_dma_addr,
@@ -1131,7 +1119,7 @@ ssi_ccm_fips_run_test(struct ssi_drvdata *drvdata,
int rc;
struct ssi_crypto_req ssi_req = {0};
- HwDesc_s desc[FIPS_CCM_MAX_SEQ_LEN];
+ struct cc_hw_desc desc[FIPS_CCM_MAX_SEQ_LEN];
unsigned int idx = 0;
unsigned int cipher_flow_mode;
@@ -1142,100 +1130,103 @@ ssi_ccm_fips_run_test(struct ssi_drvdata *drvdata,
}
/* load key */
- HW_DESC_INIT(&desc[idx]);
- HW_DESC_SET_CIPHER_MODE(&desc[idx], DRV_CIPHER_CTR);
- HW_DESC_SET_DIN_TYPE(&desc[idx], DMA_DLLI, key_dma_addr,
- ((key_size == NIST_AESCCM_192_BIT_KEY_SIZE) ? CC_AES_KEY_SIZE_MAX : key_size),
- NS_BIT);
- HW_DESC_SET_KEY_SIZE_AES(&desc[idx], key_size);
- HW_DESC_SET_SETUP_MODE(&desc[idx], SETUP_LOAD_KEY0);
- HW_DESC_SET_CIPHER_CONFIG0(&desc[idx], DESC_DIRECTION_ENCRYPT_ENCRYPT);
- HW_DESC_SET_FLOW_MODE(&desc[idx], S_DIN_to_AES);
+ hw_desc_init(&desc[idx]);
+ set_cipher_mode(&desc[idx], DRV_CIPHER_CTR);
+ set_din_type(&desc[idx], DMA_DLLI, key_dma_addr,
+ ((key_size == NIST_AESCCM_192_BIT_KEY_SIZE) ?
+ CC_AES_KEY_SIZE_MAX : key_size), NS_BIT)
+ set_key_size_aes(&desc[idx], key_size);
+ set_setup_mode(&desc[idx], SETUP_LOAD_KEY0);
+ set_cipher_config0(&desc[idx], DESC_DIRECTION_ENCRYPT_ENCRYPT);
+ set_flow_mode(&desc[idx], S_DIN_to_AES);
idx++;
/* load ctr state */
- HW_DESC_INIT(&desc[idx]);
- HW_DESC_SET_CIPHER_MODE(&desc[idx], DRV_CIPHER_CTR);
- HW_DESC_SET_KEY_SIZE_AES(&desc[idx], key_size);
- HW_DESC_SET_DIN_TYPE(&desc[idx], DMA_DLLI,
- iv_dma_addr, AES_BLOCK_SIZE,
- NS_BIT);
- HW_DESC_SET_CIPHER_CONFIG0(&desc[idx], DESC_DIRECTION_ENCRYPT_ENCRYPT);
- HW_DESC_SET_SETUP_MODE(&desc[idx], SETUP_LOAD_STATE1);
- HW_DESC_SET_FLOW_MODE(&desc[idx], S_DIN_to_AES);
+ hw_desc_init(&desc[idx]);
+ set_cipher_mode(&desc[idx], DRV_CIPHER_CTR);
+ set_key_size_aes(&desc[idx], key_size);
+ set_din_type(&desc[idx], DMA_DLLI, iv_dma_addr, AES_BLOCK_SIZE,
+ NS_BIT);
+ set_cipher_config0(&desc[idx], DESC_DIRECTION_ENCRYPT_ENCRYPT);
+ set_setup_mode(&desc[idx], SETUP_LOAD_STATE1);
+ set_flow_mode(&desc[idx], S_DIN_to_AES);
idx++;
/* load MAC key */
- HW_DESC_INIT(&desc[idx]);
- HW_DESC_SET_CIPHER_MODE(&desc[idx], DRV_CIPHER_CBC_MAC);
- HW_DESC_SET_DIN_TYPE(&desc[idx], DMA_DLLI, key_dma_addr,
- ((key_size == NIST_AESCCM_192_BIT_KEY_SIZE) ? CC_AES_KEY_SIZE_MAX : key_size),
- NS_BIT);
- HW_DESC_SET_KEY_SIZE_AES(&desc[idx], key_size);
- HW_DESC_SET_SETUP_MODE(&desc[idx], SETUP_LOAD_KEY0);
- HW_DESC_SET_CIPHER_CONFIG0(&desc[idx], DESC_DIRECTION_ENCRYPT_ENCRYPT);
- HW_DESC_SET_FLOW_MODE(&desc[idx], S_DIN_to_HASH);
- HW_DESC_SET_AES_NOT_HASH_MODE(&desc[idx]);
+ hw_desc_init(&desc[idx]);
+ set_cipher_mode(&desc[idx], DRV_CIPHER_CBC_MAC);
+ set_din_type(&desc[idx], DMA_DLLI, key_dma_addr,
+ ((key_size == NIST_AESCCM_192_BIT_KEY_SIZE) ?
+ CC_AES_KEY_SIZE_MAX : key_size), NS_BIT);
+ set_key_size_aes(&desc[idx], key_size);
+ set_setup_mode(&desc[idx], SETUP_LOAD_KEY0);
+ set_cipher_config0(&desc[idx], DESC_DIRECTION_ENCRYPT_ENCRYPT);
+ set_flow_mode(&desc[idx], S_DIN_to_HASH);
+ set_aes_not_hash_mode(&desc[idx]);
idx++;
/* load MAC state */
- HW_DESC_INIT(&desc[idx]);
- HW_DESC_SET_CIPHER_MODE(&desc[idx], DRV_CIPHER_CBC_MAC);
- HW_DESC_SET_KEY_SIZE_AES(&desc[idx], key_size);
- HW_DESC_SET_DIN_TYPE(&desc[idx], DMA_DLLI, mac_res_dma_addr, NIST_AESCCM_TAG_SIZE, NS_BIT);
- HW_DESC_SET_CIPHER_CONFIG0(&desc[idx], DESC_DIRECTION_ENCRYPT_ENCRYPT);
- HW_DESC_SET_SETUP_MODE(&desc[idx], SETUP_LOAD_STATE0);
- HW_DESC_SET_FLOW_MODE(&desc[idx], S_DIN_to_HASH);
- HW_DESC_SET_AES_NOT_HASH_MODE(&desc[idx]);
+ hw_desc_init(&desc[idx]);
+ set_cipher_mode(&desc[idx], DRV_CIPHER_CBC_MAC);
+ set_key_size_aes(&desc[idx], key_size);
+ set_din_type(&desc[idx], DMA_DLLI, mac_res_dma_addr,
+ NIST_AESCCM_TAG_SIZE, NS_BIT);
+ set_cipher_config0(&desc[idx], DESC_DIRECTION_ENCRYPT_ENCRYPT);
+ set_setup_mode(&desc[idx], SETUP_LOAD_STATE0);
+ set_flow_mode(&desc[idx], S_DIN_to_HASH);
+ set_aes_not_hash_mode(&desc[idx]);
idx++;
/* prcess assoc data */
- HW_DESC_INIT(&desc[idx]);
- HW_DESC_SET_DIN_TYPE(&desc[idx], DMA_DLLI, b0_a0_adata_dma_addr, b0_a0_adata_size, NS_BIT);
- HW_DESC_SET_FLOW_MODE(&desc[idx], DIN_HASH);
+ hw_desc_init(&desc[idx]);
+ set_din_type(&desc[idx], DMA_DLLI, b0_a0_adata_dma_addr,
+ b0_a0_adata_size, NS_BIT);
+ set_flow_mode(&desc[idx], DIN_HASH);
idx++;
/* process the cipher */
- HW_DESC_INIT(&desc[idx]);
- HW_DESC_SET_DIN_TYPE(&desc[idx], DMA_DLLI, din_dma_addr, din_size, NS_BIT);
- HW_DESC_SET_DOUT_DLLI(&desc[idx], dout_dma_addr, din_size, NS_BIT, 0);
- HW_DESC_SET_FLOW_MODE(&desc[idx], cipher_flow_mode);
+ hw_desc_init(&desc[idx]);
+ set_din_type(&desc[idx], DMA_DLLI, din_dma_addr, din_size, NS_BIT);
+ set_dout_dlli(&desc[idx], dout_dma_addr, din_size, NS_BIT, 0);
+ set_flow_mode(&desc[idx], cipher_flow_mode);
idx++;
/* Read temporal MAC */
- HW_DESC_INIT(&desc[idx]);
- HW_DESC_SET_CIPHER_MODE(&desc[idx], DRV_CIPHER_CBC_MAC);
- HW_DESC_SET_DOUT_DLLI(&desc[idx], mac_res_dma_addr, NIST_AESCCM_TAG_SIZE, NS_BIT, 0);
- HW_DESC_SET_SETUP_MODE(&desc[idx], SETUP_WRITE_STATE0);
- HW_DESC_SET_CIPHER_CONFIG0(&desc[idx], HASH_DIGEST_RESULT_LITTLE_ENDIAN);
- HW_DESC_SET_FLOW_MODE(&desc[idx], S_HASH_to_DOUT);
- HW_DESC_SET_AES_NOT_HASH_MODE(&desc[idx]);
+ hw_desc_init(&desc[idx]);
+ set_cipher_mode(&desc[idx], DRV_CIPHER_CBC_MAC);
+ set_dout_dlli(&desc[idx], mac_res_dma_addr, NIST_AESCCM_TAG_SIZE,
+ NS_BIT, 0);
+ set_setup_mode(&desc[idx], SETUP_WRITE_STATE0);
+ set_cipher_config0(&desc[idx], HASH_DIGEST_RESULT_LITTLE_ENDIAN);
+ set_flow_mode(&desc[idx], S_HASH_to_DOUT);
+ set_aes_not_hash_mode(&desc[idx]);
idx++;
/* load AES-CTR state (for last MAC calculation)*/
- HW_DESC_INIT(&desc[idx]);
- HW_DESC_SET_CIPHER_MODE(&desc[idx], DRV_CIPHER_CTR);
- HW_DESC_SET_CIPHER_CONFIG0(&desc[idx], DRV_CRYPTO_DIRECTION_ENCRYPT);
- HW_DESC_SET_DIN_TYPE(&desc[idx], DMA_DLLI,
- ctr_cnt_0_dma_addr,
- AES_BLOCK_SIZE, NS_BIT);
- HW_DESC_SET_KEY_SIZE_AES(&desc[idx], key_size);
- HW_DESC_SET_SETUP_MODE(&desc[idx], SETUP_LOAD_STATE1);
- HW_DESC_SET_FLOW_MODE(&desc[idx], S_DIN_to_AES);
+ hw_desc_init(&desc[idx]);
+ set_cipher_mode(&desc[idx], DRV_CIPHER_CTR);
+ set_cipher_config0(&desc[idx], DRV_CRYPTO_DIRECTION_ENCRYPT);
+ set_din_type(&desc[idx], DMA_DLLI, ctr_cnt_0_dma_addr, AES_BLOCK_SIZE,
+ NS_BIT);
+ set_key_size_aes(&desc[idx], key_size);
+ set_setup_mode(&desc[idx], SETUP_LOAD_STATE1);
+ set_flow_mode(&desc[idx], S_DIN_to_AES);
idx++;
/* Memory Barrier */
- HW_DESC_INIT(&desc[idx]);
- HW_DESC_SET_DIN_NO_DMA(&desc[idx], 0, 0xfffff0);
- HW_DESC_SET_DOUT_NO_DMA(&desc[idx], 0, 0, 1);
+ hw_desc_init(&desc[idx]);
+ set_din_no_dma(&desc[idx], 0, 0xfffff0);
+ set_dout_no_dma(&desc[idx], 0, 0, 1);
idx++;
/* encrypt the "T" value and store MAC inplace */
- HW_DESC_INIT(&desc[idx]);
- HW_DESC_SET_DIN_TYPE(&desc[idx], DMA_DLLI, mac_res_dma_addr, NIST_AESCCM_TAG_SIZE, NS_BIT);
- HW_DESC_SET_DOUT_DLLI(&desc[idx], mac_res_dma_addr, NIST_AESCCM_TAG_SIZE, NS_BIT, 0);
- HW_DESC_SET_FLOW_MODE(&desc[idx], DIN_AES_DOUT);
- idx++;
+ hw_desc_init(&desc[idx]);
+ set_din_type(&desc[idx], DMA_DLLI, mac_res_dma_addr,
+ NIST_AESCCM_TAG_SIZE, NS_BIT);
+ set_dout_dlli(&desc[idx], mac_res_dma_addr, NIST_AESCCM_TAG_SIZE,
+ NS_BIT, 0);
+ set_flow_mode(&desc[idx], DIN_AES_DOUT);
+ idx++;
/* perform the operation - Lock HW and push sequence */
BUG_ON(idx > FIPS_CCM_MAX_SEQ_LEN);
@@ -1244,10 +1235,10 @@ ssi_ccm_fips_run_test(struct ssi_drvdata *drvdata,
return rc;
}
-ssi_fips_error_t
+enum cc_fips_error
ssi_ccm_fips_power_up_tests(struct ssi_drvdata *drvdata, void *cpu_addr_buffer, dma_addr_t dma_coherent_buffer)
{
- ssi_fips_error_t error = CC_REE_FIPS_ERROR_OK;
+ enum cc_fips_error error = CC_REE_FIPS_ERROR_OK;
size_t i;
struct fips_ccm_ctx *virt_ctx = (struct fips_ccm_ctx *)cpu_addr_buffer;
@@ -1262,7 +1253,7 @@ ssi_ccm_fips_power_up_tests(struct ssi_drvdata *drvdata, void *cpu_addr_buffer,
for (i = 0; i < FIPS_CCM_NUM_OF_TESTS; ++i)
{
- FipsCcmData *ccmData = (FipsCcmData*)&FipsCcmDataTable[i];
+ FipsCcmData *ccmData = (FipsCcmData *)&FipsCcmDataTable[i];
int rc = 0;
memset(cpu_addr_buffer, 0, sizeof(struct fips_ccm_ctx));
@@ -1273,6 +1264,7 @@ ssi_ccm_fips_power_up_tests(struct ssi_drvdata *drvdata, void *cpu_addr_buffer,
{
/* build B0 -- B0, nonce, l(m) */
__be16 data = cpu_to_be16(NIST_AESCCM_TEXT_SIZE);
+
virt_ctx->b0_a0_adata[0] = NIST_AESCCM_B0_VAL;
memcpy(virt_ctx->b0_a0_adata + 1, ccmData->nonce, NIST_AESCCM_NONCE_SIZE);
memcpy(virt_ctx->b0_a0_adata + 14, (u8 *)&data, sizeof(__be16));
@@ -1313,9 +1305,9 @@ ssi_ccm_fips_power_up_tests(struct ssi_drvdata *drvdata, void *cpu_addr_buffer,
if (memcmp(virt_ctx->dout, ccmData->dataOut, ccmData->dataInSize) != 0)
{
FIPS_LOG("dout comparison error %d - size=%d \n", i, ccmData->dataInSize);
- error = CC_REE_FIPS_ERROR_AESCCM_PUT;
+ error = CC_REE_FIPS_ERROR_AESCCM_PUT;
break;
- }
+ }
/* compare actual mac result to expected */
if (memcmp(virt_ctx->mac_res, ccmData->macResOut, ccmData->tagSize) != 0)
@@ -1336,7 +1328,6 @@ ssi_ccm_fips_power_up_tests(struct ssi_drvdata *drvdata, void *cpu_addr_buffer,
return error;
}
-
static inline int
ssi_gcm_fips_run_test(struct ssi_drvdata *drvdata,
enum drv_crypto_direction direction,
@@ -1358,7 +1349,7 @@ ssi_gcm_fips_run_test(struct ssi_drvdata *drvdata,
int rc;
struct ssi_crypto_req ssi_req = {0};
- HwDesc_s desc[FIPS_GCM_MAX_SEQ_LEN];
+ struct cc_hw_desc desc[FIPS_GCM_MAX_SEQ_LEN];
unsigned int idx = 0;
unsigned int cipher_flow_mode;
@@ -1372,186 +1363,162 @@ ssi_gcm_fips_run_test(struct ssi_drvdata *drvdata,
// ssi_aead_gcm_setup_ghash_desc(req, desc, seq_size);
///////////////////////////////// 1 ////////////////////////////////////
- /* load key to AES*/
- HW_DESC_INIT(&desc[idx]);
- HW_DESC_SET_CIPHER_MODE(&desc[idx], DRV_CIPHER_ECB);
- HW_DESC_SET_CIPHER_CONFIG0(&desc[idx], DRV_CRYPTO_DIRECTION_ENCRYPT);
- HW_DESC_SET_DIN_TYPE(&desc[idx],
- DMA_DLLI, key_dma_addr, key_size,
- NS_BIT);
- HW_DESC_SET_KEY_SIZE_AES(&desc[idx], key_size);
- HW_DESC_SET_SETUP_MODE(&desc[idx], SETUP_LOAD_KEY0);
- HW_DESC_SET_FLOW_MODE(&desc[idx], S_DIN_to_AES);
+ /* load key to AES */
+ hw_desc_init(&desc[idx]);
+ set_cipher_mode(&desc[idx], DRV_CIPHER_ECB);
+ set_cipher_config0(&desc[idx], DRV_CRYPTO_DIRECTION_ENCRYPT);
+ set_din_type(&desc[idx], DMA_DLLI, key_dma_addr, key_size, NS_BIT);
+ set_key_size_aes(&desc[idx], key_size);
+ set_setup_mode(&desc[idx], SETUP_LOAD_KEY0);
+ set_flow_mode(&desc[idx], S_DIN_to_AES);
idx++;
/* process one zero block to generate hkey */
- HW_DESC_INIT(&desc[idx]);
- HW_DESC_SET_DIN_CONST(&desc[idx], 0x0, AES_BLOCK_SIZE);
- HW_DESC_SET_DOUT_DLLI(&desc[idx],
- hkey_dma_addr, AES_BLOCK_SIZE,
- NS_BIT, 0);
- HW_DESC_SET_FLOW_MODE(&desc[idx], DIN_AES_DOUT);
+ hw_desc_init(&desc[idx]);
+ set_din_const(&desc[idx], 0x0, AES_BLOCK_SIZE);
+ set_dout_dlli(&desc[idx], hkey_dma_addr, AES_BLOCK_SIZE, NS_BIT, 0);
+ set_flow_mode(&desc[idx], DIN_AES_DOUT);
idx++;
/* Memory Barrier */
- HW_DESC_INIT(&desc[idx]);
- HW_DESC_SET_DIN_NO_DMA(&desc[idx], 0, 0xfffff0);
- HW_DESC_SET_DOUT_NO_DMA(&desc[idx], 0, 0, 1);
+ hw_desc_init(&desc[idx]);
+ set_din_no_dma(&desc[idx], 0, 0xfffff0);
+ set_dout_no_dma(&desc[idx], 0, 0, 1);
idx++;
/* Load GHASH subkey */
- HW_DESC_INIT(&desc[idx]);
- HW_DESC_SET_DIN_TYPE(&desc[idx], DMA_DLLI,
- hkey_dma_addr, AES_BLOCK_SIZE,
- NS_BIT);
- HW_DESC_SET_DOUT_NO_DMA(&desc[idx], 0, 0, 1);
- HW_DESC_SET_FLOW_MODE(&desc[idx], S_DIN_to_HASH);
- HW_DESC_SET_AES_NOT_HASH_MODE(&desc[idx]);
- HW_DESC_SET_CIPHER_MODE(&desc[idx], DRV_HASH_HW_GHASH);
- HW_DESC_SET_CIPHER_CONFIG1(&desc[idx], HASH_PADDING_ENABLED);
- HW_DESC_SET_SETUP_MODE(&desc[idx], SETUP_LOAD_KEY0);
+ hw_desc_init(&desc[idx]);
+ set_din_type(&desc[idx], DMA_DLLI, hkey_dma_addr, AES_BLOCK_SIZE,
+ NS_BIT);
+ set_dout_no_dma(&desc[idx], 0, 0, 1);
+ set_flow_mode(&desc[idx], S_DIN_to_HASH);
+ set_aes_not_hash_mode(&desc[idx]);
+ set_cipher_mode(&desc[idx], DRV_HASH_HW_GHASH);
+ set_cipher_config1(&desc[idx], HASH_PADDING_ENABLED);
+ set_setup_mode(&desc[idx], SETUP_LOAD_KEY0);
idx++;
/* Configure Hash Engine to work with GHASH.
- Since it was not possible to extend HASH submodes to add GHASH,
- The following command is necessary in order to select GHASH (according to HW designers)*/
- HW_DESC_INIT(&desc[idx]);
- HW_DESC_SET_DIN_NO_DMA(&desc[idx], 0, 0xfffff0);
- HW_DESC_SET_DOUT_NO_DMA(&desc[idx], 0, 0, 1);
- HW_DESC_SET_FLOW_MODE(&desc[idx], S_DIN_to_HASH);
- HW_DESC_SET_AES_NOT_HASH_MODE(&desc[idx]);
- HW_DESC_SET_CIPHER_MODE(&desc[idx], DRV_HASH_HW_GHASH);
- HW_DESC_SET_CIPHER_DO(&desc[idx], 1); //1=AES_SK RKEK
- HW_DESC_SET_CIPHER_CONFIG0(&desc[idx], DRV_CRYPTO_DIRECTION_ENCRYPT);
- HW_DESC_SET_CIPHER_CONFIG1(&desc[idx], HASH_PADDING_ENABLED);
- HW_DESC_SET_SETUP_MODE(&desc[idx], SETUP_LOAD_KEY0);
+ * Since it was not possible to extend HASH submodes to add GHASH,
+ * The following command is necessary in order to
+ * select GHASH (according to HW designers)
+ */
+ hw_desc_init(&desc[idx]);
+ set_din_no_dma(&desc[idx], 0, 0xfffff0);
+ set_dout_no_dma(&desc[idx], 0, 0, 1);
+ set_flow_mode(&desc[idx], S_DIN_to_HASH);
+ set_aes_not_hash_mode(&desc[idx]);
+ set_cipher_mode(&desc[idx], DRV_HASH_HW_GHASH);
+ set_cipher_do(&desc[idx], 1); //1=AES_SK RKEK
+ set_cipher_config0(&desc[idx], DRV_CRYPTO_DIRECTION_ENCRYPT);
+ set_cipher_config1(&desc[idx], HASH_PADDING_ENABLED);
+ set_setup_mode(&desc[idx], SETUP_LOAD_KEY0);
idx++;
/* Load GHASH initial STATE (which is 0). (for any hash there is an initial state) */
- HW_DESC_INIT(&desc[idx]);
- HW_DESC_SET_DIN_CONST(&desc[idx], 0x0, AES_BLOCK_SIZE);
- HW_DESC_SET_DOUT_NO_DMA(&desc[idx], 0, 0, 1);
- HW_DESC_SET_FLOW_MODE(&desc[idx], S_DIN_to_HASH);
- HW_DESC_SET_AES_NOT_HASH_MODE(&desc[idx]);
- HW_DESC_SET_CIPHER_MODE(&desc[idx], DRV_HASH_HW_GHASH);
- HW_DESC_SET_CIPHER_CONFIG1(&desc[idx], HASH_PADDING_ENABLED);
- HW_DESC_SET_SETUP_MODE(&desc[idx], SETUP_LOAD_STATE0);
+ hw_desc_init(&desc[idx]);
+ set_din_const(&desc[idx], 0x0, AES_BLOCK_SIZE);
+ set_dout_no_dma(&desc[idx], 0, 0, 1);
+ set_flow_mode(&desc[idx], S_DIN_to_HASH);
+ set_aes_not_hash_mode(&desc[idx]);
+ set_cipher_mode(&desc[idx], DRV_HASH_HW_GHASH);
+ set_cipher_config1(&desc[idx], HASH_PADDING_ENABLED);
+ set_setup_mode(&desc[idx], SETUP_LOAD_STATE0);
idx++;
-
-
///////////////////////////////// 2 ////////////////////////////////////
/* prcess(ghash) assoc data */
// if (req->assoclen > 0)
// ssi_aead_create_assoc_desc(req, DIN_HASH, desc, seq_size);
///////////////////////////////// 2 ////////////////////////////////////
- HW_DESC_INIT(&desc[idx]);
- HW_DESC_SET_DIN_TYPE(&desc[idx], DMA_DLLI,
- adata_dma_addr, adata_size,
- NS_BIT);
- HW_DESC_SET_FLOW_MODE(&desc[idx], DIN_HASH);
+ hw_desc_init(&desc[idx]);
+ set_din_type(&desc[idx], DMA_DLLI, adata_dma_addr, adata_size, NS_BIT);
+ set_flow_mode(&desc[idx], DIN_HASH);
idx++;
-
///////////////////////////////// 3 ////////////////////////////////////
// ssi_aead_gcm_setup_gctr_desc(req, desc, seq_size);
///////////////////////////////// 3 ////////////////////////////////////
/* load key to AES*/
- HW_DESC_INIT(&desc[idx]);
- HW_DESC_SET_CIPHER_MODE(&desc[idx], DRV_CIPHER_GCTR);
- HW_DESC_SET_CIPHER_CONFIG0(&desc[idx], DRV_CRYPTO_DIRECTION_ENCRYPT);
- HW_DESC_SET_DIN_TYPE(&desc[idx], DMA_DLLI,
- key_dma_addr, key_size,
- NS_BIT);
- HW_DESC_SET_KEY_SIZE_AES(&desc[idx], key_size);
- HW_DESC_SET_SETUP_MODE(&desc[idx], SETUP_LOAD_KEY0);
- HW_DESC_SET_FLOW_MODE(&desc[idx], S_DIN_to_AES);
+ hw_desc_init(&desc[idx]);
+ set_cipher_mode(&desc[idx], DRV_CIPHER_GCTR);
+ set_cipher_config0(&desc[idx], DRV_CRYPTO_DIRECTION_ENCRYPT);
+ set_din_type(&desc[idx], DMA_DLLI, key_dma_addr, key_size, NS_BIT);
+ set_key_size_aes(&desc[idx], key_size);
+ set_setup_mode(&desc[idx], SETUP_LOAD_KEY0);
+ set_flow_mode(&desc[idx], S_DIN_to_AES);
idx++;
/* load AES/CTR initial CTR value inc by 2*/
- HW_DESC_INIT(&desc[idx]);
- HW_DESC_SET_CIPHER_MODE(&desc[idx], DRV_CIPHER_GCTR);
- HW_DESC_SET_KEY_SIZE_AES(&desc[idx], key_size);
- HW_DESC_SET_DIN_TYPE(&desc[idx], DMA_DLLI,
- iv_inc2_dma_addr, AES_BLOCK_SIZE,
- NS_BIT);
- HW_DESC_SET_CIPHER_CONFIG0(&desc[idx], DRV_CRYPTO_DIRECTION_ENCRYPT);
- HW_DESC_SET_SETUP_MODE(&desc[idx], SETUP_LOAD_STATE1);
- HW_DESC_SET_FLOW_MODE(&desc[idx], S_DIN_to_AES);
+ hw_desc_init(&desc[idx]);
+ set_cipher_mode(&desc[idx], DRV_CIPHER_GCTR);
+ set_key_size_aes(&desc[idx], key_size);
+ set_din_type(&desc[idx], DMA_DLLI, iv_inc2_dma_addr, AES_BLOCK_SIZE,
+ NS_BIT);
+ set_cipher_config0(&desc[idx], DRV_CRYPTO_DIRECTION_ENCRYPT);
+ set_setup_mode(&desc[idx], SETUP_LOAD_STATE1);
+ set_flow_mode(&desc[idx], S_DIN_to_AES);
idx++;
-
///////////////////////////////// 4 ////////////////////////////////////
/* process(gctr+ghash) */
// if (req_ctx->cryptlen != 0)
-// ssi_aead_process_cipher_data_desc(req, cipher_flow_mode, desc, seq_size);
+// ssi_aead_process_cipher_data_desc(req, cipher_flow_mode, desc, seq_size);
///////////////////////////////// 4 ////////////////////////////////////
- HW_DESC_INIT(&desc[idx]);
- HW_DESC_SET_DIN_TYPE(&desc[idx], DMA_DLLI,
- din_dma_addr, din_size,
- NS_BIT);
- HW_DESC_SET_DOUT_DLLI(&desc[idx],
- dout_dma_addr, din_size,
- NS_BIT, 0);
- HW_DESC_SET_FLOW_MODE(&desc[idx], cipher_flow_mode);
+ hw_desc_init(&desc[idx]);
+ set_din_type(&desc[idx], DMA_DLLI, din_dma_addr, din_size, NS_BIT);
+ set_dout_dlli(&desc[idx], dout_dma_addr, din_size, NS_BIT, 0);
+ set_flow_mode(&desc[idx], cipher_flow_mode);
idx++;
-
///////////////////////////////// 5 ////////////////////////////////////
// ssi_aead_process_gcm_result_desc(req, desc, seq_size);
///////////////////////////////// 5 ////////////////////////////////////
/* prcess(ghash) gcm_block_len */
- HW_DESC_INIT(&desc[idx]);
- HW_DESC_SET_DIN_TYPE(&desc[idx], DMA_DLLI,
- block_len_dma_addr, AES_BLOCK_SIZE,
- NS_BIT);
- HW_DESC_SET_FLOW_MODE(&desc[idx], DIN_HASH);
+ hw_desc_init(&desc[idx]);
+ set_din_type(&desc[idx], DMA_DLLI, block_len_dma_addr, AES_BLOCK_SIZE,
+ NS_BIT);
+ set_flow_mode(&desc[idx], DIN_HASH);
idx++;
/* Store GHASH state after GHASH(Associated Data + Cipher +LenBlock) */
- HW_DESC_INIT(&desc[idx]);
- HW_DESC_SET_CIPHER_MODE(&desc[idx], DRV_HASH_HW_GHASH);
- HW_DESC_SET_DIN_NO_DMA(&desc[idx], 0, 0xfffff0);
- HW_DESC_SET_DOUT_DLLI(&desc[idx],
- mac_res_dma_addr, AES_BLOCK_SIZE,
- NS_BIT, 0);
- HW_DESC_SET_SETUP_MODE(&desc[idx], SETUP_WRITE_STATE0);
- HW_DESC_SET_FLOW_MODE(&desc[idx], S_HASH_to_DOUT);
- HW_DESC_SET_AES_NOT_HASH_MODE(&desc[idx]);
- idx++;
+ hw_desc_init(&desc[idx]);
+ set_cipher_mode(&desc[idx], DRV_HASH_HW_GHASH);
+ set_din_no_dma(&desc[idx], 0, 0xfffff0);
+ set_dout_dlli(&desc[idx], mac_res_dma_addr, AES_BLOCK_SIZE, NS_BIT, 0);
+ set_setup_mode(&desc[idx], SETUP_WRITE_STATE0);
+ set_flow_mode(&desc[idx], S_HASH_to_DOUT);
+ set_aes_not_hash_mode(&desc[idx]);
+ idx++;
/* load AES/CTR initial CTR value inc by 1*/
- HW_DESC_INIT(&desc[idx]);
- HW_DESC_SET_CIPHER_MODE(&desc[idx], DRV_CIPHER_GCTR);
- HW_DESC_SET_KEY_SIZE_AES(&desc[idx], key_size);
- HW_DESC_SET_DIN_TYPE(&desc[idx], DMA_DLLI,
- iv_inc1_dma_addr, AES_BLOCK_SIZE,
- NS_BIT);
- HW_DESC_SET_CIPHER_CONFIG0(&desc[idx], DRV_CRYPTO_DIRECTION_ENCRYPT);
- HW_DESC_SET_SETUP_MODE(&desc[idx], SETUP_LOAD_STATE1);
- HW_DESC_SET_FLOW_MODE(&desc[idx], S_DIN_to_AES);
+ hw_desc_init(&desc[idx]);
+ set_cipher_mode(&desc[idx], DRV_CIPHER_GCTR);
+ set_key_size_aes(&desc[idx], key_size);
+ set_din_type(&desc[idx], DMA_DLLI, iv_inc1_dma_addr, AES_BLOCK_SIZE,
+ NS_BIT);
+ set_cipher_config0(&desc[idx], DRV_CRYPTO_DIRECTION_ENCRYPT);
+ set_setup_mode(&desc[idx], SETUP_LOAD_STATE1);
+ set_flow_mode(&desc[idx], S_DIN_to_AES);
idx++;
/* Memory Barrier */
- HW_DESC_INIT(&desc[idx]);
- HW_DESC_SET_DIN_NO_DMA(&desc[idx], 0, 0xfffff0);
- HW_DESC_SET_DOUT_NO_DMA(&desc[idx], 0, 0, 1);
+ hw_desc_init(&desc[idx]);
+ set_din_no_dma(&desc[idx], 0, 0xfffff0);
+ set_dout_no_dma(&desc[idx], 0, 0, 1);
idx++;
/* process GCTR on stored GHASH and store MAC inplace */
- HW_DESC_INIT(&desc[idx]);
- HW_DESC_SET_CIPHER_MODE(&desc[idx], DRV_CIPHER_GCTR);
- HW_DESC_SET_DIN_TYPE(&desc[idx], DMA_DLLI,
- mac_res_dma_addr, AES_BLOCK_SIZE,
- NS_BIT);
- HW_DESC_SET_DOUT_DLLI(&desc[idx],
- mac_res_dma_addr, AES_BLOCK_SIZE,
- NS_BIT, 0);
- HW_DESC_SET_FLOW_MODE(&desc[idx], DIN_AES_DOUT);
+ hw_desc_init(&desc[idx]);
+ set_cipher_mode(&desc[idx], DRV_CIPHER_GCTR);
+ set_din_type(&desc[idx], DMA_DLLI, mac_res_dma_addr, AES_BLOCK_SIZE,
+ NS_BIT);
+ set_dout_dlli(&desc[idx], mac_res_dma_addr, AES_BLOCK_SIZE, NS_BIT, 0);
+ set_flow_mode(&desc[idx], DIN_AES_DOUT);
idx++;
/* perform the operation - Lock HW and push sequence */
@@ -1561,10 +1528,10 @@ ssi_gcm_fips_run_test(struct ssi_drvdata *drvdata,
return rc;
}
-ssi_fips_error_t
+enum cc_fips_error
ssi_gcm_fips_power_up_tests(struct ssi_drvdata *drvdata, void *cpu_addr_buffer, dma_addr_t dma_coherent_buffer)
{
- ssi_fips_error_t error = CC_REE_FIPS_ERROR_OK;
+ enum cc_fips_error error = CC_REE_FIPS_ERROR_OK;
size_t i;
struct fips_gcm_ctx *virt_ctx = (struct fips_gcm_ctx *)cpu_addr_buffer;
@@ -1581,7 +1548,7 @@ ssi_gcm_fips_power_up_tests(struct ssi_drvdata *drvdata, void *cpu_addr_buffer,
for (i = 0; i < FIPS_GCM_NUM_OF_TESTS; ++i)
{
- FipsGcmData *gcmData = (FipsGcmData*)&FipsGcmDataTable[i];
+ FipsGcmData *gcmData = (FipsGcmData *)&FipsGcmDataTable[i];
int rc = 0;
memset(cpu_addr_buffer, 0, sizeof(struct fips_gcm_ctx));
@@ -1594,6 +1561,7 @@ ssi_gcm_fips_power_up_tests(struct ssi_drvdata *drvdata, void *cpu_addr_buffer,
/* len_block */
{
__be64 len_bits;
+
len_bits = cpu_to_be64(gcmData->adataSize * 8);
memcpy(virt_ctx->len_block, &len_bits, sizeof(len_bits));
len_bits = cpu_to_be64(gcmData->dataInSize * 8);
@@ -1602,6 +1570,7 @@ ssi_gcm_fips_power_up_tests(struct ssi_drvdata *drvdata, void *cpu_addr_buffer,
/* iv_inc1, iv_inc2 */
{
__be32 counter = cpu_to_be32(1);
+
memcpy(virt_ctx->iv_inc1, gcmData->iv, NIST_AESGCM_IV_SIZE);
memcpy(virt_ctx->iv_inc1 + NIST_AESGCM_IV_SIZE, &counter, sizeof(counter));
counter = cpu_to_be32(2);
@@ -1666,7 +1635,6 @@ ssi_gcm_fips_power_up_tests(struct ssi_drvdata *drvdata, void *cpu_addr_buffer,
return error;
}
-
size_t ssi_fips_max_mem_alloc_size(void)
{
FIPS_DBG("sizeof(struct fips_cipher_ctx) %d \n", sizeof(struct fips_cipher_ctx));
diff --git a/drivers/staging/ccree/ssi_fips_local.c b/drivers/staging/ccree/ssi_fips_local.c
index 51b535a2a09a..aefb71dc9e9a 100644
--- a/drivers/staging/ccree/ssi_fips_local.c
+++ b/drivers/staging/ccree/ssi_fips_local.c
@@ -1,22 +1,22 @@
/*
* Copyright (C) 2012-2017 ARM Limited or its affiliates.
- *
+ *
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
- *
+ *
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
- *
+ *
* You should have received a copy of the GNU General Public License
* along with this program; if not, see <http://www.gnu.org/licenses/>.
*/
/**************************************************************
-This file defines the driver FIPS internal function, used by the driver itself.
-***************************************************************/
+ * This file defines the driver FIPS internal function, used by the driver itself.
+ ***************************************************************/
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/platform_device.h>
@@ -26,7 +26,6 @@ This file defines the driver FIPS internal function, used by the driver itself.
#include "ssi_driver.h"
#include "cc_hal.h"
-
#define FIPS_POWER_UP_TEST_CIPHER 1
#define FIPS_POWER_UP_TEST_CMAC 1
#define FIPS_POWER_UP_TEST_HASH 1
@@ -49,62 +48,57 @@ struct ssi_fips_handle {
#endif
};
-
-extern int ssi_fips_get_state(ssi_fips_state_t *p_state);
-extern int ssi_fips_get_error(ssi_fips_error_t *p_err);
-extern int ssi_fips_ext_set_state(ssi_fips_state_t state);
-extern int ssi_fips_ext_set_error(ssi_fips_error_t err);
+extern int ssi_fips_get_state(enum cc_fips_state_t *p_state);
+extern int ssi_fips_get_error(enum cc_fips_error *p_err);
+extern int ssi_fips_ext_set_state(enum cc_fips_state_t state);
+extern int ssi_fips_ext_set_error(enum cc_fips_error err);
/* FIPS power-up tests */
-extern ssi_fips_error_t ssi_cipher_fips_power_up_tests(struct ssi_drvdata *drvdata, void *cpu_addr_buffer, dma_addr_t dma_coherent_buffer);
-extern ssi_fips_error_t ssi_cmac_fips_power_up_tests(struct ssi_drvdata *drvdata, void *cpu_addr_buffer, dma_addr_t dma_coherent_buffer);
-extern ssi_fips_error_t ssi_hash_fips_power_up_tests(struct ssi_drvdata *drvdata, void *cpu_addr_buffer, dma_addr_t dma_coherent_buffer);
-extern ssi_fips_error_t ssi_hmac_fips_power_up_tests(struct ssi_drvdata *drvdata, void *cpu_addr_buffer, dma_addr_t dma_coherent_buffer);
-extern ssi_fips_error_t ssi_ccm_fips_power_up_tests(struct ssi_drvdata *drvdata, void *cpu_addr_buffer, dma_addr_t dma_coherent_buffer);
-extern ssi_fips_error_t ssi_gcm_fips_power_up_tests(struct ssi_drvdata *drvdata, void *cpu_addr_buffer, dma_addr_t dma_coherent_buffer);
+extern enum cc_fips_error ssi_cipher_fips_power_up_tests(struct ssi_drvdata *drvdata, void *cpu_addr_buffer, dma_addr_t dma_coherent_buffer);
+extern enum cc_fips_error ssi_cmac_fips_power_up_tests(struct ssi_drvdata *drvdata, void *cpu_addr_buffer, dma_addr_t dma_coherent_buffer);
+extern enum cc_fips_error ssi_hash_fips_power_up_tests(struct ssi_drvdata *drvdata, void *cpu_addr_buffer, dma_addr_t dma_coherent_buffer);
+extern enum cc_fips_error ssi_hmac_fips_power_up_tests(struct ssi_drvdata *drvdata, void *cpu_addr_buffer, dma_addr_t dma_coherent_buffer);
+extern enum cc_fips_error ssi_ccm_fips_power_up_tests(struct ssi_drvdata *drvdata, void *cpu_addr_buffer, dma_addr_t dma_coherent_buffer);
+extern enum cc_fips_error ssi_gcm_fips_power_up_tests(struct ssi_drvdata *drvdata, void *cpu_addr_buffer, dma_addr_t dma_coherent_buffer);
extern size_t ssi_fips_max_mem_alloc_size(void);
-
/* The function called once at driver entry point to check whether TEE FIPS error occured.*/
static enum ssi_fips_error ssi_fips_get_tee_error(struct ssi_drvdata *drvdata)
{
- uint32_t regVal;
+ u32 regVal;
void __iomem *cc_base = drvdata->cc_base;
regVal = CC_HAL_READ_REGISTER(CC_REG_OFFSET(HOST_RGF, GPR_HOST));
- if (regVal == (CC_FIPS_SYNC_TEE_STATUS | CC_FIPS_SYNC_MODULE_OK)) {
+ if (regVal == (CC_FIPS_SYNC_TEE_STATUS | CC_FIPS_SYNC_MODULE_OK))
return CC_REE_FIPS_ERROR_OK;
- }
+
return CC_REE_FIPS_ERROR_FROM_TEE;
}
-
-/*
- This function should push the FIPS REE library status towards the TEE library.
- By writing the error state to HOST_GPR0 register. The function is called from .
- driver entry point so no need to protect by mutex.
-*/
-static void ssi_fips_update_tee_upon_ree_status(struct ssi_drvdata *drvdata, ssi_fips_error_t err)
+/*
+ * This function should push the FIPS REE library status towards the TEE library.
+ * By writing the error state to HOST_GPR0 register. The function is called from
+ * driver entry point so no need to protect by mutex.
+ */
+static void ssi_fips_update_tee_upon_ree_status(struct ssi_drvdata *drvdata, enum cc_fips_error err)
{
void __iomem *cc_base = drvdata->cc_base;
- if (err == CC_REE_FIPS_ERROR_OK) {
- CC_HAL_WRITE_REGISTER(CC_REG_OFFSET(HOST_RGF, HOST_GPR0), (CC_FIPS_SYNC_REE_STATUS|CC_FIPS_SYNC_MODULE_OK));
- } else {
- CC_HAL_WRITE_REGISTER(CC_REG_OFFSET(HOST_RGF, HOST_GPR0), (CC_FIPS_SYNC_REE_STATUS|CC_FIPS_SYNC_MODULE_ERROR));
- }
-}
-
+ if (err == CC_REE_FIPS_ERROR_OK)
+ CC_HAL_WRITE_REGISTER(CC_REG_OFFSET(HOST_RGF, HOST_GPR0), (CC_FIPS_SYNC_REE_STATUS | CC_FIPS_SYNC_MODULE_OK));
+ else
+ CC_HAL_WRITE_REGISTER(CC_REG_OFFSET(HOST_RGF, HOST_GPR0), (CC_FIPS_SYNC_REE_STATUS | CC_FIPS_SYNC_MODULE_ERROR));
+}
void ssi_fips_fini(struct ssi_drvdata *drvdata)
{
struct ssi_fips_handle *fips_h = drvdata->fips_handle;
- if (fips_h == NULL)
+ if (!fips_h)
return; /* Not allocated */
#ifdef COMP_IN_WQ
- if (fips_h->workq != NULL) {
+ if (fips_h->workq) {
flush_workqueue(fips_h->workq);
destroy_workqueue(fips_h->workq);
}
@@ -119,7 +113,7 @@ void ssi_fips_fini(struct ssi_drvdata *drvdata)
void fips_handler(struct ssi_drvdata *drvdata)
{
- struct ssi_fips_handle *fips_handle_ptr =
+ struct ssi_fips_handle *fips_handle_ptr =
drvdata->fips_handle;
#ifdef COMP_IN_WQ
queue_delayed_work(fips_handle_ptr->workq, &fips_handle_ptr->fipswork, 0);
@@ -128,8 +122,6 @@ void fips_handler(struct ssi_drvdata *drvdata)
#endif
}
-
-
#ifdef COMP_IN_WQ
static void fips_wq_handler(struct work_struct *work)
{
@@ -145,29 +137,27 @@ static void fips_dsr(unsigned long devarg)
{
struct ssi_drvdata *drvdata = (struct ssi_drvdata *)devarg;
void __iomem *cc_base = drvdata->cc_base;
- uint32_t irq;
- uint32_t teeFipsError = 0;
+ u32 irq;
+ u32 teeFipsError = 0;
irq = (drvdata->irq & (SSI_GPR0_IRQ_MASK));
if (irq & SSI_GPR0_IRQ_MASK) {
teeFipsError = CC_HAL_READ_REGISTER(CC_REG_OFFSET(HOST_RGF, GPR_HOST));
- if (teeFipsError != (CC_FIPS_SYNC_TEE_STATUS | CC_FIPS_SYNC_MODULE_OK)) {
+ if (teeFipsError != (CC_FIPS_SYNC_TEE_STATUS | CC_FIPS_SYNC_MODULE_OK))
ssi_fips_set_error(drvdata, CC_REE_FIPS_ERROR_FROM_TEE);
- }
}
/* after verifing that there is nothing to do, Unmask AXI completion interrupt */
- CC_HAL_WRITE_REGISTER(CC_REG_OFFSET(HOST_RGF, HOST_IMR),
+ CC_HAL_WRITE_REGISTER(CC_REG_OFFSET(HOST_RGF, HOST_IMR),
CC_HAL_READ_REGISTER(
CC_REG_OFFSET(HOST_RGF, HOST_IMR)) & ~irq);
}
-
-ssi_fips_error_t cc_fips_run_power_up_tests(struct ssi_drvdata *drvdata)
+enum cc_fips_error cc_fips_run_power_up_tests(struct ssi_drvdata *drvdata)
{
- ssi_fips_error_t fips_error = CC_REE_FIPS_ERROR_OK;
- void * cpu_addr_buffer = NULL;
+ enum cc_fips_error fips_error = CC_REE_FIPS_ERROR_OK;
+ void *cpu_addr_buffer = NULL;
dma_addr_t dma_handle;
size_t alloc_buff_size = ssi_fips_max_mem_alloc_size();
struct device *dev = &drvdata->plat_dev->dev;
@@ -177,9 +167,9 @@ ssi_fips_error_t cc_fips_run_power_up_tests(struct ssi_drvdata *drvdata)
// the dma_handle is the returned phy address - use it in the HW descriptor
FIPS_DBG("dma_alloc_coherent \n");
cpu_addr_buffer = dma_alloc_coherent(dev, alloc_buff_size, &dma_handle, GFP_KERNEL);
- if (cpu_addr_buffer == NULL) {
+ if (!cpu_addr_buffer)
return CC_REE_FIPS_ERROR_GENERAL;
- }
+
FIPS_DBG("allocated coherent buffer - addr 0x%08X , size = %d \n", (size_t)cpu_addr_buffer, alloc_buff_size);
#if FIPS_POWER_UP_TEST_CIPHER
@@ -229,13 +219,12 @@ ssi_fips_error_t cc_fips_run_power_up_tests(struct ssi_drvdata *drvdata)
return fips_error;
}
-
-
-/* The function checks if FIPS supported and FIPS error exists.*
-* It should be used in every driver API.*/
+/* The function checks if FIPS supported and FIPS error exists.*
+ * It should be used in every driver API.
+ */
int ssi_fips_check_fips_error(void)
{
- ssi_fips_state_t fips_state;
+ enum cc_fips_state_t fips_state;
if (ssi_fips_get_state(&fips_state) != 0) {
FIPS_LOG("ssi_fips_get_state FAILED, returning.. \n");
@@ -248,62 +237,61 @@ int ssi_fips_check_fips_error(void)
return 0;
}
-
-/* The function sets the REE FIPS state.*
-* It should be used while driver is being loaded .*/
-int ssi_fips_set_state(ssi_fips_state_t state)
+/* The function sets the REE FIPS state.*
+ * It should be used while driver is being loaded.
+ */
+int ssi_fips_set_state(enum cc_fips_state_t state)
{
return ssi_fips_ext_set_state(state);
}
-/* The function sets the REE FIPS error, and pushes the error to TEE library. *
-* It should be used when any of the KAT tests fails .*/
-int ssi_fips_set_error(struct ssi_drvdata *p_drvdata, ssi_fips_error_t err)
+/* The function sets the REE FIPS error, and pushes the error to TEE library. *
+ * It should be used when any of the KAT tests fails.
+ */
+int ssi_fips_set_error(struct ssi_drvdata *p_drvdata, enum cc_fips_error err)
{
int rc = 0;
- ssi_fips_error_t current_err;
+ enum cc_fips_error current_err;
- FIPS_LOG("ssi_fips_set_error - fips_error = %d \n", err);
+ FIPS_LOG("ssi_fips_set_error - fips_error = %d \n", err);
// setting no error is not allowed
- if (err == CC_REE_FIPS_ERROR_OK) {
- return -ENOEXEC;
- }
- // If error exists, do not set new error
- if (ssi_fips_get_error(&current_err) != 0) {
- return -ENOEXEC;
- }
- if (current_err != CC_REE_FIPS_ERROR_OK) {
- return -ENOEXEC;
- }
- // set REE internal error and state
+ if (err == CC_REE_FIPS_ERROR_OK)
+ return -ENOEXEC;
+
+ // If error exists, do not set new error
+ if (ssi_fips_get_error(&current_err) != 0)
+ return -ENOEXEC;
+
+ if (current_err != CC_REE_FIPS_ERROR_OK)
+ return -ENOEXEC;
+
+ // set REE internal error and state
rc = ssi_fips_ext_set_error(err);
- if (rc != 0) {
- return -ENOEXEC;
- }
+ if (rc != 0)
+ return -ENOEXEC;
+
rc = ssi_fips_ext_set_state(CC_FIPS_STATE_ERROR);
- if (rc != 0) {
- return -ENOEXEC;
- }
+ if (rc != 0)
+ return -ENOEXEC;
- // push error towards TEE libraray, if it's not TEE error
- if (err != CC_REE_FIPS_ERROR_FROM_TEE) {
+ // push error towards TEE libraray, if it's not TEE error
+ if (err != CC_REE_FIPS_ERROR_FROM_TEE)
ssi_fips_update_tee_upon_ree_status(p_drvdata, err);
- }
+
return rc;
}
-
/* The function called once at driver entry point .*/
int ssi_fips_init(struct ssi_drvdata *p_drvdata)
{
- ssi_fips_error_t rc = CC_REE_FIPS_ERROR_OK;
+ enum cc_fips_error rc = CC_REE_FIPS_ERROR_OK;
struct ssi_fips_handle *fips_h;
FIPS_DBG("CC FIPS code .. (fips=%d) \n", ssi_fips_support);
- fips_h = kzalloc(sizeof(struct ssi_fips_handle),GFP_KERNEL);
- if (fips_h == NULL) {
+ fips_h = kzalloc(sizeof(struct ssi_fips_handle), GFP_KERNEL);
+ if (!fips_h) {
ssi_fips_set_error(p_drvdata, CC_REE_FIPS_ERROR_GENERAL);
return -ENOMEM;
}
@@ -313,7 +301,7 @@ int ssi_fips_init(struct ssi_drvdata *p_drvdata)
#ifdef COMP_IN_WQ
SSI_LOG_DEBUG("Initializing fips workqueue\n");
fips_h->workq = create_singlethread_workqueue("arm_cc7x_fips_wq");
- if (unlikely(fips_h->workq == NULL)) {
+ if (unlikely(!fips_h->workq)) {
SSI_LOG_ERR("Failed creating fips work queue\n");
ssi_fips_set_error(p_drvdata, CC_REE_FIPS_ERROR_GENERAL);
rc = -ENOMEM;
@@ -326,7 +314,7 @@ int ssi_fips_init(struct ssi_drvdata *p_drvdata)
#endif
/* init fips driver data */
- rc = ssi_fips_set_state((ssi_fips_support == 0)? CC_FIPS_STATE_NOT_SUPPORTED : CC_FIPS_STATE_SUPPORTED);
+ rc = ssi_fips_set_state((ssi_fips_support == 0) ? CC_FIPS_STATE_NOT_SUPPORTED : CC_FIPS_STATE_SUPPORTED);
if (unlikely(rc != 0)) {
ssi_fips_set_error(p_drvdata, CC_REE_FIPS_ERROR_GENERAL);
rc = -EAGAIN;
diff --git a/drivers/staging/ccree/ssi_fips_local.h b/drivers/staging/ccree/ssi_fips_local.h
index 65997c15a20e..8c7994fe9fae 100644
--- a/drivers/staging/ccree/ssi_fips_local.h
+++ b/drivers/staging/ccree/ssi_fips_local.h
@@ -1,15 +1,15 @@
/*
* Copyright (C) 2012-2017 ARM Limited or its affiliates.
- *
+ *
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
- *
+ *
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
- *
+ *
* You should have received a copy of the GNU General Public License
* along with this program; if not, see <http://www.gnu.org/licenses/>.
*/
@@ -17,32 +17,23 @@
#ifndef __SSI_FIPS_LOCAL_H__
#define __SSI_FIPS_LOCAL_H__
-
#ifdef CONFIG_CCX7REE_FIPS_SUPPORT
#include "ssi_fips.h"
struct ssi_drvdata;
-// IG - how to make 1 file for TEE and REE
-typedef enum CC_FipsSyncStatus{
- CC_FIPS_SYNC_MODULE_OK = 0x0,
- CC_FIPS_SYNC_MODULE_ERROR = 0x1,
- CC_FIPS_SYNC_REE_STATUS = 0x4,
- CC_FIPS_SYNC_TEE_STATUS = 0x8,
- CC_FIPS_SYNC_STATUS_RESERVE32B = INT32_MAX
-}CCFipsSyncStatus_t;
-
-
#define CHECK_AND_RETURN_UPON_FIPS_ERROR() {\
- if (ssi_fips_check_fips_error() != 0) {\
- return -ENOEXEC;\
- }\
+ if (ssi_fips_check_fips_error() != 0) {\
+ return -ENOEXEC;\
+ } \
}
+
#define CHECK_AND_RETURN_VOID_UPON_FIPS_ERROR() {\
- if (ssi_fips_check_fips_error() != 0) {\
- return;\
- }\
+ if (ssi_fips_check_fips_error() != 0) {\
+ return;\
+ } \
}
+
#define SSI_FIPS_INIT(p_drvData) (ssi_fips_init(p_drvData))
#define SSI_FIPS_FINI(p_drvData) (ssi_fips_fini(p_drvData))
@@ -53,7 +44,7 @@ typedef enum CC_FipsSyncStatus{
int ssi_fips_init(struct ssi_drvdata *p_drvdata);
void ssi_fips_fini(struct ssi_drvdata *drvdata);
int ssi_fips_check_fips_error(void);
-int ssi_fips_set_error(struct ssi_drvdata *p_drvdata, ssi_fips_error_t err);
+int ssi_fips_set_error(struct ssi_drvdata *p_drvdata, enum cc_fips_error err);
void fips_handler(struct ssi_drvdata *drvdata);
#else /* CONFIG_CC7XXREE_FIPS_SUPPORT */
@@ -72,6 +63,5 @@ void fips_handler(struct ssi_drvdata *drvdata);
#endif /* CONFIG_CC7XXREE_FIPS_SUPPORT */
-
#endif /*__SSI_FIPS_LOCAL_H__*/
diff --git a/drivers/staging/ccree/ssi_hash.c b/drivers/staging/ccree/ssi_hash.c
index f99d4219b01e..ae8f36af3837 100644
--- a/drivers/staging/ccree/ssi_hash.c
+++ b/drivers/staging/ccree/ssi_hash.c
@@ -1,15 +1,15 @@
/*
* Copyright (C) 2012-2017 ARM Limited or its affiliates.
- *
+ *
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
- *
+ *
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
- *
+ *
* You should have received a copy of the GNU General Public License
* along with this program; if not, see <http://www.gnu.org/licenses/>.
*/
@@ -42,64 +42,61 @@ struct ssi_hash_handle {
struct completion init_comp;
};
-static const uint32_t digest_len_init[] = {
+static const u32 digest_len_init[] = {
0x00000040, 0x00000000, 0x00000000, 0x00000000 };
-static const uint32_t md5_init[] = {
+static const u32 md5_init[] = {
SHA1_H3, SHA1_H2, SHA1_H1, SHA1_H0 };
-static const uint32_t sha1_init[] = {
+static const u32 sha1_init[] = {
SHA1_H4, SHA1_H3, SHA1_H2, SHA1_H1, SHA1_H0 };
-static const uint32_t sha224_init[] = {
+static const u32 sha224_init[] = {
SHA224_H7, SHA224_H6, SHA224_H5, SHA224_H4,
SHA224_H3, SHA224_H2, SHA224_H1, SHA224_H0 };
-static const uint32_t sha256_init[] = {
+static const u32 sha256_init[] = {
SHA256_H7, SHA256_H6, SHA256_H5, SHA256_H4,
SHA256_H3, SHA256_H2, SHA256_H1, SHA256_H0 };
#if (DX_DEV_SHA_MAX > 256)
-static const uint32_t digest_len_sha512_init[] = {
+static const u32 digest_len_sha512_init[] = {
0x00000080, 0x00000000, 0x00000000, 0x00000000 };
-static const uint64_t sha384_init[] = {
+static const u64 sha384_init[] = {
SHA384_H7, SHA384_H6, SHA384_H5, SHA384_H4,
SHA384_H3, SHA384_H2, SHA384_H1, SHA384_H0 };
-static const uint64_t sha512_init[] = {
+static const u64 sha512_init[] = {
SHA512_H7, SHA512_H6, SHA512_H5, SHA512_H4,
SHA512_H3, SHA512_H2, SHA512_H1, SHA512_H0 };
#endif
static void ssi_hash_create_xcbc_setup(
- struct ahash_request *areq,
- HwDesc_s desc[],
+ struct ahash_request *areq,
+ struct cc_hw_desc desc[],
unsigned int *seq_size);
-static void ssi_hash_create_cmac_setup(struct ahash_request *areq,
- HwDesc_s desc[],
+static void ssi_hash_create_cmac_setup(struct ahash_request *areq,
+ struct cc_hw_desc desc[],
unsigned int *seq_size);
struct ssi_hash_alg {
struct list_head entry;
- bool synchronize;
int hash_mode;
int hw_mode;
int inter_digestsize;
struct ssi_drvdata *drvdata;
- union {
- struct ahash_alg ahash_alg;
- struct shash_alg shash_alg;
- };
+ struct ahash_alg ahash_alg;
};
-
struct hash_key_req_ctx {
- uint32_t keylen;
+ u32 keylen;
dma_addr_t key_dma_addr;
};
/* hash per-session context */
struct ssi_hash_ctx {
struct ssi_drvdata *drvdata;
- /* holds the origin digest; the digest after "setkey" if HMAC,*
- the initial digest if HASH. */
- uint8_t digest_buff[SSI_MAX_HASH_DIGEST_SIZE] ____cacheline_aligned;
- uint8_t opad_tmp_keys_buff[SSI_MAX_HASH_OPAD_TMP_KEYS_SIZE] ____cacheline_aligned;
+ /* holds the origin digest; the digest after "setkey" if HMAC,*
+ * the initial digest if HASH.
+ */
+ u8 digest_buff[SSI_MAX_HASH_DIGEST_SIZE] ____cacheline_aligned;
+ u8 opad_tmp_keys_buff[SSI_MAX_HASH_OPAD_TMP_KEYS_SIZE] ____cacheline_aligned;
+
dma_addr_t opad_tmp_keys_dma_addr ____cacheline_aligned;
dma_addr_t digest_buff_dma_addr;
/* use for hmac with key large then mode block size */
@@ -111,31 +108,29 @@ struct ssi_hash_ctx {
bool is_hmac;
};
-static const struct crypto_type crypto_shash_type;
-
static void ssi_hash_create_data_desc(
struct ahash_req_ctx *areq_ctx,
- struct ssi_hash_ctx *ctx,
- unsigned int flow_mode,HwDesc_s desc[],
+ struct ssi_hash_ctx *ctx,
+ unsigned int flow_mode, struct cc_hw_desc desc[],
bool is_not_last_data,
unsigned int *seq_size);
-static inline void ssi_set_hash_endianity(uint32_t mode, HwDesc_s *desc)
+static inline void ssi_set_hash_endianity(u32 mode, struct cc_hw_desc *desc)
{
if (unlikely((mode == DRV_HASH_MD5) ||
(mode == DRV_HASH_SHA384) ||
(mode == DRV_HASH_SHA512))) {
- HW_DESC_SET_BYTES_SWAP(desc, 1);
+ set_bytes_swap(desc, 1);
} else {
- HW_DESC_SET_CIPHER_CONFIG0(desc, HASH_DIGEST_RESULT_LITTLE_ENDIAN);
+ set_cipher_config0(desc, HASH_DIGEST_RESULT_LITTLE_ENDIAN);
}
}
-static int ssi_hash_map_result(struct device *dev,
- struct ahash_req_ctx *state,
+static int ssi_hash_map_result(struct device *dev,
+ struct ahash_req_ctx *state,
unsigned int digestsize)
{
- state->digest_result_dma_addr =
+ state->digest_result_dma_addr =
dma_map_single(dev, (void *)state->digest_result_buff,
digestsize,
DMA_BIDIRECTIONAL);
@@ -144,8 +139,6 @@ static int ssi_hash_map_result(struct device *dev,
digestsize);
return -ENOMEM;
}
- SSI_UPDATE_DMA_ADDR_TO_48BIT(state->digest_result_dma_addr,
- digestsize);
SSI_LOG_DEBUG("Mapped digest result buffer %u B "
"at va=%pK to dma=0x%llX\n",
digestsize, state->digest_result_buff,
@@ -154,33 +147,33 @@ static int ssi_hash_map_result(struct device *dev,
return 0;
}
-static int ssi_hash_map_request(struct device *dev,
- struct ahash_req_ctx *state,
+static int ssi_hash_map_request(struct device *dev,
+ struct ahash_req_ctx *state,
struct ssi_hash_ctx *ctx)
{
bool is_hmac = ctx->is_hmac;
ssi_sram_addr_t larval_digest_addr = ssi_ahash_get_larval_digest_sram_addr(
ctx->drvdata, ctx->hash_mode);
struct ssi_crypto_req ssi_req = {};
- HwDesc_s desc;
+ struct cc_hw_desc desc;
int rc = -ENOMEM;
- state->buff0 = kzalloc(SSI_MAX_HASH_BLCK_SIZE ,GFP_KERNEL|GFP_DMA);
+ state->buff0 = kzalloc(SSI_MAX_HASH_BLCK_SIZE, GFP_KERNEL | GFP_DMA);
if (!state->buff0) {
SSI_LOG_ERR("Allocating buff0 in context failed\n");
goto fail0;
}
- state->buff1 = kzalloc(SSI_MAX_HASH_BLCK_SIZE ,GFP_KERNEL|GFP_DMA);
+ state->buff1 = kzalloc(SSI_MAX_HASH_BLCK_SIZE, GFP_KERNEL | GFP_DMA);
if (!state->buff1) {
SSI_LOG_ERR("Allocating buff1 in context failed\n");
goto fail_buff0;
}
- state->digest_result_buff = kzalloc(SSI_MAX_HASH_DIGEST_SIZE ,GFP_KERNEL|GFP_DMA);
+ state->digest_result_buff = kzalloc(SSI_MAX_HASH_DIGEST_SIZE, GFP_KERNEL | GFP_DMA);
if (!state->digest_result_buff) {
SSI_LOG_ERR("Allocating digest_result_buff in context failed\n");
goto fail_buff1;
}
- state->digest_buff = kzalloc(ctx->inter_digestsize, GFP_KERNEL|GFP_DMA);
+ state->digest_buff = kzalloc(ctx->inter_digestsize, GFP_KERNEL | GFP_DMA);
if (!state->digest_buff) {
SSI_LOG_ERR("Allocating digest-buffer in context failed\n");
goto fail_digest_result_buff;
@@ -188,7 +181,7 @@ static int ssi_hash_map_request(struct device *dev,
SSI_LOG_DEBUG("Allocated digest-buffer in context ctx->digest_buff=@%p\n", state->digest_buff);
if (ctx->hw_mode != DRV_CIPHER_XCBC_MAC) {
- state->digest_bytes_len = kzalloc(HASH_LEN_SIZE, GFP_KERNEL|GFP_DMA);
+ state->digest_bytes_len = kzalloc(HASH_LEN_SIZE, GFP_KERNEL | GFP_DMA);
if (!state->digest_bytes_len) {
SSI_LOG_ERR("Allocating digest-bytes-len in context failed\n");
goto fail1;
@@ -198,7 +191,7 @@ static int ssi_hash_map_request(struct device *dev,
state->digest_bytes_len = NULL;
}
- state->opad_digest_buff = kzalloc(ctx->inter_digestsize, GFP_KERNEL|GFP_DMA);
+ state->opad_digest_buff = kzalloc(ctx->inter_digestsize, GFP_KERNEL | GFP_DMA);
if (!state->opad_digest_buff) {
SSI_LOG_ERR("Allocating opad-digest-buffer in context failed\n");
goto fail2;
@@ -211,50 +204,40 @@ static int ssi_hash_map_request(struct device *dev,
ctx->inter_digestsize, state->digest_buff);
goto fail3;
}
- SSI_UPDATE_DMA_ADDR_TO_48BIT(state->digest_buff_dma_addr,
- ctx->inter_digestsize);
SSI_LOG_DEBUG("Mapped digest %d B at va=%pK to dma=0x%llX\n",
ctx->inter_digestsize, state->digest_buff,
(unsigned long long)state->digest_buff_dma_addr);
if (is_hmac) {
- SSI_RESTORE_DMA_ADDR_TO_48BIT(ctx->digest_buff_dma_addr);
dma_sync_single_for_cpu(dev, ctx->digest_buff_dma_addr, ctx->inter_digestsize, DMA_BIDIRECTIONAL);
- SSI_UPDATE_DMA_ADDR_TO_48BIT(ctx->digest_buff_dma_addr,
- ctx->inter_digestsize);
if ((ctx->hw_mode == DRV_CIPHER_XCBC_MAC) || (ctx->hw_mode == DRV_CIPHER_CMAC)) {
memset(state->digest_buff, 0, ctx->inter_digestsize);
} else { /*sha*/
memcpy(state->digest_buff, ctx->digest_buff, ctx->inter_digestsize);
#if (DX_DEV_SHA_MAX > 256)
- if (unlikely((ctx->hash_mode == DRV_HASH_SHA512) || (ctx->hash_mode == DRV_HASH_SHA384))) {
+ if (unlikely((ctx->hash_mode == DRV_HASH_SHA512) || (ctx->hash_mode == DRV_HASH_SHA384)))
memcpy(state->digest_bytes_len, digest_len_sha512_init, HASH_LEN_SIZE);
- } else {
+ else
memcpy(state->digest_bytes_len, digest_len_init, HASH_LEN_SIZE);
- }
#else
memcpy(state->digest_bytes_len, digest_len_init, HASH_LEN_SIZE);
#endif
}
- SSI_RESTORE_DMA_ADDR_TO_48BIT(state->digest_buff_dma_addr);
dma_sync_single_for_device(dev, state->digest_buff_dma_addr, ctx->inter_digestsize, DMA_BIDIRECTIONAL);
- SSI_UPDATE_DMA_ADDR_TO_48BIT(state->digest_buff_dma_addr,
- ctx->inter_digestsize);
if (ctx->hash_mode != DRV_HASH_NULL) {
- SSI_RESTORE_DMA_ADDR_TO_48BIT(ctx->opad_tmp_keys_dma_addr);
dma_sync_single_for_cpu(dev, ctx->opad_tmp_keys_dma_addr, ctx->inter_digestsize, DMA_BIDIRECTIONAL);
memcpy(state->opad_digest_buff, ctx->opad_tmp_keys_buff, ctx->inter_digestsize);
- SSI_UPDATE_DMA_ADDR_TO_48BIT(ctx->opad_tmp_keys_dma_addr,
- ctx->inter_digestsize);
- }
+ }
} else { /*hash*/
/* Copy the initial digests if hash flow. The SRAM contains the
- initial digests in the expected order for all SHA* */
- HW_DESC_INIT(&desc);
- HW_DESC_SET_DIN_SRAM(&desc, larval_digest_addr, ctx->inter_digestsize);
- HW_DESC_SET_DOUT_DLLI(&desc, state->digest_buff_dma_addr, ctx->inter_digestsize, NS_BIT, 0);
- HW_DESC_SET_FLOW_MODE(&desc, BYPASS);
+ * initial digests in the expected order for all SHA*
+ */
+ hw_desc_init(&desc);
+ set_din_sram(&desc, larval_digest_addr, ctx->inter_digestsize);
+ set_dout_dlli(&desc, state->digest_buff_dma_addr,
+ ctx->inter_digestsize, NS_BIT, 0);
+ set_flow_mode(&desc, BYPASS);
rc = send_request(ctx->drvdata, &ssi_req, &desc, 1, 0);
if (unlikely(rc != 0)) {
@@ -270,8 +253,6 @@ static int ssi_hash_map_request(struct device *dev,
HASH_LEN_SIZE, state->digest_bytes_len);
goto fail4;
}
- SSI_UPDATE_DMA_ADDR_TO_48BIT(state->digest_bytes_len_dma_addr,
- HASH_LEN_SIZE);
SSI_LOG_DEBUG("Mapped digest len %u B at va=%pK to dma=0x%llX\n",
HASH_LEN_SIZE, state->digest_bytes_len,
(unsigned long long)state->digest_bytes_len_dma_addr);
@@ -286,8 +267,6 @@ static int ssi_hash_map_request(struct device *dev,
ctx->inter_digestsize, state->opad_digest_buff);
goto fail5;
}
- SSI_UPDATE_DMA_ADDR_TO_48BIT(state->opad_digest_dma_addr,
- ctx->inter_digestsize);
SSI_LOG_DEBUG("Mapped opad digest %d B at va=%pK to dma=0x%llX\n",
ctx->inter_digestsize, state->opad_digest_buff,
(unsigned long long)state->opad_digest_dma_addr);
@@ -303,13 +282,11 @@ static int ssi_hash_map_request(struct device *dev,
fail5:
if (state->digest_bytes_len_dma_addr != 0) {
- SSI_RESTORE_DMA_ADDR_TO_48BIT(state->digest_bytes_len_dma_addr);
dma_unmap_single(dev, state->digest_bytes_len_dma_addr, HASH_LEN_SIZE, DMA_BIDIRECTIONAL);
state->digest_bytes_len_dma_addr = 0;
}
fail4:
if (state->digest_buff_dma_addr != 0) {
- SSI_RESTORE_DMA_ADDR_TO_48BIT(state->digest_buff_dma_addr);
dma_unmap_single(dev, state->digest_buff_dma_addr, ctx->inter_digestsize, DMA_BIDIRECTIONAL);
state->digest_buff_dma_addr = 0;
}
@@ -320,17 +297,17 @@ fail2:
fail1:
kfree(state->digest_buff);
fail_digest_result_buff:
- if (state->digest_result_buff != NULL) {
+ if (state->digest_result_buff) {
kfree(state->digest_result_buff);
state->digest_result_buff = NULL;
}
fail_buff1:
- if (state->buff1 != NULL) {
+ if (state->buff1) {
kfree(state->buff1);
state->buff1 = NULL;
}
fail_buff0:
- if (state->buff0 != NULL) {
+ if (state->buff0) {
kfree(state->buff0);
state->buff0 = NULL;
}
@@ -338,12 +315,11 @@ fail0:
return rc;
}
-static void ssi_hash_unmap_request(struct device *dev,
- struct ahash_req_ctx *state,
+static void ssi_hash_unmap_request(struct device *dev,
+ struct ahash_req_ctx *state,
struct ssi_hash_ctx *ctx)
{
if (state->digest_buff_dma_addr != 0) {
- SSI_RESTORE_DMA_ADDR_TO_48BIT(state->digest_buff_dma_addr);
dma_unmap_single(dev, state->digest_buff_dma_addr,
ctx->inter_digestsize, DMA_BIDIRECTIONAL);
SSI_LOG_DEBUG("Unmapped digest-buffer: digest_buff_dma_addr=0x%llX\n",
@@ -351,7 +327,6 @@ static void ssi_hash_unmap_request(struct device *dev,
state->digest_buff_dma_addr = 0;
}
if (state->digest_bytes_len_dma_addr != 0) {
- SSI_RESTORE_DMA_ADDR_TO_48BIT(state->digest_bytes_len_dma_addr);
dma_unmap_single(dev, state->digest_bytes_len_dma_addr,
HASH_LEN_SIZE, DMA_BIDIRECTIONAL);
SSI_LOG_DEBUG("Unmapped digest-bytes-len buffer: digest_bytes_len_dma_addr=0x%llX\n",
@@ -359,7 +334,6 @@ static void ssi_hash_unmap_request(struct device *dev,
state->digest_bytes_len_dma_addr = 0;
}
if (state->opad_digest_dma_addr != 0) {
- SSI_RESTORE_DMA_ADDR_TO_48BIT(state->opad_digest_dma_addr);
dma_unmap_single(dev, state->opad_digest_dma_addr,
ctx->inter_digestsize, DMA_BIDIRECTIONAL);
SSI_LOG_DEBUG("Unmapped opad-digest: opad_digest_dma_addr=0x%llX\n",
@@ -375,19 +349,18 @@ static void ssi_hash_unmap_request(struct device *dev,
kfree(state->buff0);
}
-static void ssi_hash_unmap_result(struct device *dev,
- struct ahash_req_ctx *state,
+static void ssi_hash_unmap_result(struct device *dev,
+ struct ahash_req_ctx *state,
unsigned int digestsize, u8 *result)
{
if (state->digest_result_dma_addr != 0) {
- SSI_RESTORE_DMA_ADDR_TO_48BIT(state->digest_result_dma_addr);
dma_unmap_single(dev,
state->digest_result_dma_addr,
digestsize,
- DMA_BIDIRECTIONAL);
+ DMA_BIDIRECTIONAL);
SSI_LOG_DEBUG("unmpa digest result buffer "
"va (%pK) pa (%llx) len %u\n",
- state->digest_result_buff,
+ state->digest_result_buff,
(unsigned long long)state->digest_result_dma_addr,
digestsize);
memcpy(result,
@@ -414,8 +387,8 @@ static void ssi_hash_digest_complete(struct device *dev, void *ssi_req, void __i
struct ahash_req_ctx *state = ahash_request_ctx(req);
struct crypto_ahash *tfm = crypto_ahash_reqtfm(req);
struct ssi_hash_ctx *ctx = crypto_ahash_ctx(tfm);
- uint32_t digestsize = crypto_ahash_digestsize(tfm);
-
+ u32 digestsize = crypto_ahash_digestsize(tfm);
+
SSI_LOG_DEBUG("req=%pK\n", req);
ssi_buffer_mgr_unmap_hash_request(dev, state, req->src, false);
@@ -430,8 +403,8 @@ static void ssi_hash_complete(struct device *dev, void *ssi_req, void __iomem *c
struct ahash_req_ctx *state = ahash_request_ctx(req);
struct crypto_ahash *tfm = crypto_ahash_reqtfm(req);
struct ssi_hash_ctx *ctx = crypto_ahash_ctx(tfm);
- uint32_t digestsize = crypto_ahash_digestsize(tfm);
-
+ u32 digestsize = crypto_ahash_digestsize(tfm);
+
SSI_LOG_DEBUG("req=%pK\n", req);
ssi_buffer_mgr_unmap_hash_request(dev, state, req->src, false);
@@ -440,24 +413,23 @@ static void ssi_hash_complete(struct device *dev, void *ssi_req, void __iomem *c
req->base.complete(&req->base, 0);
}
-static int ssi_hash_digest(struct ahash_req_ctx *state,
- struct ssi_hash_ctx *ctx,
- unsigned int digestsize,
- struct scatterlist *src,
- unsigned int nbytes, u8 *result,
+static int ssi_hash_digest(struct ahash_req_ctx *state,
+ struct ssi_hash_ctx *ctx,
+ unsigned int digestsize,
+ struct scatterlist *src,
+ unsigned int nbytes, u8 *result,
void *async_req)
{
struct device *dev = &ctx->drvdata->plat_dev->dev;
bool is_hmac = ctx->is_hmac;
struct ssi_crypto_req ssi_req = {};
- HwDesc_s desc[SSI_MAX_AHASH_SEQ_LEN];
+ struct cc_hw_desc desc[SSI_MAX_AHASH_SEQ_LEN];
ssi_sram_addr_t larval_digest_addr = ssi_ahash_get_larval_digest_sram_addr(
ctx->drvdata, ctx->hash_mode);
int idx = 0;
int rc = 0;
-
- SSI_LOG_DEBUG("===== %s-digest (%d) ====\n", is_hmac?"hmac":"hash", nbytes);
+ SSI_LOG_DEBUG("===== %s-digest (%d) ====\n", is_hmac ? "hmac" : "hash", nbytes);
CHECK_AND_RETURN_UPON_FIPS_ERROR();
@@ -480,102 +452,109 @@ static int ssi_hash_digest(struct ahash_req_ctx *state,
/* Setup DX request structure */
ssi_req.user_cb = (void *)ssi_hash_digest_complete;
ssi_req.user_arg = (void *)async_req;
-#ifdef ENABLE_CYCLE_COUNT
- ssi_req.op_type = STAT_OP_TYPE_ENCODE; /* Use "Encode" stats */
-#endif
}
/* If HMAC then load hash IPAD xor key, if HASH then load initial digest */
- HW_DESC_INIT(&desc[idx]);
- HW_DESC_SET_CIPHER_MODE(&desc[idx], ctx->hw_mode);
+ hw_desc_init(&desc[idx]);
+ set_cipher_mode(&desc[idx], ctx->hw_mode);
if (is_hmac) {
- HW_DESC_SET_DIN_TYPE(&desc[idx], DMA_DLLI, state->digest_buff_dma_addr, ctx->inter_digestsize, NS_BIT);
+ set_din_type(&desc[idx], DMA_DLLI, state->digest_buff_dma_addr,
+ ctx->inter_digestsize, NS_BIT);
} else {
- HW_DESC_SET_DIN_SRAM(&desc[idx], larval_digest_addr, ctx->inter_digestsize);
+ set_din_sram(&desc[idx], larval_digest_addr,
+ ctx->inter_digestsize);
}
- HW_DESC_SET_FLOW_MODE(&desc[idx], S_DIN_to_HASH);
- HW_DESC_SET_SETUP_MODE(&desc[idx], SETUP_LOAD_STATE0);
+ set_flow_mode(&desc[idx], S_DIN_to_HASH);
+ set_setup_mode(&desc[idx], SETUP_LOAD_STATE0);
idx++;
/* Load the hash current length */
- HW_DESC_INIT(&desc[idx]);
- HW_DESC_SET_CIPHER_MODE(&desc[idx], ctx->hw_mode);
+ hw_desc_init(&desc[idx]);
+ set_cipher_mode(&desc[idx], ctx->hw_mode);
if (is_hmac) {
- HW_DESC_SET_DIN_TYPE(&desc[idx], DMA_DLLI, state->digest_bytes_len_dma_addr, HASH_LEN_SIZE, NS_BIT);
+ set_din_type(&desc[idx], DMA_DLLI,
+ state->digest_bytes_len_dma_addr, HASH_LEN_SIZE,
+ NS_BIT);
} else {
- HW_DESC_SET_DIN_CONST(&desc[idx], 0, HASH_LEN_SIZE);
- if (likely(nbytes != 0)) {
- HW_DESC_SET_CIPHER_CONFIG1(&desc[idx], HASH_PADDING_ENABLED);
- } else {
- HW_DESC_SET_CIPHER_DO(&desc[idx], DO_PAD);
- }
- }
- HW_DESC_SET_FLOW_MODE(&desc[idx], S_DIN_to_HASH);
- HW_DESC_SET_SETUP_MODE(&desc[idx], SETUP_LOAD_KEY0);
+ set_din_const(&desc[idx], 0, HASH_LEN_SIZE);
+ if (likely(nbytes != 0))
+ set_cipher_config1(&desc[idx], HASH_PADDING_ENABLED);
+ else
+ set_cipher_do(&desc[idx], DO_PAD);
+ }
+ set_flow_mode(&desc[idx], S_DIN_to_HASH);
+ set_setup_mode(&desc[idx], SETUP_LOAD_KEY0);
idx++;
ssi_hash_create_data_desc(state, ctx, DIN_HASH, desc, false, &idx);
if (is_hmac) {
/* HW last hash block padding (aka. "DO_PAD") */
- HW_DESC_INIT(&desc[idx]);
- HW_DESC_SET_CIPHER_MODE(&desc[idx], ctx->hw_mode);
- HW_DESC_SET_DOUT_DLLI(&desc[idx], state->digest_buff_dma_addr, HASH_LEN_SIZE, NS_BIT, 0);
- HW_DESC_SET_FLOW_MODE(&desc[idx], S_HASH_to_DOUT);
- HW_DESC_SET_SETUP_MODE(&desc[idx], SETUP_WRITE_STATE1);
- HW_DESC_SET_CIPHER_DO(&desc[idx], DO_PAD);
+ hw_desc_init(&desc[idx]);
+ set_cipher_mode(&desc[idx], ctx->hw_mode);
+ set_dout_dlli(&desc[idx], state->digest_buff_dma_addr,
+ HASH_LEN_SIZE, NS_BIT, 0);
+ set_flow_mode(&desc[idx], S_HASH_to_DOUT);
+ set_setup_mode(&desc[idx], SETUP_WRITE_STATE1);
+ set_cipher_do(&desc[idx], DO_PAD);
idx++;
/* store the hash digest result in the context */
- HW_DESC_INIT(&desc[idx]);
- HW_DESC_SET_CIPHER_MODE(&desc[idx], ctx->hw_mode);
- HW_DESC_SET_DOUT_DLLI(&desc[idx], state->digest_buff_dma_addr, digestsize, NS_BIT, 0);
- HW_DESC_SET_FLOW_MODE(&desc[idx], S_HASH_to_DOUT);
+ hw_desc_init(&desc[idx]);
+ set_cipher_mode(&desc[idx], ctx->hw_mode);
+ set_dout_dlli(&desc[idx], state->digest_buff_dma_addr,
+ digestsize, NS_BIT, 0);
+ set_flow_mode(&desc[idx], S_HASH_to_DOUT);
ssi_set_hash_endianity(ctx->hash_mode, &desc[idx]);
- HW_DESC_SET_SETUP_MODE(&desc[idx], SETUP_WRITE_STATE0);
+ set_setup_mode(&desc[idx], SETUP_WRITE_STATE0);
idx++;
/* Loading hash opad xor key state */
- HW_DESC_INIT(&desc[idx]);
- HW_DESC_SET_CIPHER_MODE(&desc[idx], ctx->hw_mode);
- HW_DESC_SET_DIN_TYPE(&desc[idx], DMA_DLLI, state->opad_digest_dma_addr, ctx->inter_digestsize, NS_BIT);
- HW_DESC_SET_FLOW_MODE(&desc[idx], S_DIN_to_HASH);
- HW_DESC_SET_SETUP_MODE(&desc[idx], SETUP_LOAD_STATE0);
+ hw_desc_init(&desc[idx]);
+ set_cipher_mode(&desc[idx], ctx->hw_mode);
+ set_din_type(&desc[idx], DMA_DLLI, state->opad_digest_dma_addr,
+ ctx->inter_digestsize, NS_BIT);
+ set_flow_mode(&desc[idx], S_DIN_to_HASH);
+ set_setup_mode(&desc[idx], SETUP_LOAD_STATE0);
idx++;
/* Load the hash current length */
- HW_DESC_INIT(&desc[idx]);
- HW_DESC_SET_CIPHER_MODE(&desc[idx], ctx->hw_mode);
- HW_DESC_SET_DIN_SRAM(&desc[idx], ssi_ahash_get_initial_digest_len_sram_addr(ctx->drvdata, ctx->hash_mode), HASH_LEN_SIZE);
- HW_DESC_SET_CIPHER_CONFIG1(&desc[idx], HASH_PADDING_ENABLED);
- HW_DESC_SET_FLOW_MODE(&desc[idx], S_DIN_to_HASH);
- HW_DESC_SET_SETUP_MODE(&desc[idx], SETUP_LOAD_KEY0);
+ hw_desc_init(&desc[idx]);
+ set_cipher_mode(&desc[idx], ctx->hw_mode);
+ set_din_sram(&desc[idx],
+ ssi_ahash_get_initial_digest_len_sram_addr(
+ctx->drvdata, ctx->hash_mode), HASH_LEN_SIZE);
+ set_cipher_config1(&desc[idx], HASH_PADDING_ENABLED);
+ set_flow_mode(&desc[idx], S_DIN_to_HASH);
+ set_setup_mode(&desc[idx], SETUP_LOAD_KEY0);
idx++;
/* Memory Barrier: wait for IPAD/OPAD axi write to complete */
- HW_DESC_INIT(&desc[idx]);
- HW_DESC_SET_DIN_NO_DMA(&desc[idx], 0, 0xfffff0);
- HW_DESC_SET_DOUT_NO_DMA(&desc[idx], 0, 0, 1);
+ hw_desc_init(&desc[idx]);
+ set_din_no_dma(&desc[idx], 0, 0xfffff0);
+ set_dout_no_dma(&desc[idx], 0, 0, 1);
idx++;
/* Perform HASH update */
- HW_DESC_INIT(&desc[idx]);
- HW_DESC_SET_DIN_TYPE(&desc[idx], DMA_DLLI, state->digest_buff_dma_addr, digestsize, NS_BIT);
- HW_DESC_SET_FLOW_MODE(&desc[idx], DIN_HASH);
+ hw_desc_init(&desc[idx]);
+ set_din_type(&desc[idx], DMA_DLLI, state->digest_buff_dma_addr,
+ digestsize, NS_BIT);
+ set_flow_mode(&desc[idx], DIN_HASH);
idx++;
}
/* Get final MAC result */
- HW_DESC_INIT(&desc[idx]);
- HW_DESC_SET_CIPHER_MODE(&desc[idx], ctx->hw_mode);
- HW_DESC_SET_DOUT_DLLI(&desc[idx], state->digest_result_dma_addr, digestsize, NS_BIT, async_req? 1:0); /*TODO*/
- if (async_req) {
- HW_DESC_SET_QUEUE_LAST_IND(&desc[idx]);
- }
- HW_DESC_SET_FLOW_MODE(&desc[idx], S_HASH_to_DOUT);
- HW_DESC_SET_SETUP_MODE(&desc[idx], SETUP_WRITE_STATE0);
- HW_DESC_SET_CIPHER_CONFIG1(&desc[idx], HASH_PADDING_DISABLED);
+ hw_desc_init(&desc[idx]);
+ set_cipher_mode(&desc[idx], ctx->hw_mode);
+ /* TODO */
+ set_dout_dlli(&desc[idx], state->digest_result_dma_addr, digestsize,
+ NS_BIT, (async_req ? 1 : 0));
+ if (async_req)
+ set_queue_last_ind(&desc[idx]);
+ set_flow_mode(&desc[idx], S_HASH_to_DOUT);
+ set_setup_mode(&desc[idx], SETUP_WRITE_STATE0);
+ set_cipher_config1(&desc[idx], HASH_PADDING_DISABLED);
ssi_set_hash_endianity(ctx->hash_mode, &desc[idx]);
idx++;
@@ -593,7 +572,7 @@ static int ssi_hash_digest(struct ahash_req_ctx *state,
SSI_LOG_ERR("send_request() failed (rc=%d)\n", rc);
ssi_buffer_mgr_unmap_hash_request(dev, state, src, true);
} else {
- ssi_buffer_mgr_unmap_hash_request(dev, state, src, false);
+ ssi_buffer_mgr_unmap_hash_request(dev, state, src, false);
}
ssi_hash_unmap_result(dev, state, digestsize, result);
ssi_hash_unmap_request(dev, state, ctx);
@@ -601,21 +580,21 @@ static int ssi_hash_digest(struct ahash_req_ctx *state,
return rc;
}
-static int ssi_hash_update(struct ahash_req_ctx *state,
- struct ssi_hash_ctx *ctx,
- unsigned int block_size,
- struct scatterlist *src,
- unsigned int nbytes,
+static int ssi_hash_update(struct ahash_req_ctx *state,
+ struct ssi_hash_ctx *ctx,
+ unsigned int block_size,
+ struct scatterlist *src,
+ unsigned int nbytes,
void *async_req)
{
struct device *dev = &ctx->drvdata->plat_dev->dev;
struct ssi_crypto_req ssi_req = {};
- HwDesc_s desc[SSI_MAX_AHASH_SEQ_LEN];
- uint32_t idx = 0;
+ struct cc_hw_desc desc[SSI_MAX_AHASH_SEQ_LEN];
+ u32 idx = 0;
int rc;
SSI_LOG_DEBUG("===== %s-update (%d) ====\n", ctx->is_hmac ?
- "hmac":"hash", nbytes);
+ "hmac" : "hash", nbytes);
CHECK_AND_RETURN_UPON_FIPS_ERROR();
if (nbytes == 0) {
@@ -638,45 +617,45 @@ static int ssi_hash_update(struct ahash_req_ctx *state,
/* Setup DX request structure */
ssi_req.user_cb = (void *)ssi_hash_update_complete;
ssi_req.user_arg = async_req;
-#ifdef ENABLE_CYCLE_COUNT
- ssi_req.op_type = STAT_OP_TYPE_ENCODE; /* Use "Encode" stats */
-#endif
}
/* Restore hash digest */
- HW_DESC_INIT(&desc[idx]);
- HW_DESC_SET_CIPHER_MODE(&desc[idx], ctx->hw_mode);
- HW_DESC_SET_DIN_TYPE(&desc[idx], DMA_DLLI, state->digest_buff_dma_addr, ctx->inter_digestsize, NS_BIT);
- HW_DESC_SET_FLOW_MODE(&desc[idx], S_DIN_to_HASH);
- HW_DESC_SET_SETUP_MODE(&desc[idx], SETUP_LOAD_STATE0);
+ hw_desc_init(&desc[idx]);
+ set_cipher_mode(&desc[idx], ctx->hw_mode);
+ set_din_type(&desc[idx], DMA_DLLI, state->digest_buff_dma_addr,
+ ctx->inter_digestsize, NS_BIT);
+ set_flow_mode(&desc[idx], S_DIN_to_HASH);
+ set_setup_mode(&desc[idx], SETUP_LOAD_STATE0);
idx++;
/* Restore hash current length */
- HW_DESC_INIT(&desc[idx]);
- HW_DESC_SET_CIPHER_MODE(&desc[idx], ctx->hw_mode);
- HW_DESC_SET_DIN_TYPE(&desc[idx], DMA_DLLI, state->digest_bytes_len_dma_addr, HASH_LEN_SIZE, NS_BIT);
- HW_DESC_SET_FLOW_MODE(&desc[idx], S_DIN_to_HASH);
- HW_DESC_SET_SETUP_MODE(&desc[idx], SETUP_LOAD_KEY0);
+ hw_desc_init(&desc[idx]);
+ set_cipher_mode(&desc[idx], ctx->hw_mode);
+ set_din_type(&desc[idx], DMA_DLLI, state->digest_bytes_len_dma_addr,
+ HASH_LEN_SIZE, NS_BIT);
+ set_flow_mode(&desc[idx], S_DIN_to_HASH);
+ set_setup_mode(&desc[idx], SETUP_LOAD_KEY0);
idx++;
ssi_hash_create_data_desc(state, ctx, DIN_HASH, desc, false, &idx);
/* store the hash digest result in context */
- HW_DESC_INIT(&desc[idx]);
- HW_DESC_SET_CIPHER_MODE(&desc[idx], ctx->hw_mode);
- HW_DESC_SET_DOUT_DLLI(&desc[idx], state->digest_buff_dma_addr, ctx->inter_digestsize, NS_BIT, 0);
- HW_DESC_SET_FLOW_MODE(&desc[idx], S_HASH_to_DOUT);
- HW_DESC_SET_SETUP_MODE(&desc[idx], SETUP_WRITE_STATE0);
+ hw_desc_init(&desc[idx]);
+ set_cipher_mode(&desc[idx], ctx->hw_mode);
+ set_dout_dlli(&desc[idx], state->digest_buff_dma_addr,
+ ctx->inter_digestsize, NS_BIT, 0);
+ set_flow_mode(&desc[idx], S_HASH_to_DOUT);
+ set_setup_mode(&desc[idx], SETUP_WRITE_STATE0);
idx++;
/* store current hash length in context */
- HW_DESC_INIT(&desc[idx]);
- HW_DESC_SET_CIPHER_MODE(&desc[idx], ctx->hw_mode);
- HW_DESC_SET_DOUT_DLLI(&desc[idx], state->digest_bytes_len_dma_addr, HASH_LEN_SIZE, NS_BIT, async_req? 1:0);
- if (async_req) {
- HW_DESC_SET_QUEUE_LAST_IND(&desc[idx]);
- }
- HW_DESC_SET_FLOW_MODE(&desc[idx], S_HASH_to_DOUT);
- HW_DESC_SET_SETUP_MODE(&desc[idx], SETUP_WRITE_STATE1);
+ hw_desc_init(&desc[idx]);
+ set_cipher_mode(&desc[idx], ctx->hw_mode);
+ set_dout_dlli(&desc[idx], state->digest_bytes_len_dma_addr,
+ HASH_LEN_SIZE, NS_BIT, (async_req ? 1 : 0));
+ if (async_req)
+ set_queue_last_ind(&desc[idx]);
+ set_flow_mode(&desc[idx], S_HASH_to_DOUT);
+ set_setup_mode(&desc[idx], SETUP_WRITE_STATE1);
idx++;
if (async_req) {
@@ -697,26 +676,26 @@ static int ssi_hash_update(struct ahash_req_ctx *state,
return rc;
}
-static int ssi_hash_finup(struct ahash_req_ctx *state,
- struct ssi_hash_ctx *ctx,
- unsigned int digestsize,
- struct scatterlist *src,
- unsigned int nbytes,
- u8 *result,
+static int ssi_hash_finup(struct ahash_req_ctx *state,
+ struct ssi_hash_ctx *ctx,
+ unsigned int digestsize,
+ struct scatterlist *src,
+ unsigned int nbytes,
+ u8 *result,
void *async_req)
{
struct device *dev = &ctx->drvdata->plat_dev->dev;
bool is_hmac = ctx->is_hmac;
struct ssi_crypto_req ssi_req = {};
- HwDesc_s desc[SSI_MAX_AHASH_SEQ_LEN];
+ struct cc_hw_desc desc[SSI_MAX_AHASH_SEQ_LEN];
int idx = 0;
int rc;
- SSI_LOG_DEBUG("===== %s-finup (%d) ====\n", is_hmac?"hmac":"hash", nbytes);
+ SSI_LOG_DEBUG("===== %s-finup (%d) ====\n", is_hmac ? "hmac" : "hash", nbytes);
CHECK_AND_RETURN_UPON_FIPS_ERROR();
- if (unlikely(ssi_buffer_mgr_map_hash_request_final(ctx->drvdata, state, src , nbytes, 1) != 0)) {
+ if (unlikely(ssi_buffer_mgr_map_hash_request_final(ctx->drvdata, state, src, nbytes, 1) != 0)) {
SSI_LOG_ERR("map_ahash_request_final() failed\n");
return -ENOMEM;
}
@@ -729,81 +708,86 @@ static int ssi_hash_finup(struct ahash_req_ctx *state,
/* Setup DX request structure */
ssi_req.user_cb = (void *)ssi_hash_complete;
ssi_req.user_arg = async_req;
-#ifdef ENABLE_CYCLE_COUNT
- ssi_req.op_type = STAT_OP_TYPE_ENCODE; /* Use "Encode" stats */
-#endif
}
/* Restore hash digest */
- HW_DESC_INIT(&desc[idx]);
- HW_DESC_SET_CIPHER_MODE(&desc[idx], ctx->hw_mode);
- HW_DESC_SET_DIN_TYPE(&desc[idx], DMA_DLLI, state->digest_buff_dma_addr, ctx->inter_digestsize, NS_BIT);
- HW_DESC_SET_FLOW_MODE(&desc[idx], S_DIN_to_HASH);
- HW_DESC_SET_SETUP_MODE(&desc[idx], SETUP_LOAD_STATE0);
+ hw_desc_init(&desc[idx]);
+ set_cipher_mode(&desc[idx], ctx->hw_mode);
+ set_din_type(&desc[idx], DMA_DLLI, state->digest_buff_dma_addr,
+ ctx->inter_digestsize, NS_BIT);
+ set_flow_mode(&desc[idx], S_DIN_to_HASH);
+ set_setup_mode(&desc[idx], SETUP_LOAD_STATE0);
idx++;
/* Restore hash current length */
- HW_DESC_INIT(&desc[idx]);
- HW_DESC_SET_CIPHER_MODE(&desc[idx], ctx->hw_mode);
- HW_DESC_SET_CIPHER_CONFIG1(&desc[idx], HASH_PADDING_ENABLED);
- HW_DESC_SET_DIN_TYPE(&desc[idx], DMA_DLLI, state->digest_bytes_len_dma_addr, HASH_LEN_SIZE, NS_BIT);
- HW_DESC_SET_FLOW_MODE(&desc[idx], S_DIN_to_HASH);
- HW_DESC_SET_SETUP_MODE(&desc[idx], SETUP_LOAD_KEY0);
+ hw_desc_init(&desc[idx]);
+ set_cipher_mode(&desc[idx], ctx->hw_mode);
+ set_cipher_config1(&desc[idx], HASH_PADDING_ENABLED);
+ set_din_type(&desc[idx], DMA_DLLI, state->digest_bytes_len_dma_addr,
+ HASH_LEN_SIZE, NS_BIT);
+ set_flow_mode(&desc[idx], S_DIN_to_HASH);
+ set_setup_mode(&desc[idx], SETUP_LOAD_KEY0);
idx++;
ssi_hash_create_data_desc(state, ctx, DIN_HASH, desc, false, &idx);
if (is_hmac) {
/* Store the hash digest result in the context */
- HW_DESC_INIT(&desc[idx]);
- HW_DESC_SET_CIPHER_MODE(&desc[idx], ctx->hw_mode);
- HW_DESC_SET_DOUT_DLLI(&desc[idx], state->digest_buff_dma_addr, digestsize, NS_BIT, 0);
- ssi_set_hash_endianity(ctx->hash_mode,&desc[idx]);
- HW_DESC_SET_FLOW_MODE(&desc[idx], S_HASH_to_DOUT);
- HW_DESC_SET_SETUP_MODE(&desc[idx], SETUP_WRITE_STATE0);
+ hw_desc_init(&desc[idx]);
+ set_cipher_mode(&desc[idx], ctx->hw_mode);
+ set_dout_dlli(&desc[idx], state->digest_buff_dma_addr,
+ digestsize, NS_BIT, 0);
+ ssi_set_hash_endianity(ctx->hash_mode, &desc[idx]);
+ set_flow_mode(&desc[idx], S_HASH_to_DOUT);
+ set_setup_mode(&desc[idx], SETUP_WRITE_STATE0);
idx++;
/* Loading hash OPAD xor key state */
- HW_DESC_INIT(&desc[idx]);
- HW_DESC_SET_CIPHER_MODE(&desc[idx], ctx->hw_mode);
- HW_DESC_SET_DIN_TYPE(&desc[idx], DMA_DLLI, state->opad_digest_dma_addr, ctx->inter_digestsize, NS_BIT);
- HW_DESC_SET_FLOW_MODE(&desc[idx], S_DIN_to_HASH);
- HW_DESC_SET_SETUP_MODE(&desc[idx], SETUP_LOAD_STATE0);
+ hw_desc_init(&desc[idx]);
+ set_cipher_mode(&desc[idx], ctx->hw_mode);
+ set_din_type(&desc[idx], DMA_DLLI, state->opad_digest_dma_addr,
+ ctx->inter_digestsize, NS_BIT);
+ set_flow_mode(&desc[idx], S_DIN_to_HASH);
+ set_setup_mode(&desc[idx], SETUP_LOAD_STATE0);
idx++;
/* Load the hash current length */
- HW_DESC_INIT(&desc[idx]);
- HW_DESC_SET_CIPHER_MODE(&desc[idx], ctx->hw_mode);
- HW_DESC_SET_DIN_SRAM(&desc[idx], ssi_ahash_get_initial_digest_len_sram_addr(ctx->drvdata, ctx->hash_mode), HASH_LEN_SIZE);
- HW_DESC_SET_CIPHER_CONFIG1(&desc[idx], HASH_PADDING_ENABLED);
- HW_DESC_SET_FLOW_MODE(&desc[idx], S_DIN_to_HASH);
- HW_DESC_SET_SETUP_MODE(&desc[idx], SETUP_LOAD_KEY0);
+ hw_desc_init(&desc[idx]);
+ set_cipher_mode(&desc[idx], ctx->hw_mode);
+ set_din_sram(&desc[idx],
+ ssi_ahash_get_initial_digest_len_sram_addr(
+ctx->drvdata, ctx->hash_mode), HASH_LEN_SIZE);
+ set_cipher_config1(&desc[idx], HASH_PADDING_ENABLED);
+ set_flow_mode(&desc[idx], S_DIN_to_HASH);
+ set_setup_mode(&desc[idx], SETUP_LOAD_KEY0);
idx++;
/* Memory Barrier: wait for IPAD/OPAD axi write to complete */
- HW_DESC_INIT(&desc[idx]);
- HW_DESC_SET_DIN_NO_DMA(&desc[idx], 0, 0xfffff0);
- HW_DESC_SET_DOUT_NO_DMA(&desc[idx], 0, 0, 1);
+ hw_desc_init(&desc[idx]);
+ set_din_no_dma(&desc[idx], 0, 0xfffff0);
+ set_dout_no_dma(&desc[idx], 0, 0, 1);
idx++;
/* Perform HASH update on last digest */
- HW_DESC_INIT(&desc[idx]);
- HW_DESC_SET_DIN_TYPE(&desc[idx], DMA_DLLI, state->digest_buff_dma_addr, digestsize, NS_BIT);
- HW_DESC_SET_FLOW_MODE(&desc[idx], DIN_HASH);
+ hw_desc_init(&desc[idx]);
+ set_din_type(&desc[idx], DMA_DLLI, state->digest_buff_dma_addr,
+ digestsize, NS_BIT);
+ set_flow_mode(&desc[idx], DIN_HASH);
idx++;
}
/* Get final MAC result */
- HW_DESC_INIT(&desc[idx]);
- HW_DESC_SET_DOUT_DLLI(&desc[idx], state->digest_result_dma_addr, digestsize, NS_BIT, async_req? 1:0); /*TODO*/
- if (async_req) {
- HW_DESC_SET_QUEUE_LAST_IND(&desc[idx]);
- }
- HW_DESC_SET_FLOW_MODE(&desc[idx], S_HASH_to_DOUT);
- HW_DESC_SET_CIPHER_CONFIG1(&desc[idx], HASH_PADDING_DISABLED);
- HW_DESC_SET_SETUP_MODE(&desc[idx], SETUP_WRITE_STATE0);
- ssi_set_hash_endianity(ctx->hash_mode,&desc[idx]);
- HW_DESC_SET_CIPHER_MODE(&desc[idx], ctx->hw_mode);
+ hw_desc_init(&desc[idx]);
+ /* TODO */
+ set_dout_dlli(&desc[idx], state->digest_result_dma_addr, digestsize,
+ NS_BIT, (async_req ? 1 : 0));
+ if (async_req)
+ set_queue_last_ind(&desc[idx]);
+ set_flow_mode(&desc[idx], S_HASH_to_DOUT);
+ set_cipher_config1(&desc[idx], HASH_PADDING_DISABLED);
+ set_setup_mode(&desc[idx], SETUP_WRITE_STATE0);
+ ssi_set_hash_endianity(ctx->hash_mode, &desc[idx]);
+ set_cipher_mode(&desc[idx], ctx->hw_mode);
idx++;
if (async_req) {
@@ -828,22 +812,22 @@ static int ssi_hash_finup(struct ahash_req_ctx *state,
return rc;
}
-static int ssi_hash_final(struct ahash_req_ctx *state,
- struct ssi_hash_ctx *ctx,
- unsigned int digestsize,
- struct scatterlist *src,
- unsigned int nbytes,
- u8 *result,
+static int ssi_hash_final(struct ahash_req_ctx *state,
+ struct ssi_hash_ctx *ctx,
+ unsigned int digestsize,
+ struct scatterlist *src,
+ unsigned int nbytes,
+ u8 *result,
void *async_req)
{
struct device *dev = &ctx->drvdata->plat_dev->dev;
bool is_hmac = ctx->is_hmac;
struct ssi_crypto_req ssi_req = {};
- HwDesc_s desc[SSI_MAX_AHASH_SEQ_LEN];
+ struct cc_hw_desc desc[SSI_MAX_AHASH_SEQ_LEN];
int idx = 0;
int rc;
- SSI_LOG_DEBUG("===== %s-final (%d) ====\n", is_hmac?"hmac":"hash", nbytes);
+ SSI_LOG_DEBUG("===== %s-final (%d) ====\n", is_hmac ? "hmac" : "hash", nbytes);
CHECK_AND_RETURN_UPON_FIPS_ERROR();
@@ -861,90 +845,95 @@ static int ssi_hash_final(struct ahash_req_ctx *state,
/* Setup DX request structure */
ssi_req.user_cb = (void *)ssi_hash_complete;
ssi_req.user_arg = async_req;
-#ifdef ENABLE_CYCLE_COUNT
- ssi_req.op_type = STAT_OP_TYPE_ENCODE; /* Use "Encode" stats */
-#endif
}
/* Restore hash digest */
- HW_DESC_INIT(&desc[idx]);
- HW_DESC_SET_CIPHER_MODE(&desc[idx], ctx->hw_mode);
- HW_DESC_SET_DIN_TYPE(&desc[idx], DMA_DLLI, state->digest_buff_dma_addr, ctx->inter_digestsize, NS_BIT);
- HW_DESC_SET_FLOW_MODE(&desc[idx], S_DIN_to_HASH);
- HW_DESC_SET_SETUP_MODE(&desc[idx], SETUP_LOAD_STATE0);
+ hw_desc_init(&desc[idx]);
+ set_cipher_mode(&desc[idx], ctx->hw_mode);
+ set_din_type(&desc[idx], DMA_DLLI, state->digest_buff_dma_addr,
+ ctx->inter_digestsize, NS_BIT);
+ set_flow_mode(&desc[idx], S_DIN_to_HASH);
+ set_setup_mode(&desc[idx], SETUP_LOAD_STATE0);
idx++;
/* Restore hash current length */
- HW_DESC_INIT(&desc[idx]);
- HW_DESC_SET_CIPHER_MODE(&desc[idx], ctx->hw_mode);
- HW_DESC_SET_CIPHER_CONFIG1(&desc[idx], HASH_PADDING_DISABLED);
- HW_DESC_SET_DIN_TYPE(&desc[idx], DMA_DLLI, state->digest_bytes_len_dma_addr, HASH_LEN_SIZE, NS_BIT);
- HW_DESC_SET_FLOW_MODE(&desc[idx], S_DIN_to_HASH);
- HW_DESC_SET_SETUP_MODE(&desc[idx], SETUP_LOAD_KEY0);
+ hw_desc_init(&desc[idx]);
+ set_cipher_mode(&desc[idx], ctx->hw_mode);
+ set_cipher_config1(&desc[idx], HASH_PADDING_DISABLED);
+ set_din_type(&desc[idx], DMA_DLLI, state->digest_bytes_len_dma_addr,
+ HASH_LEN_SIZE, NS_BIT);
+ set_flow_mode(&desc[idx], S_DIN_to_HASH);
+ set_setup_mode(&desc[idx], SETUP_LOAD_KEY0);
idx++;
ssi_hash_create_data_desc(state, ctx, DIN_HASH, desc, false, &idx);
/* "DO-PAD" must be enabled only when writing current length to HW */
- HW_DESC_INIT(&desc[idx]);
- HW_DESC_SET_CIPHER_DO(&desc[idx], DO_PAD);
- HW_DESC_SET_CIPHER_MODE(&desc[idx], ctx->hw_mode);
- HW_DESC_SET_DOUT_DLLI(&desc[idx], state->digest_bytes_len_dma_addr, HASH_LEN_SIZE, NS_BIT, 0);
- HW_DESC_SET_SETUP_MODE(&desc[idx], SETUP_WRITE_STATE1);
- HW_DESC_SET_FLOW_MODE(&desc[idx], S_HASH_to_DOUT);
+ hw_desc_init(&desc[idx]);
+ set_cipher_do(&desc[idx], DO_PAD);
+ set_cipher_mode(&desc[idx], ctx->hw_mode);
+ set_dout_dlli(&desc[idx], state->digest_bytes_len_dma_addr,
+ HASH_LEN_SIZE, NS_BIT, 0);
+ set_setup_mode(&desc[idx], SETUP_WRITE_STATE1);
+ set_flow_mode(&desc[idx], S_HASH_to_DOUT);
idx++;
if (is_hmac) {
/* Store the hash digest result in the context */
- HW_DESC_INIT(&desc[idx]);
- HW_DESC_SET_CIPHER_MODE(&desc[idx], ctx->hw_mode);
- HW_DESC_SET_DOUT_DLLI(&desc[idx], state->digest_buff_dma_addr, digestsize, NS_BIT, 0);
- ssi_set_hash_endianity(ctx->hash_mode,&desc[idx]);
- HW_DESC_SET_FLOW_MODE(&desc[idx], S_HASH_to_DOUT);
- HW_DESC_SET_SETUP_MODE(&desc[idx], SETUP_WRITE_STATE0);
+ hw_desc_init(&desc[idx]);
+ set_cipher_mode(&desc[idx], ctx->hw_mode);
+ set_dout_dlli(&desc[idx], state->digest_buff_dma_addr,
+ digestsize, NS_BIT, 0);
+ ssi_set_hash_endianity(ctx->hash_mode, &desc[idx]);
+ set_flow_mode(&desc[idx], S_HASH_to_DOUT);
+ set_setup_mode(&desc[idx], SETUP_WRITE_STATE0);
idx++;
/* Loading hash OPAD xor key state */
- HW_DESC_INIT(&desc[idx]);
- HW_DESC_SET_CIPHER_MODE(&desc[idx], ctx->hw_mode);
- HW_DESC_SET_DIN_TYPE(&desc[idx], DMA_DLLI, state->opad_digest_dma_addr, ctx->inter_digestsize, NS_BIT);
- HW_DESC_SET_FLOW_MODE(&desc[idx], S_DIN_to_HASH);
- HW_DESC_SET_SETUP_MODE(&desc[idx], SETUP_LOAD_STATE0);
+ hw_desc_init(&desc[idx]);
+ set_cipher_mode(&desc[idx], ctx->hw_mode);
+ set_din_type(&desc[idx], DMA_DLLI, state->opad_digest_dma_addr,
+ ctx->inter_digestsize, NS_BIT);
+ set_flow_mode(&desc[idx], S_DIN_to_HASH);
+ set_setup_mode(&desc[idx], SETUP_LOAD_STATE0);
idx++;
/* Load the hash current length */
- HW_DESC_INIT(&desc[idx]);
- HW_DESC_SET_CIPHER_MODE(&desc[idx], ctx->hw_mode);
- HW_DESC_SET_DIN_SRAM(&desc[idx], ssi_ahash_get_initial_digest_len_sram_addr(ctx->drvdata, ctx->hash_mode), HASH_LEN_SIZE);
- HW_DESC_SET_CIPHER_CONFIG1(&desc[idx], HASH_PADDING_ENABLED);
- HW_DESC_SET_FLOW_MODE(&desc[idx], S_DIN_to_HASH);
- HW_DESC_SET_SETUP_MODE(&desc[idx], SETUP_LOAD_KEY0);
+ hw_desc_init(&desc[idx]);
+ set_cipher_mode(&desc[idx], ctx->hw_mode);
+ set_din_sram(&desc[idx],
+ ssi_ahash_get_initial_digest_len_sram_addr(
+ctx->drvdata, ctx->hash_mode), HASH_LEN_SIZE);
+ set_cipher_config1(&desc[idx], HASH_PADDING_ENABLED);
+ set_flow_mode(&desc[idx], S_DIN_to_HASH);
+ set_setup_mode(&desc[idx], SETUP_LOAD_KEY0);
idx++;
/* Memory Barrier: wait for IPAD/OPAD axi write to complete */
- HW_DESC_INIT(&desc[idx]);
- HW_DESC_SET_DIN_NO_DMA(&desc[idx], 0, 0xfffff0);
- HW_DESC_SET_DOUT_NO_DMA(&desc[idx], 0, 0, 1);
+ hw_desc_init(&desc[idx]);
+ set_din_no_dma(&desc[idx], 0, 0xfffff0);
+ set_dout_no_dma(&desc[idx], 0, 0, 1);
idx++;
/* Perform HASH update on last digest */
- HW_DESC_INIT(&desc[idx]);
- HW_DESC_SET_DIN_TYPE(&desc[idx], DMA_DLLI, state->digest_buff_dma_addr, digestsize, NS_BIT);
- HW_DESC_SET_FLOW_MODE(&desc[idx], DIN_HASH);
+ hw_desc_init(&desc[idx]);
+ set_din_type(&desc[idx], DMA_DLLI, state->digest_buff_dma_addr,
+ digestsize, NS_BIT);
+ set_flow_mode(&desc[idx], DIN_HASH);
idx++;
}
/* Get final MAC result */
- HW_DESC_INIT(&desc[idx]);
- HW_DESC_SET_DOUT_DLLI(&desc[idx], state->digest_result_dma_addr, digestsize, NS_BIT, async_req? 1:0);
- if (async_req) {
- HW_DESC_SET_QUEUE_LAST_IND(&desc[idx]);
- }
- HW_DESC_SET_FLOW_MODE(&desc[idx], S_HASH_to_DOUT);
- HW_DESC_SET_CIPHER_CONFIG1(&desc[idx], HASH_PADDING_DISABLED);
- HW_DESC_SET_SETUP_MODE(&desc[idx], SETUP_WRITE_STATE0);
- ssi_set_hash_endianity(ctx->hash_mode,&desc[idx]);
- HW_DESC_SET_CIPHER_MODE(&desc[idx], ctx->hw_mode);
+ hw_desc_init(&desc[idx]);
+ set_dout_dlli(&desc[idx], state->digest_result_dma_addr, digestsize,
+ NS_BIT, (async_req ? 1 : 0));
+ if (async_req)
+ set_queue_last_ind(&desc[idx]);
+ set_flow_mode(&desc[idx], S_HASH_to_DOUT);
+ set_cipher_config1(&desc[idx], HASH_PADDING_DISABLED);
+ set_setup_mode(&desc[idx], SETUP_WRITE_STATE0);
+ ssi_set_hash_endianity(ctx->hash_mode, &desc[idx]);
+ set_cipher_mode(&desc[idx], ctx->hw_mode);
idx++;
if (async_req) {
@@ -972,33 +961,18 @@ static int ssi_hash_final(struct ahash_req_ctx *state,
static int ssi_hash_init(struct ahash_req_ctx *state, struct ssi_hash_ctx *ctx)
{
struct device *dev = &ctx->drvdata->plat_dev->dev;
- state->xcbc_count = 0;
- CHECK_AND_RETURN_UPON_FIPS_ERROR();
- ssi_hash_map_request(dev, state, ctx);
-
- return 0;
-}
+ state->xcbc_count = 0;
-#ifdef EXPORT_FIXED
-static int ssi_hash_export(struct ssi_hash_ctx *ctx, void *out)
-{
CHECK_AND_RETURN_UPON_FIPS_ERROR();
- memcpy(out, ctx, sizeof(struct ssi_hash_ctx));
- return 0;
-}
+ ssi_hash_map_request(dev, state, ctx);
-static int ssi_hash_import(struct ssi_hash_ctx *ctx, const void *in)
-{
- CHECK_AND_RETURN_UPON_FIPS_ERROR();
- memcpy(ctx, in, sizeof(struct ssi_hash_ctx));
return 0;
}
-#endif
static int ssi_hash_setkey(void *hash,
- const u8 *key,
- unsigned int keylen,
+ const u8 *key,
+ unsigned int keylen,
bool synchronize)
{
unsigned int hmacPadConst[2] = { HMAC_IPAD_CONST, HMAC_OPAD_CONST };
@@ -1007,27 +981,22 @@ static int ssi_hash_setkey(void *hash,
int blocksize = 0;
int digestsize = 0;
int i, idx = 0, rc = 0;
- HwDesc_s desc[SSI_MAX_AHASH_SEQ_LEN];
+ struct cc_hw_desc desc[SSI_MAX_AHASH_SEQ_LEN];
ssi_sram_addr_t larval_addr;
SSI_LOG_DEBUG("ssi_hash_setkey: start keylen: %d", keylen);
-
+
CHECK_AND_RETURN_UPON_FIPS_ERROR();
- if (synchronize) {
- ctx = crypto_shash_ctx(((struct crypto_shash *)hash));
- blocksize = crypto_tfm_alg_blocksize(&((struct crypto_shash *)hash)->base);
- digestsize = crypto_shash_digestsize(((struct crypto_shash *)hash));
- } else {
- ctx = crypto_ahash_ctx(((struct crypto_ahash *)hash));
- blocksize = crypto_tfm_alg_blocksize(&((struct crypto_ahash *)hash)->base);
- digestsize = crypto_ahash_digestsize(((struct crypto_ahash *)hash));
- }
-
+ ctx = crypto_ahash_ctx(((struct crypto_ahash *)hash));
+ blocksize = crypto_tfm_alg_blocksize(&((struct crypto_ahash *)hash)->base);
+ digestsize = crypto_ahash_digestsize(((struct crypto_ahash *)hash));
+
larval_addr = ssi_ahash_get_larval_digest_sram_addr(
ctx->drvdata, ctx->hash_mode);
/* The keylen value distinguishes HASH in case keylen is ZERO bytes,
- any NON-ZERO value utilizes HMAC flow */
+ * any NON-ZERO value utilizes HMAC flow
+ */
ctx->key_params.keylen = keylen;
ctx->key_params.key_dma_addr = 0;
ctx->is_hmac = true;
@@ -1043,7 +1012,6 @@ static int ssi_hash_setkey(void *hash,
" DMA failed\n", key, keylen);
return -ENOMEM;
}
- SSI_UPDATE_DMA_ADDR_TO_48BIT(ctx->key_params.key_dma_addr, keylen);
SSI_LOG_DEBUG("mapping key-buffer: key_dma_addr=0x%llX "
"keylen=%u\n",
(unsigned long long)ctx->key_params.key_dma_addr,
@@ -1051,79 +1019,76 @@ static int ssi_hash_setkey(void *hash,
if (keylen > blocksize) {
/* Load hash initial state */
- HW_DESC_INIT(&desc[idx]);
- HW_DESC_SET_CIPHER_MODE(&desc[idx], ctx->hw_mode);
- HW_DESC_SET_DIN_SRAM(&desc[idx], larval_addr,
- ctx->inter_digestsize);
- HW_DESC_SET_FLOW_MODE(&desc[idx], S_DIN_to_HASH);
- HW_DESC_SET_SETUP_MODE(&desc[idx], SETUP_LOAD_STATE0);
+ hw_desc_init(&desc[idx]);
+ set_cipher_mode(&desc[idx], ctx->hw_mode);
+ set_din_sram(&desc[idx], larval_addr,
+ ctx->inter_digestsize);
+ set_flow_mode(&desc[idx], S_DIN_to_HASH);
+ set_setup_mode(&desc[idx], SETUP_LOAD_STATE0);
idx++;
-
+
/* Load the hash current length*/
- HW_DESC_INIT(&desc[idx]);
- HW_DESC_SET_CIPHER_MODE(&desc[idx], ctx->hw_mode);
- HW_DESC_SET_DIN_CONST(&desc[idx], 0, HASH_LEN_SIZE);
- HW_DESC_SET_CIPHER_CONFIG1(&desc[idx], HASH_PADDING_ENABLED);
- HW_DESC_SET_FLOW_MODE(&desc[idx], S_DIN_to_HASH);
- HW_DESC_SET_SETUP_MODE(&desc[idx], SETUP_LOAD_KEY0);
+ hw_desc_init(&desc[idx]);
+ set_cipher_mode(&desc[idx], ctx->hw_mode);
+ set_din_const(&desc[idx], 0, HASH_LEN_SIZE);
+ set_cipher_config1(&desc[idx], HASH_PADDING_ENABLED);
+ set_flow_mode(&desc[idx], S_DIN_to_HASH);
+ set_setup_mode(&desc[idx], SETUP_LOAD_KEY0);
idx++;
-
- HW_DESC_INIT(&desc[idx]);
- HW_DESC_SET_DIN_TYPE(&desc[idx], DMA_DLLI,
- ctx->key_params.key_dma_addr,
- keylen, NS_BIT);
- HW_DESC_SET_FLOW_MODE(&desc[idx], DIN_HASH);
+
+ hw_desc_init(&desc[idx]);
+ set_din_type(&desc[idx], DMA_DLLI,
+ ctx->key_params.key_dma_addr, keylen,
+ NS_BIT);
+ set_flow_mode(&desc[idx], DIN_HASH);
idx++;
-
+
/* Get hashed key */
- HW_DESC_INIT(&desc[idx]);
- HW_DESC_SET_CIPHER_MODE(&desc[idx], ctx->hw_mode);
- HW_DESC_SET_DOUT_DLLI(&desc[idx], ctx->opad_tmp_keys_dma_addr,
- digestsize, NS_BIT, 0);
- HW_DESC_SET_FLOW_MODE(&desc[idx], S_HASH_to_DOUT);
- HW_DESC_SET_SETUP_MODE(&desc[idx], SETUP_WRITE_STATE0);
- HW_DESC_SET_CIPHER_CONFIG1(&desc[idx], HASH_PADDING_DISABLED);
- ssi_set_hash_endianity(ctx->hash_mode,&desc[idx]);
+ hw_desc_init(&desc[idx]);
+ set_cipher_mode(&desc[idx], ctx->hw_mode);
+ set_dout_dlli(&desc[idx], ctx->opad_tmp_keys_dma_addr,
+ digestsize, NS_BIT, 0);
+ set_flow_mode(&desc[idx], S_HASH_to_DOUT);
+ set_setup_mode(&desc[idx], SETUP_WRITE_STATE0);
+ set_cipher_config1(&desc[idx], HASH_PADDING_DISABLED);
+ ssi_set_hash_endianity(ctx->hash_mode, &desc[idx]);
idx++;
-
- HW_DESC_INIT(&desc[idx]);
- HW_DESC_SET_DIN_CONST(&desc[idx], 0, (blocksize - digestsize));
- HW_DESC_SET_FLOW_MODE(&desc[idx], BYPASS);
- HW_DESC_SET_DOUT_DLLI(&desc[idx],
- (ctx->opad_tmp_keys_dma_addr + digestsize),
- (blocksize - digestsize),
- NS_BIT, 0);
+
+ hw_desc_init(&desc[idx]);
+ set_din_const(&desc[idx], 0, (blocksize - digestsize));
+ set_flow_mode(&desc[idx], BYPASS);
+ set_dout_dlli(&desc[idx], (ctx->opad_tmp_keys_dma_addr +
+ digestsize),
+ (blocksize - digestsize), NS_BIT, 0);
idx++;
} else {
- HW_DESC_INIT(&desc[idx]);
- HW_DESC_SET_DIN_TYPE(&desc[idx], DMA_DLLI,
- ctx->key_params.key_dma_addr,
- keylen, NS_BIT);
- HW_DESC_SET_FLOW_MODE(&desc[idx], BYPASS);
- HW_DESC_SET_DOUT_DLLI(&desc[idx],
- (ctx->opad_tmp_keys_dma_addr),
- keylen, NS_BIT, 0);
+ hw_desc_init(&desc[idx]);
+ set_din_type(&desc[idx], DMA_DLLI,
+ ctx->key_params.key_dma_addr, keylen,
+ NS_BIT);
+ set_flow_mode(&desc[idx], BYPASS);
+ set_dout_dlli(&desc[idx], ctx->opad_tmp_keys_dma_addr,
+ keylen, NS_BIT, 0);
idx++;
if ((blocksize - keylen) != 0) {
- HW_DESC_INIT(&desc[idx]);
- HW_DESC_SET_DIN_CONST(&desc[idx], 0, (blocksize - keylen));
- HW_DESC_SET_FLOW_MODE(&desc[idx], BYPASS);
- HW_DESC_SET_DOUT_DLLI(&desc[idx],
- (ctx->opad_tmp_keys_dma_addr + keylen),
- (blocksize - keylen),
- NS_BIT, 0);
+ hw_desc_init(&desc[idx]);
+ set_din_const(&desc[idx], 0,
+ (blocksize - keylen));
+ set_flow_mode(&desc[idx], BYPASS);
+ set_dout_dlli(&desc[idx],
+ (ctx->opad_tmp_keys_dma_addr +
+ keylen), (blocksize - keylen),
+ NS_BIT, 0);
idx++;
}
}
} else {
- HW_DESC_INIT(&desc[idx]);
- HW_DESC_SET_DIN_CONST(&desc[idx], 0, blocksize);
- HW_DESC_SET_FLOW_MODE(&desc[idx], BYPASS);
- HW_DESC_SET_DOUT_DLLI(&desc[idx],
- (ctx->opad_tmp_keys_dma_addr),
- blocksize,
- NS_BIT, 0);
+ hw_desc_init(&desc[idx]);
+ set_din_const(&desc[idx], 0, blocksize);
+ set_flow_mode(&desc[idx], BYPASS);
+ set_dout_dlli(&desc[idx], (ctx->opad_tmp_keys_dma_addr),
+ blocksize, NS_BIT, 0);
idx++;
}
@@ -1136,71 +1101,59 @@ static int ssi_hash_setkey(void *hash,
/* calc derived HMAC key */
for (idx = 0, i = 0; i < 2; i++) {
/* Load hash initial state */
- HW_DESC_INIT(&desc[idx]);
- HW_DESC_SET_CIPHER_MODE(&desc[idx], ctx->hw_mode);
- HW_DESC_SET_DIN_SRAM(&desc[idx], larval_addr,
- ctx->inter_digestsize);
- HW_DESC_SET_FLOW_MODE(&desc[idx], S_DIN_to_HASH);
- HW_DESC_SET_SETUP_MODE(&desc[idx], SETUP_LOAD_STATE0);
+ hw_desc_init(&desc[idx]);
+ set_cipher_mode(&desc[idx], ctx->hw_mode);
+ set_din_sram(&desc[idx], larval_addr, ctx->inter_digestsize);
+ set_flow_mode(&desc[idx], S_DIN_to_HASH);
+ set_setup_mode(&desc[idx], SETUP_LOAD_STATE0);
idx++;
/* Load the hash current length*/
- HW_DESC_INIT(&desc[idx]);
- HW_DESC_SET_CIPHER_MODE(&desc[idx], ctx->hw_mode);
- HW_DESC_SET_DIN_CONST(&desc[idx], 0, HASH_LEN_SIZE);
- HW_DESC_SET_FLOW_MODE(&desc[idx], S_DIN_to_HASH);
- HW_DESC_SET_SETUP_MODE(&desc[idx], SETUP_LOAD_KEY0);
+ hw_desc_init(&desc[idx]);
+ set_cipher_mode(&desc[idx], ctx->hw_mode);
+ set_din_const(&desc[idx], 0, HASH_LEN_SIZE);
+ set_flow_mode(&desc[idx], S_DIN_to_HASH);
+ set_setup_mode(&desc[idx], SETUP_LOAD_KEY0);
idx++;
/* Prepare ipad key */
- HW_DESC_INIT(&desc[idx]);
- HW_DESC_SET_XOR_VAL(&desc[idx], hmacPadConst[i]);
- HW_DESC_SET_CIPHER_MODE(&desc[idx], ctx->hw_mode);
- HW_DESC_SET_FLOW_MODE(&desc[idx], S_DIN_to_HASH);
- HW_DESC_SET_SETUP_MODE(&desc[idx], SETUP_LOAD_STATE1);
+ hw_desc_init(&desc[idx]);
+ set_xor_val(&desc[idx], hmacPadConst[i]);
+ set_cipher_mode(&desc[idx], ctx->hw_mode);
+ set_flow_mode(&desc[idx], S_DIN_to_HASH);
+ set_setup_mode(&desc[idx], SETUP_LOAD_STATE1);
idx++;
/* Perform HASH update */
- HW_DESC_INIT(&desc[idx]);
- HW_DESC_SET_DIN_TYPE(&desc[idx], DMA_DLLI,
- ctx->opad_tmp_keys_dma_addr,
- blocksize, NS_BIT);
- HW_DESC_SET_CIPHER_MODE(&desc[idx],ctx->hw_mode);
- HW_DESC_SET_XOR_ACTIVE(&desc[idx]);
- HW_DESC_SET_FLOW_MODE(&desc[idx], DIN_HASH);
+ hw_desc_init(&desc[idx]);
+ set_din_type(&desc[idx], DMA_DLLI, ctx->opad_tmp_keys_dma_addr,
+ blocksize, NS_BIT);
+ set_cipher_mode(&desc[idx], ctx->hw_mode);
+ set_xor_active(&desc[idx]);
+ set_flow_mode(&desc[idx], DIN_HASH);
idx++;
/* Get the IPAD/OPAD xor key (Note, IPAD is the initial digest of the first HASH "update" state) */
- HW_DESC_INIT(&desc[idx]);
- HW_DESC_SET_CIPHER_MODE(&desc[idx], ctx->hw_mode);
+ hw_desc_init(&desc[idx]);
+ set_cipher_mode(&desc[idx], ctx->hw_mode);
if (i > 0) /* Not first iteration */
- HW_DESC_SET_DOUT_DLLI(&desc[idx],
- ctx->opad_tmp_keys_dma_addr,
- ctx->inter_digestsize,
- NS_BIT, 0);
+ set_dout_dlli(&desc[idx], ctx->opad_tmp_keys_dma_addr,
+ ctx->inter_digestsize, NS_BIT, 0);
else /* First iteration */
- HW_DESC_SET_DOUT_DLLI(&desc[idx],
- ctx->digest_buff_dma_addr,
- ctx->inter_digestsize,
- NS_BIT, 0);
- HW_DESC_SET_FLOW_MODE(&desc[idx], S_HASH_to_DOUT);
- HW_DESC_SET_SETUP_MODE(&desc[idx], SETUP_WRITE_STATE0);
+ set_dout_dlli(&desc[idx], ctx->digest_buff_dma_addr,
+ ctx->inter_digestsize, NS_BIT, 0);
+ set_flow_mode(&desc[idx], S_HASH_to_DOUT);
+ set_setup_mode(&desc[idx], SETUP_WRITE_STATE0);
idx++;
}
rc = send_request(ctx->drvdata, &ssi_req, desc, idx, 0);
out:
- if (rc != 0) {
- if (synchronize) {
- crypto_shash_set_flags((struct crypto_shash *)hash, CRYPTO_TFM_RES_BAD_KEY_LEN);
- } else {
- crypto_ahash_set_flags((struct crypto_ahash *)hash, CRYPTO_TFM_RES_BAD_KEY_LEN);
- }
- }
+ if (rc)
+ crypto_ahash_set_flags((struct crypto_ahash *)hash, CRYPTO_TFM_RES_BAD_KEY_LEN);
if (ctx->key_params.key_dma_addr) {
- SSI_RESTORE_DMA_ADDR_TO_48BIT(ctx->key_params.key_dma_addr);
dma_unmap_single(&ctx->drvdata->plat_dev->dev,
ctx->key_params.key_dma_addr,
ctx->key_params.keylen, DMA_TO_DEVICE);
@@ -1211,14 +1164,13 @@ out:
return rc;
}
-
static int ssi_xcbc_setkey(struct crypto_ahash *ahash,
const u8 *key, unsigned int keylen)
{
struct ssi_crypto_req ssi_req = {};
struct ssi_hash_ctx *ctx = crypto_ahash_ctx(ahash);
int idx = 0, rc = 0;
- HwDesc_s desc[SSI_MAX_AHASH_SEQ_LEN];
+ struct cc_hw_desc desc[SSI_MAX_AHASH_SEQ_LEN];
SSI_LOG_DEBUG("===== setkey (%d) ====\n", keylen);
CHECK_AND_RETURN_UPON_FIPS_ERROR();
@@ -1244,43 +1196,43 @@ static int ssi_xcbc_setkey(struct crypto_ahash *ahash,
" DMA failed\n", key, keylen);
return -ENOMEM;
}
- SSI_UPDATE_DMA_ADDR_TO_48BIT(ctx->key_params.key_dma_addr, keylen);
SSI_LOG_DEBUG("mapping key-buffer: key_dma_addr=0x%llX "
"keylen=%u\n",
(unsigned long long)ctx->key_params.key_dma_addr,
ctx->key_params.keylen);
-
+
ctx->is_hmac = true;
/* 1. Load the AES key */
- HW_DESC_INIT(&desc[idx]);
- HW_DESC_SET_DIN_TYPE(&desc[idx], DMA_DLLI, ctx->key_params.key_dma_addr, keylen, NS_BIT);
- HW_DESC_SET_CIPHER_MODE(&desc[idx], DRV_CIPHER_ECB);
- HW_DESC_SET_CIPHER_CONFIG0(&desc[idx], DRV_CRYPTO_DIRECTION_ENCRYPT);
- HW_DESC_SET_KEY_SIZE_AES(&desc[idx], keylen);
- HW_DESC_SET_FLOW_MODE(&desc[idx], S_DIN_to_AES);
- HW_DESC_SET_SETUP_MODE(&desc[idx], SETUP_LOAD_KEY0);
+ hw_desc_init(&desc[idx]);
+ set_din_type(&desc[idx], DMA_DLLI, ctx->key_params.key_dma_addr,
+ keylen, NS_BIT);
+ set_cipher_mode(&desc[idx], DRV_CIPHER_ECB);
+ set_cipher_config0(&desc[idx], DRV_CRYPTO_DIRECTION_ENCRYPT);
+ set_key_size_aes(&desc[idx], keylen);
+ set_flow_mode(&desc[idx], S_DIN_to_AES);
+ set_setup_mode(&desc[idx], SETUP_LOAD_KEY0);
idx++;
- HW_DESC_INIT(&desc[idx]);
- HW_DESC_SET_DIN_CONST(&desc[idx], 0x01010101, CC_AES_128_BIT_KEY_SIZE);
- HW_DESC_SET_FLOW_MODE(&desc[idx], DIN_AES_DOUT);
- HW_DESC_SET_DOUT_DLLI(&desc[idx], (ctx->opad_tmp_keys_dma_addr +
- XCBC_MAC_K1_OFFSET),
+ hw_desc_init(&desc[idx]);
+ set_din_const(&desc[idx], 0x01010101, CC_AES_128_BIT_KEY_SIZE);
+ set_flow_mode(&desc[idx], DIN_AES_DOUT);
+ set_dout_dlli(&desc[idx], (ctx->opad_tmp_keys_dma_addr +
+ XCBC_MAC_K1_OFFSET),
CC_AES_128_BIT_KEY_SIZE, NS_BIT, 0);
idx++;
- HW_DESC_INIT(&desc[idx]);
- HW_DESC_SET_DIN_CONST(&desc[idx], 0x02020202, CC_AES_128_BIT_KEY_SIZE);
- HW_DESC_SET_FLOW_MODE(&desc[idx], DIN_AES_DOUT);
- HW_DESC_SET_DOUT_DLLI(&desc[idx], (ctx->opad_tmp_keys_dma_addr +
- XCBC_MAC_K2_OFFSET),
+ hw_desc_init(&desc[idx]);
+ set_din_const(&desc[idx], 0x02020202, CC_AES_128_BIT_KEY_SIZE);
+ set_flow_mode(&desc[idx], DIN_AES_DOUT);
+ set_dout_dlli(&desc[idx], (ctx->opad_tmp_keys_dma_addr +
+ XCBC_MAC_K2_OFFSET),
CC_AES_128_BIT_KEY_SIZE, NS_BIT, 0);
idx++;
- HW_DESC_INIT(&desc[idx]);
- HW_DESC_SET_DIN_CONST(&desc[idx], 0x03030303, CC_AES_128_BIT_KEY_SIZE);
- HW_DESC_SET_FLOW_MODE(&desc[idx], DIN_AES_DOUT);
- HW_DESC_SET_DOUT_DLLI(&desc[idx], (ctx->opad_tmp_keys_dma_addr +
+ hw_desc_init(&desc[idx]);
+ set_din_const(&desc[idx], 0x03030303, CC_AES_128_BIT_KEY_SIZE);
+ set_flow_mode(&desc[idx], DIN_AES_DOUT);
+ set_dout_dlli(&desc[idx], (ctx->opad_tmp_keys_dma_addr +
XCBC_MAC_K3_OFFSET),
CC_AES_128_BIT_KEY_SIZE, NS_BIT, 0);
idx++;
@@ -1290,7 +1242,6 @@ static int ssi_xcbc_setkey(struct crypto_ahash *ahash,
if (rc != 0)
crypto_ahash_set_flags(ahash, CRYPTO_TFM_RES_BAD_KEY_LEN);
- SSI_RESTORE_DMA_ADDR_TO_48BIT(ctx->key_params.key_dma_addr);
dma_unmap_single(&ctx->drvdata->plat_dev->dev,
ctx->key_params.key_dma_addr,
ctx->key_params.keylen, DMA_TO_DEVICE);
@@ -1300,12 +1251,13 @@ static int ssi_xcbc_setkey(struct crypto_ahash *ahash,
return rc;
}
+
#if SSI_CC_HAS_CMAC
static int ssi_cmac_setkey(struct crypto_ahash *ahash,
const u8 *key, unsigned int keylen)
{
struct ssi_hash_ctx *ctx = crypto_ahash_ctx(ahash);
- DECL_CYCLE_COUNT_RESOURCES;
+
SSI_LOG_DEBUG("===== setkey (%d) ====\n", keylen);
CHECK_AND_RETURN_UPON_FIPS_ERROR();
@@ -1323,25 +1275,20 @@ static int ssi_cmac_setkey(struct crypto_ahash *ahash,
ctx->key_params.keylen = keylen;
/* STAT_PHASE_1: Copy key to ctx */
- START_CYCLE_COUNT();
-
- SSI_RESTORE_DMA_ADDR_TO_48BIT(ctx->opad_tmp_keys_dma_addr);
+
dma_sync_single_for_cpu(&ctx->drvdata->plat_dev->dev,
- ctx->opad_tmp_keys_dma_addr,
+ ctx->opad_tmp_keys_dma_addr,
keylen, DMA_TO_DEVICE);
memcpy(ctx->opad_tmp_keys_buff, key, keylen);
if (keylen == 24)
memset(ctx->opad_tmp_keys_buff + 24, 0, CC_AES_KEY_SIZE_MAX - 24);
-
+
dma_sync_single_for_device(&ctx->drvdata->plat_dev->dev,
- ctx->opad_tmp_keys_dma_addr,
+ ctx->opad_tmp_keys_dma_addr,
keylen, DMA_TO_DEVICE);
- SSI_UPDATE_DMA_ADDR_TO_48BIT(ctx->opad_tmp_keys_dma_addr, keylen);
-
+
ctx->key_params.keylen = keylen;
-
- END_CYCLE_COUNT(STAT_OP_TYPE_SETKEY, STAT_PHASE_1);
return 0;
}
@@ -1352,7 +1299,6 @@ static void ssi_hash_free_ctx(struct ssi_hash_ctx *ctx)
struct device *dev = &ctx->drvdata->plat_dev->dev;
if (ctx->digest_buff_dma_addr != 0) {
- SSI_RESTORE_DMA_ADDR_TO_48BIT(ctx->digest_buff_dma_addr);
dma_unmap_single(dev, ctx->digest_buff_dma_addr,
sizeof(ctx->digest_buff), DMA_BIDIRECTIONAL);
SSI_LOG_DEBUG("Unmapped digest-buffer: "
@@ -1361,7 +1307,6 @@ static void ssi_hash_free_ctx(struct ssi_hash_ctx *ctx)
ctx->digest_buff_dma_addr = 0;
}
if (ctx->opad_tmp_keys_dma_addr != 0) {
- SSI_RESTORE_DMA_ADDR_TO_48BIT(ctx->opad_tmp_keys_dma_addr);
dma_unmap_single(dev, ctx->opad_tmp_keys_dma_addr,
sizeof(ctx->opad_tmp_keys_buff),
DMA_BIDIRECTIONAL);
@@ -1372,10 +1317,8 @@ static void ssi_hash_free_ctx(struct ssi_hash_ctx *ctx)
}
ctx->key_params.keylen = 0;
-
}
-
static int ssi_hash_alloc_ctx(struct ssi_hash_ctx *ctx)
{
struct device *dev = &ctx->drvdata->plat_dev->dev;
@@ -1388,8 +1331,6 @@ static int ssi_hash_alloc_ctx(struct ssi_hash_ctx *ctx)
sizeof(ctx->digest_buff), ctx->digest_buff);
goto fail;
}
- SSI_UPDATE_DMA_ADDR_TO_48BIT(ctx->digest_buff_dma_addr,
- sizeof(ctx->digest_buff));
SSI_LOG_DEBUG("Mapped digest %zu B at va=%pK to dma=0x%llX\n",
sizeof(ctx->digest_buff), ctx->digest_buff,
(unsigned long long)ctx->digest_buff_dma_addr);
@@ -1401,8 +1342,6 @@ static int ssi_hash_alloc_ctx(struct ssi_hash_ctx *ctx)
ctx->opad_tmp_keys_buff);
goto fail;
}
- SSI_UPDATE_DMA_ADDR_TO_48BIT(ctx->opad_tmp_keys_dma_addr,
- sizeof(ctx->opad_tmp_keys_buff));
SSI_LOG_DEBUG("Mapped opad_tmp_keys %zu B at va=%pK to dma=0x%llX\n",
sizeof(ctx->opad_tmp_keys_buff), ctx->opad_tmp_keys_buff,
(unsigned long long)ctx->opad_tmp_keys_dma_addr);
@@ -1415,34 +1354,16 @@ fail:
return -ENOMEM;
}
-static int ssi_shash_cra_init(struct crypto_tfm *tfm)
-{
- struct ssi_hash_ctx *ctx = crypto_tfm_ctx(tfm);
- struct shash_alg * shash_alg =
- container_of(tfm->__crt_alg, struct shash_alg, base);
- struct ssi_hash_alg *ssi_alg =
- container_of(shash_alg, struct ssi_hash_alg, shash_alg);
-
- CHECK_AND_RETURN_UPON_FIPS_ERROR();
- ctx->hash_mode = ssi_alg->hash_mode;
- ctx->hw_mode = ssi_alg->hw_mode;
- ctx->inter_digestsize = ssi_alg->inter_digestsize;
- ctx->drvdata = ssi_alg->drvdata;
-
- return ssi_hash_alloc_ctx(ctx);
-}
-
static int ssi_ahash_cra_init(struct crypto_tfm *tfm)
{
struct ssi_hash_ctx *ctx = crypto_tfm_ctx(tfm);
- struct hash_alg_common * hash_alg_common =
+ struct hash_alg_common *hash_alg_common =
container_of(tfm->__crt_alg, struct hash_alg_common, base);
- struct ahash_alg *ahash_alg =
+ struct ahash_alg *ahash_alg =
container_of(hash_alg_common, struct ahash_alg, halg);
struct ssi_hash_alg *ssi_alg =
container_of(ahash_alg, struct ssi_hash_alg, ahash_alg);
-
CHECK_AND_RETURN_UPON_FIPS_ERROR();
crypto_ahash_set_reqsize(__crypto_ahash_cast(tfm),
sizeof(struct ahash_req_ctx));
@@ -1471,9 +1392,9 @@ static int ssi_mac_update(struct ahash_request *req)
struct device *dev = &ctx->drvdata->plat_dev->dev;
unsigned int block_size = crypto_tfm_alg_blocksize(&tfm->base);
struct ssi_crypto_req ssi_req = {};
- HwDesc_s desc[SSI_MAX_AHASH_SEQ_LEN];
+ struct cc_hw_desc desc[SSI_MAX_AHASH_SEQ_LEN];
int rc;
- uint32_t idx = 0;
+ u32 idx = 0;
CHECK_AND_RETURN_UPON_FIPS_ERROR();
if (req->nbytes == 0) {
@@ -1494,29 +1415,26 @@ static int ssi_mac_update(struct ahash_request *req)
return -ENOMEM;
}
- if (ctx->hw_mode == DRV_CIPHER_XCBC_MAC) {
+ if (ctx->hw_mode == DRV_CIPHER_XCBC_MAC)
ssi_hash_create_xcbc_setup(req, desc, &idx);
- } else {
+ else
ssi_hash_create_cmac_setup(req, desc, &idx);
- }
-
+
ssi_hash_create_data_desc(state, ctx, DIN_AES_DOUT, desc, true, &idx);
/* store the hash digest result in context */
- HW_DESC_INIT(&desc[idx]);
- HW_DESC_SET_CIPHER_MODE(&desc[idx], ctx->hw_mode);
- HW_DESC_SET_DOUT_DLLI(&desc[idx], state->digest_buff_dma_addr, ctx->inter_digestsize, NS_BIT, 1);
- HW_DESC_SET_QUEUE_LAST_IND(&desc[idx]);
- HW_DESC_SET_FLOW_MODE(&desc[idx], S_AES_to_DOUT);
- HW_DESC_SET_SETUP_MODE(&desc[idx], SETUP_WRITE_STATE0);
+ hw_desc_init(&desc[idx]);
+ set_cipher_mode(&desc[idx], ctx->hw_mode);
+ set_dout_dlli(&desc[idx], state->digest_buff_dma_addr,
+ ctx->inter_digestsize, NS_BIT, 1);
+ set_queue_last_ind(&desc[idx]);
+ set_flow_mode(&desc[idx], S_AES_to_DOUT);
+ set_setup_mode(&desc[idx], SETUP_WRITE_STATE0);
idx++;
/* Setup DX request structure */
ssi_req.user_cb = (void *)ssi_hash_update_complete;
ssi_req.user_arg = (void *)req;
-#ifdef ENABLE_CYCLE_COUNT
- ssi_req.op_type = STAT_OP_TYPE_ENCODE; /* Use "Encode" stats */
-#endif
rc = send_request(ctx->drvdata, &ssi_req, desc, idx, 1);
if (unlikely(rc != -EINPROGRESS)) {
@@ -1533,15 +1451,14 @@ static int ssi_mac_final(struct ahash_request *req)
struct ssi_hash_ctx *ctx = crypto_ahash_ctx(tfm);
struct device *dev = &ctx->drvdata->plat_dev->dev;
struct ssi_crypto_req ssi_req = {};
- HwDesc_s desc[SSI_MAX_AHASH_SEQ_LEN];
+ struct cc_hw_desc desc[SSI_MAX_AHASH_SEQ_LEN];
int idx = 0;
int rc = 0;
- uint32_t keySize, keyLen;
- uint32_t digestsize = crypto_ahash_digestsize(tfm);
+ u32 keySize, keyLen;
+ u32 digestsize = crypto_ahash_digestsize(tfm);
- uint32_t rem_cnt = state->buff_index ? state->buff1_cnt :
+ u32 rem_cnt = state->buff_index ? state->buff1_cnt :
state->buff0_cnt;
-
CHECK_AND_RETURN_UPON_FIPS_ERROR();
if (ctx->hw_mode == DRV_CIPHER_XCBC_MAC) {
@@ -1567,68 +1484,66 @@ static int ssi_mac_final(struct ahash_request *req)
/* Setup DX request structure */
ssi_req.user_cb = (void *)ssi_hash_complete;
ssi_req.user_arg = (void *)req;
-#ifdef ENABLE_CYCLE_COUNT
- ssi_req.op_type = STAT_OP_TYPE_ENCODE; /* Use "Encode" stats */
-#endif
if (state->xcbc_count && (rem_cnt == 0)) {
/* Load key for ECB decryption */
- HW_DESC_INIT(&desc[idx]);
- HW_DESC_SET_CIPHER_MODE(&desc[idx], DRV_CIPHER_ECB);
- HW_DESC_SET_CIPHER_CONFIG0(&desc[idx], DRV_CRYPTO_DIRECTION_DECRYPT);
- HW_DESC_SET_DIN_TYPE(&desc[idx], DMA_DLLI,
- (ctx->opad_tmp_keys_dma_addr +
- XCBC_MAC_K1_OFFSET),
- keySize, NS_BIT);
- HW_DESC_SET_KEY_SIZE_AES(&desc[idx], keyLen);
- HW_DESC_SET_FLOW_MODE(&desc[idx], S_DIN_to_AES);
- HW_DESC_SET_SETUP_MODE(&desc[idx], SETUP_LOAD_KEY0);
+ hw_desc_init(&desc[idx]);
+ set_cipher_mode(&desc[idx], DRV_CIPHER_ECB);
+ set_cipher_config0(&desc[idx], DRV_CRYPTO_DIRECTION_DECRYPT);
+ set_din_type(&desc[idx], DMA_DLLI,
+ (ctx->opad_tmp_keys_dma_addr +
+ XCBC_MAC_K1_OFFSET), keySize, NS_BIT);
+ set_key_size_aes(&desc[idx], keyLen);
+ set_flow_mode(&desc[idx], S_DIN_to_AES);
+ set_setup_mode(&desc[idx], SETUP_LOAD_KEY0);
idx++;
-
/* Initiate decryption of block state to previous block_state-XOR-M[n] */
- HW_DESC_INIT(&desc[idx]);
- HW_DESC_SET_DIN_TYPE(&desc[idx], DMA_DLLI, state->digest_buff_dma_addr, CC_AES_BLOCK_SIZE, NS_BIT);
- HW_DESC_SET_DOUT_DLLI(&desc[idx], state->digest_buff_dma_addr, CC_AES_BLOCK_SIZE, NS_BIT,0);
- HW_DESC_SET_FLOW_MODE(&desc[idx], DIN_AES_DOUT);
+ hw_desc_init(&desc[idx]);
+ set_din_type(&desc[idx], DMA_DLLI, state->digest_buff_dma_addr,
+ CC_AES_BLOCK_SIZE, NS_BIT);
+ set_dout_dlli(&desc[idx], state->digest_buff_dma_addr,
+ CC_AES_BLOCK_SIZE, NS_BIT, 0);
+ set_flow_mode(&desc[idx], DIN_AES_DOUT);
idx++;
/* Memory Barrier: wait for axi write to complete */
- HW_DESC_INIT(&desc[idx]);
- HW_DESC_SET_DIN_NO_DMA(&desc[idx], 0, 0xfffff0);
- HW_DESC_SET_DOUT_NO_DMA(&desc[idx], 0, 0, 1);
+ hw_desc_init(&desc[idx]);
+ set_din_no_dma(&desc[idx], 0, 0xfffff0);
+ set_dout_no_dma(&desc[idx], 0, 0, 1);
idx++;
}
-
- if (ctx->hw_mode == DRV_CIPHER_XCBC_MAC) {
+
+ if (ctx->hw_mode == DRV_CIPHER_XCBC_MAC)
ssi_hash_create_xcbc_setup(req, desc, &idx);
- } else {
+ else
ssi_hash_create_cmac_setup(req, desc, &idx);
- }
if (state->xcbc_count == 0) {
- HW_DESC_INIT(&desc[idx]);
- HW_DESC_SET_CIPHER_MODE(&desc[idx], ctx->hw_mode);
- HW_DESC_SET_KEY_SIZE_AES(&desc[idx], keyLen);
- HW_DESC_SET_CMAC_SIZE0_MODE(&desc[idx]);
- HW_DESC_SET_FLOW_MODE(&desc[idx], S_DIN_to_AES);
+ hw_desc_init(&desc[idx]);
+ set_cipher_mode(&desc[idx], ctx->hw_mode);
+ set_key_size_aes(&desc[idx], keyLen);
+ set_cmac_size0_mode(&desc[idx]);
+ set_flow_mode(&desc[idx], S_DIN_to_AES);
idx++;
} else if (rem_cnt > 0) {
ssi_hash_create_data_desc(state, ctx, DIN_AES_DOUT, desc, false, &idx);
} else {
- HW_DESC_INIT(&desc[idx]);
- HW_DESC_SET_DIN_CONST(&desc[idx], 0x00, CC_AES_BLOCK_SIZE);
- HW_DESC_SET_FLOW_MODE(&desc[idx], DIN_AES_DOUT);
+ hw_desc_init(&desc[idx]);
+ set_din_const(&desc[idx], 0x00, CC_AES_BLOCK_SIZE);
+ set_flow_mode(&desc[idx], DIN_AES_DOUT);
idx++;
}
-
+
/* Get final MAC result */
- HW_DESC_INIT(&desc[idx]);
- HW_DESC_SET_DOUT_DLLI(&desc[idx], state->digest_result_dma_addr, digestsize, NS_BIT, 1); /*TODO*/
- HW_DESC_SET_QUEUE_LAST_IND(&desc[idx]);
- HW_DESC_SET_FLOW_MODE(&desc[idx], S_AES_to_DOUT);
- HW_DESC_SET_SETUP_MODE(&desc[idx], SETUP_WRITE_STATE0);
- HW_DESC_SET_CIPHER_MODE(&desc[idx], ctx->hw_mode);
+ hw_desc_init(&desc[idx]);
+ /* TODO */
+ set_dout_dlli(&desc[idx], state->digest_result_dma_addr,
+ digestsize, NS_BIT, 1);
+ set_queue_last_ind(&desc[idx]);
+ set_flow_mode(&desc[idx], S_AES_to_DOUT);
+ set_setup_mode(&desc[idx], SETUP_WRITE_STATE0);
+ set_cipher_mode(&desc[idx], ctx->hw_mode);
idx++;
rc = send_request(ctx->drvdata, &ssi_req, desc, idx, 1);
@@ -1647,11 +1562,11 @@ static int ssi_mac_finup(struct ahash_request *req)
struct ssi_hash_ctx *ctx = crypto_ahash_ctx(tfm);
struct device *dev = &ctx->drvdata->plat_dev->dev;
struct ssi_crypto_req ssi_req = {};
- HwDesc_s desc[SSI_MAX_AHASH_SEQ_LEN];
+ struct cc_hw_desc desc[SSI_MAX_AHASH_SEQ_LEN];
int idx = 0;
int rc = 0;
- uint32_t key_len = 0;
- uint32_t digestsize = crypto_ahash_digestsize(tfm);
+ u32 key_len = 0;
+ u32 digestsize = crypto_ahash_digestsize(tfm);
SSI_LOG_DEBUG("===== finup xcbc(%d) ====\n", req->nbytes);
CHECK_AND_RETURN_UPON_FIPS_ERROR();
@@ -1659,7 +1574,7 @@ static int ssi_mac_finup(struct ahash_request *req)
SSI_LOG_DEBUG("No data to update. Call to fdx_mac_final \n");
return ssi_mac_final(req);
}
-
+
if (unlikely(ssi_buffer_mgr_map_hash_request_final(ctx->drvdata, state, req->src, req->nbytes, 1) != 0)) {
SSI_LOG_ERR("map_ahash_request_final() failed\n");
return -ENOMEM;
@@ -1672,9 +1587,6 @@ static int ssi_mac_finup(struct ahash_request *req)
/* Setup DX request structure */
ssi_req.user_cb = (void *)ssi_hash_complete;
ssi_req.user_arg = (void *)req;
-#ifdef ENABLE_CYCLE_COUNT
- ssi_req.op_type = STAT_OP_TYPE_ENCODE; /* Use "Encode" stats */
-#endif
if (ctx->hw_mode == DRV_CIPHER_XCBC_MAC) {
key_len = CC_AES_128_BIT_KEY_SIZE;
@@ -1685,23 +1597,25 @@ static int ssi_mac_finup(struct ahash_request *req)
}
if (req->nbytes == 0) {
- HW_DESC_INIT(&desc[idx]);
- HW_DESC_SET_CIPHER_MODE(&desc[idx], ctx->hw_mode);
- HW_DESC_SET_KEY_SIZE_AES(&desc[idx], key_len);
- HW_DESC_SET_CMAC_SIZE0_MODE(&desc[idx]);
- HW_DESC_SET_FLOW_MODE(&desc[idx], S_DIN_to_AES);
+ hw_desc_init(&desc[idx]);
+ set_cipher_mode(&desc[idx], ctx->hw_mode);
+ set_key_size_aes(&desc[idx], key_len);
+ set_cmac_size0_mode(&desc[idx]);
+ set_flow_mode(&desc[idx], S_DIN_to_AES);
idx++;
} else {
ssi_hash_create_data_desc(state, ctx, DIN_AES_DOUT, desc, false, &idx);
}
-
+
/* Get final MAC result */
- HW_DESC_INIT(&desc[idx]);
- HW_DESC_SET_DOUT_DLLI(&desc[idx], state->digest_result_dma_addr, digestsize, NS_BIT, 1); /*TODO*/
- HW_DESC_SET_QUEUE_LAST_IND(&desc[idx]);
- HW_DESC_SET_FLOW_MODE(&desc[idx], S_AES_to_DOUT);
- HW_DESC_SET_SETUP_MODE(&desc[idx], SETUP_WRITE_STATE0);
- HW_DESC_SET_CIPHER_MODE(&desc[idx], ctx->hw_mode);
+ hw_desc_init(&desc[idx]);
+ /* TODO */
+ set_dout_dlli(&desc[idx], state->digest_result_dma_addr,
+ digestsize, NS_BIT, 1);
+ set_queue_last_ind(&desc[idx]);
+ set_flow_mode(&desc[idx], S_AES_to_DOUT);
+ set_setup_mode(&desc[idx], SETUP_WRITE_STATE0);
+ set_cipher_mode(&desc[idx], ctx->hw_mode);
idx++;
rc = send_request(ctx->drvdata, &ssi_req, desc, idx, 1);
@@ -1719,16 +1633,16 @@ static int ssi_mac_digest(struct ahash_request *req)
struct crypto_ahash *tfm = crypto_ahash_reqtfm(req);
struct ssi_hash_ctx *ctx = crypto_ahash_ctx(tfm);
struct device *dev = &ctx->drvdata->plat_dev->dev;
- uint32_t digestsize = crypto_ahash_digestsize(tfm);
+ u32 digestsize = crypto_ahash_digestsize(tfm);
struct ssi_crypto_req ssi_req = {};
- HwDesc_s desc[SSI_MAX_AHASH_SEQ_LEN];
- uint32_t keyLen;
+ struct cc_hw_desc desc[SSI_MAX_AHASH_SEQ_LEN];
+ u32 keyLen;
int idx = 0;
int rc;
SSI_LOG_DEBUG("===== -digest mac (%d) ====\n", req->nbytes);
CHECK_AND_RETURN_UPON_FIPS_ERROR();
-
+
if (unlikely(ssi_hash_map_request(dev, state, ctx) != 0)) {
SSI_LOG_ERR("map_ahash_source() failed\n");
return -ENOMEM;
@@ -1742,15 +1656,11 @@ static int ssi_mac_digest(struct ahash_request *req)
SSI_LOG_ERR("map_ahash_request_final() failed\n");
return -ENOMEM;
}
-
+
/* Setup DX request structure */
ssi_req.user_cb = (void *)ssi_hash_digest_complete;
ssi_req.user_arg = (void *)req;
-#ifdef ENABLE_CYCLE_COUNT
- ssi_req.op_type = STAT_OP_TYPE_ENCODE; /* Use "Encode" stats */
-#endif
-
if (ctx->hw_mode == DRV_CIPHER_XCBC_MAC) {
keyLen = CC_AES_128_BIT_KEY_SIZE;
ssi_hash_create_xcbc_setup(req, desc, &idx);
@@ -1760,24 +1670,25 @@ static int ssi_mac_digest(struct ahash_request *req)
}
if (req->nbytes == 0) {
- HW_DESC_INIT(&desc[idx]);
- HW_DESC_SET_CIPHER_MODE(&desc[idx], ctx->hw_mode);
- HW_DESC_SET_KEY_SIZE_AES(&desc[idx], keyLen);
- HW_DESC_SET_CMAC_SIZE0_MODE(&desc[idx]);
- HW_DESC_SET_FLOW_MODE(&desc[idx], S_DIN_to_AES);
+ hw_desc_init(&desc[idx]);
+ set_cipher_mode(&desc[idx], ctx->hw_mode);
+ set_key_size_aes(&desc[idx], keyLen);
+ set_cmac_size0_mode(&desc[idx]);
+ set_flow_mode(&desc[idx], S_DIN_to_AES);
idx++;
} else {
ssi_hash_create_data_desc(state, ctx, DIN_AES_DOUT, desc, false, &idx);
}
-
+
/* Get final MAC result */
- HW_DESC_INIT(&desc[idx]);
- HW_DESC_SET_DOUT_DLLI(&desc[idx], state->digest_result_dma_addr, CC_AES_BLOCK_SIZE, NS_BIT,1);
- HW_DESC_SET_QUEUE_LAST_IND(&desc[idx]);
- HW_DESC_SET_FLOW_MODE(&desc[idx], S_AES_to_DOUT);
- HW_DESC_SET_SETUP_MODE(&desc[idx], SETUP_WRITE_STATE0);
- HW_DESC_SET_CIPHER_CONFIG0(&desc[idx],DESC_DIRECTION_ENCRYPT_ENCRYPT);
- HW_DESC_SET_CIPHER_MODE(&desc[idx], ctx->hw_mode);
+ hw_desc_init(&desc[idx]);
+ set_dout_dlli(&desc[idx], state->digest_result_dma_addr,
+ CC_AES_BLOCK_SIZE, NS_BIT, 1);
+ set_queue_last_ind(&desc[idx]);
+ set_flow_mode(&desc[idx], S_AES_to_DOUT);
+ set_setup_mode(&desc[idx], SETUP_WRITE_STATE0);
+ set_cipher_config0(&desc[idx], DESC_DIRECTION_ENCRYPT_ENCRYPT);
+ set_cipher_mode(&desc[idx], ctx->hw_mode);
idx++;
rc = send_request(ctx->drvdata, &ssi_req, desc, idx, 1);
@@ -1790,108 +1701,14 @@ static int ssi_mac_digest(struct ahash_request *req)
return rc;
}
-//shash wrap functions
-#ifdef SYNC_ALGS
-static int ssi_shash_digest(struct shash_desc *desc,
- const u8 *data, unsigned int len, u8 *out)
-{
- struct ahash_req_ctx *state = shash_desc_ctx(desc);
- struct crypto_shash *tfm = desc->tfm;
- struct ssi_hash_ctx *ctx = crypto_shash_ctx(tfm);
- uint32_t digestsize = crypto_shash_digestsize(tfm);
- struct scatterlist src;
-
- if (len == 0) {
- return ssi_hash_digest(state, ctx, digestsize, NULL, 0, out, NULL);
- }
-
- /* sg_init_one may crash when len is 0 (depends on kernel configuration) */
- sg_init_one(&src, (const void *)data, len);
-
- return ssi_hash_digest(state, ctx, digestsize, &src, len, out, NULL);
-}
-
-static int ssi_shash_update(struct shash_desc *desc,
- const u8 *data, unsigned int len)
-{
- struct ahash_req_ctx *state = shash_desc_ctx(desc);
- struct crypto_shash *tfm = desc->tfm;
- struct ssi_hash_ctx *ctx = crypto_shash_ctx(tfm);
- uint32_t blocksize = crypto_tfm_alg_blocksize(&tfm->base);
- struct scatterlist src;
-
- sg_init_one(&src, (const void *)data, len);
-
- return ssi_hash_update(state, ctx, blocksize, &src, len, NULL);
-}
-
-static int ssi_shash_finup(struct shash_desc *desc,
- const u8 *data, unsigned int len, u8 *out)
-{
- struct ahash_req_ctx *state = shash_desc_ctx(desc);
- struct crypto_shash *tfm = desc->tfm;
- struct ssi_hash_ctx *ctx = crypto_shash_ctx(tfm);
- uint32_t digestsize = crypto_shash_digestsize(tfm);
- struct scatterlist src;
-
- sg_init_one(&src, (const void *)data, len);
-
- return ssi_hash_finup(state, ctx, digestsize, &src, len, out, NULL);
-}
-
-static int ssi_shash_final(struct shash_desc *desc, u8 *out)
-{
- struct ahash_req_ctx *state = shash_desc_ctx(desc);
- struct crypto_shash *tfm = desc->tfm;
- struct ssi_hash_ctx *ctx = crypto_shash_ctx(tfm);
- uint32_t digestsize = crypto_shash_digestsize(tfm);
-
- return ssi_hash_final(state, ctx, digestsize, NULL, 0, out, NULL);
-}
-
-static int ssi_shash_init(struct shash_desc *desc)
-{
- struct ahash_req_ctx *state = shash_desc_ctx(desc);
- struct crypto_shash *tfm = desc->tfm;
- struct ssi_hash_ctx *ctx = crypto_shash_ctx(tfm);
-
- return ssi_hash_init(state, ctx);
-}
-
-#ifdef EXPORT_FIXED
-static int ssi_shash_export(struct shash_desc *desc, void *out)
-{
- struct crypto_shash *tfm = desc->tfm;
- struct ssi_hash_ctx *ctx = crypto_shash_ctx(tfm);
-
- return ssi_hash_export(ctx, out);
-}
-
-static int ssi_shash_import(struct shash_desc *desc, const void *in)
-{
- struct crypto_shash *tfm = desc->tfm;
- struct ssi_hash_ctx *ctx = crypto_shash_ctx(tfm);
-
- return ssi_hash_import(ctx, in);
-}
-#endif
-
-static int ssi_shash_setkey(struct crypto_shash *tfm,
- const u8 *key, unsigned int keylen)
-{
- return ssi_hash_setkey((void *) tfm, key, keylen, true);
-}
-
-#endif /* SYNC_ALGS */
-
//ahash wrap functions
static int ssi_ahash_digest(struct ahash_request *req)
{
struct ahash_req_ctx *state = ahash_request_ctx(req);
struct crypto_ahash *tfm = crypto_ahash_reqtfm(req);
struct ssi_hash_ctx *ctx = crypto_ahash_ctx(tfm);
- uint32_t digestsize = crypto_ahash_digestsize(tfm);
-
+ u32 digestsize = crypto_ahash_digestsize(tfm);
+
return ssi_hash_digest(state, ctx, digestsize, req->src, req->nbytes, req->result, (void *)req);
}
@@ -1901,7 +1718,7 @@ static int ssi_ahash_update(struct ahash_request *req)
struct crypto_ahash *tfm = crypto_ahash_reqtfm(req);
struct ssi_hash_ctx *ctx = crypto_ahash_ctx(tfm);
unsigned int block_size = crypto_tfm_alg_blocksize(&tfm->base);
-
+
return ssi_hash_update(state, ctx, block_size, req->src, req->nbytes, (void *)req);
}
@@ -1910,8 +1727,8 @@ static int ssi_ahash_finup(struct ahash_request *req)
struct ahash_req_ctx *state = ahash_request_ctx(req);
struct crypto_ahash *tfm = crypto_ahash_reqtfm(req);
struct ssi_hash_ctx *ctx = crypto_ahash_ctx(tfm);
- uint32_t digestsize = crypto_ahash_digestsize(tfm);
-
+ u32 digestsize = crypto_ahash_digestsize(tfm);
+
return ssi_hash_finup(state, ctx, digestsize, req->src, req->nbytes, req->result, (void *)req);
}
@@ -1920,8 +1737,8 @@ static int ssi_ahash_final(struct ahash_request *req)
struct ahash_req_ctx *state = ahash_request_ctx(req);
struct crypto_ahash *tfm = crypto_ahash_reqtfm(req);
struct ssi_hash_ctx *ctx = crypto_ahash_ctx(tfm);
- uint32_t digestsize = crypto_ahash_digestsize(tfm);
-
+ u32 digestsize = crypto_ahash_digestsize(tfm);
+
return ssi_hash_final(state, ctx, digestsize, req->src, req->nbytes, req->result, (void *)req);
}
@@ -1929,81 +1746,161 @@ static int ssi_ahash_init(struct ahash_request *req)
{
struct ahash_req_ctx *state = ahash_request_ctx(req);
struct crypto_ahash *tfm = crypto_ahash_reqtfm(req);
- struct ssi_hash_ctx *ctx = crypto_ahash_ctx(tfm);
+ struct ssi_hash_ctx *ctx = crypto_ahash_ctx(tfm);
SSI_LOG_DEBUG("===== init (%d) ====\n", req->nbytes);
return ssi_hash_init(state, ctx);
}
-#ifdef EXPORT_FIXED
static int ssi_ahash_export(struct ahash_request *req, void *out)
{
struct crypto_ahash *ahash = crypto_ahash_reqtfm(req);
struct ssi_hash_ctx *ctx = crypto_ahash_ctx(ahash);
-
- return ssi_hash_export(ctx, out);
+ struct device *dev = &ctx->drvdata->plat_dev->dev;
+ struct ahash_req_ctx *state = ahash_request_ctx(req);
+ u8 *curr_buff = state->buff_index ? state->buff1 : state->buff0;
+ u32 curr_buff_cnt = state->buff_index ? state->buff1_cnt :
+ state->buff0_cnt;
+ const u32 tmp = CC_EXPORT_MAGIC;
+
+ CHECK_AND_RETURN_UPON_FIPS_ERROR();
+
+ memcpy(out, &tmp, sizeof(u32));
+ out += sizeof(u32);
+
+ dma_sync_single_for_cpu(dev, state->digest_buff_dma_addr,
+ ctx->inter_digestsize, DMA_BIDIRECTIONAL);
+ memcpy(out, state->digest_buff, ctx->inter_digestsize);
+ out += ctx->inter_digestsize;
+
+ if (state->digest_bytes_len_dma_addr) {
+ dma_sync_single_for_cpu(dev, state->digest_bytes_len_dma_addr,
+ HASH_LEN_SIZE, DMA_BIDIRECTIONAL);
+ memcpy(out, state->digest_bytes_len, HASH_LEN_SIZE);
+ } else {
+ /* Poison the unused exported digest len field. */
+ memset(out, 0x5F, HASH_LEN_SIZE);
+ }
+ out += HASH_LEN_SIZE;
+
+ memcpy(out, &curr_buff_cnt, sizeof(u32));
+ out += sizeof(u32);
+
+ memcpy(out, curr_buff, curr_buff_cnt);
+
+ /* No sync for device ineeded since we did not change the data,
+ * we only copy it
+ */
+
+ return 0;
}
static int ssi_ahash_import(struct ahash_request *req, const void *in)
{
struct crypto_ahash *ahash = crypto_ahash_reqtfm(req);
struct ssi_hash_ctx *ctx = crypto_ahash_ctx(ahash);
-
- return ssi_hash_import(ctx, in);
+ struct device *dev = &ctx->drvdata->plat_dev->dev;
+ struct ahash_req_ctx *state = ahash_request_ctx(req);
+ u32 tmp;
+ int rc;
+
+ CHECK_AND_RETURN_UPON_FIPS_ERROR();
+
+ memcpy(&tmp, in, sizeof(u32));
+ if (tmp != CC_EXPORT_MAGIC) {
+ rc = -EINVAL;
+ goto out;
+ }
+ in += sizeof(u32);
+
+ rc = ssi_hash_init(state, ctx);
+ if (rc)
+ goto out;
+
+ dma_sync_single_for_cpu(dev, state->digest_buff_dma_addr,
+ ctx->inter_digestsize, DMA_BIDIRECTIONAL);
+ memcpy(state->digest_buff, in, ctx->inter_digestsize);
+ in += ctx->inter_digestsize;
+
+ if (state->digest_bytes_len_dma_addr) {
+ dma_sync_single_for_cpu(dev, state->digest_bytes_len_dma_addr,
+ HASH_LEN_SIZE, DMA_BIDIRECTIONAL);
+ memcpy(state->digest_bytes_len, in, HASH_LEN_SIZE);
+ }
+ in += HASH_LEN_SIZE;
+
+ dma_sync_single_for_device(dev, state->digest_buff_dma_addr,
+ ctx->inter_digestsize, DMA_BIDIRECTIONAL);
+
+ if (state->digest_bytes_len_dma_addr)
+ dma_sync_single_for_device(dev,
+ state->digest_bytes_len_dma_addr,
+ HASH_LEN_SIZE, DMA_BIDIRECTIONAL);
+
+ state->buff_index = 0;
+
+ /* Sanity check the data as much as possible */
+ memcpy(&tmp, in, sizeof(u32));
+ if (tmp > SSI_MAX_HASH_BLCK_SIZE) {
+ rc = -EINVAL;
+ goto out;
+ }
+ in += sizeof(u32);
+
+ state->buff0_cnt = tmp;
+ memcpy(state->buff0, in, state->buff0_cnt);
+
+out:
+ return rc;
}
-#endif
static int ssi_ahash_setkey(struct crypto_ahash *ahash,
const u8 *key, unsigned int keylen)
-{
- return ssi_hash_setkey((void *) ahash, key, keylen, false);
+{
+ return ssi_hash_setkey((void *)ahash, key, keylen, false);
}
struct ssi_hash_template {
char name[CRYPTO_MAX_ALG_NAME];
char driver_name[CRYPTO_MAX_ALG_NAME];
- char hmac_name[CRYPTO_MAX_ALG_NAME];
- char hmac_driver_name[CRYPTO_MAX_ALG_NAME];
+ char mac_name[CRYPTO_MAX_ALG_NAME];
+ char mac_driver_name[CRYPTO_MAX_ALG_NAME];
unsigned int blocksize;
bool synchronize;
- union {
- struct ahash_alg template_ahash;
- struct shash_alg template_shash;
- };
+ struct ahash_alg template_ahash;
int hash_mode;
int hw_mode;
int inter_digestsize;
struct ssi_drvdata *drvdata;
};
+#define CC_STATE_SIZE(_x) \
+ ((_x) + HASH_LEN_SIZE + SSI_MAX_HASH_BLCK_SIZE + (2 * sizeof(u32)))
+
/* hash descriptors */
static struct ssi_hash_template driver_hash[] = {
//Asynchronize hash template
{
.name = "sha1",
.driver_name = "sha1-dx",
- .hmac_name = "hmac(sha1)",
- .hmac_driver_name = "hmac-sha1-dx",
+ .mac_name = "hmac(sha1)",
+ .mac_driver_name = "hmac-sha1-dx",
.blocksize = SHA1_BLOCK_SIZE,
.synchronize = false,
- {
- .template_ahash = {
- .init = ssi_ahash_init,
- .update = ssi_ahash_update,
- .final = ssi_ahash_final,
- .finup = ssi_ahash_finup,
- .digest = ssi_ahash_digest,
-#ifdef EXPORT_FIXED
- .export = ssi_ahash_export,
- .import = ssi_ahash_import,
-#endif
- .setkey = ssi_ahash_setkey,
- .halg = {
- .digestsize = SHA1_DIGEST_SIZE,
- .statesize = sizeof(struct sha1_state),
- },
- },
+ .template_ahash = {
+ .init = ssi_ahash_init,
+ .update = ssi_ahash_update,
+ .final = ssi_ahash_final,
+ .finup = ssi_ahash_finup,
+ .digest = ssi_ahash_digest,
+ .export = ssi_ahash_export,
+ .import = ssi_ahash_import,
+ .setkey = ssi_ahash_setkey,
+ .halg = {
+ .digestsize = SHA1_DIGEST_SIZE,
+ .statesize = CC_STATE_SIZE(SHA1_DIGEST_SIZE),
+ },
},
.hash_mode = DRV_HASH_SHA1,
.hw_mode = DRV_HASH_HW_SHA1,
@@ -2012,27 +1909,22 @@ static struct ssi_hash_template driver_hash[] = {
{
.name = "sha256",
.driver_name = "sha256-dx",
- .hmac_name = "hmac(sha256)",
- .hmac_driver_name = "hmac-sha256-dx",
+ .mac_name = "hmac(sha256)",
+ .mac_driver_name = "hmac-sha256-dx",
.blocksize = SHA256_BLOCK_SIZE,
- .synchronize = false,
- {
- .template_ahash = {
- .init = ssi_ahash_init,
- .update = ssi_ahash_update,
- .final = ssi_ahash_final,
- .finup = ssi_ahash_finup,
- .digest = ssi_ahash_digest,
-#ifdef EXPORT_FIXED
- .export = ssi_ahash_export,
- .import = ssi_ahash_import,
-#endif
- .setkey = ssi_ahash_setkey,
- .halg = {
- .digestsize = SHA256_DIGEST_SIZE,
- .statesize = sizeof(struct sha256_state),
- },
- },
+ .template_ahash = {
+ .init = ssi_ahash_init,
+ .update = ssi_ahash_update,
+ .final = ssi_ahash_final,
+ .finup = ssi_ahash_finup,
+ .digest = ssi_ahash_digest,
+ .export = ssi_ahash_export,
+ .import = ssi_ahash_import,
+ .setkey = ssi_ahash_setkey,
+ .halg = {
+ .digestsize = SHA256_DIGEST_SIZE,
+ .statesize = CC_STATE_SIZE(SHA256_DIGEST_SIZE)
+ },
},
.hash_mode = DRV_HASH_SHA256,
.hw_mode = DRV_HASH_HW_SHA256,
@@ -2041,27 +1933,22 @@ static struct ssi_hash_template driver_hash[] = {
{
.name = "sha224",
.driver_name = "sha224-dx",
- .hmac_name = "hmac(sha224)",
- .hmac_driver_name = "hmac-sha224-dx",
+ .mac_name = "hmac(sha224)",
+ .mac_driver_name = "hmac-sha224-dx",
.blocksize = SHA224_BLOCK_SIZE,
- .synchronize = false,
- {
- .template_ahash = {
- .init = ssi_ahash_init,
- .update = ssi_ahash_update,
- .final = ssi_ahash_final,
- .finup = ssi_ahash_finup,
- .digest = ssi_ahash_digest,
-#ifdef EXPORT_FIXED
- .export = ssi_ahash_export,
- .import = ssi_ahash_import,
-#endif
- .setkey = ssi_ahash_setkey,
- .halg = {
- .digestsize = SHA224_DIGEST_SIZE,
- .statesize = sizeof(struct sha256_state),
- },
- },
+ .template_ahash = {
+ .init = ssi_ahash_init,
+ .update = ssi_ahash_update,
+ .final = ssi_ahash_final,
+ .finup = ssi_ahash_finup,
+ .digest = ssi_ahash_digest,
+ .export = ssi_ahash_export,
+ .import = ssi_ahash_import,
+ .setkey = ssi_ahash_setkey,
+ .halg = {
+ .digestsize = SHA224_DIGEST_SIZE,
+ .statesize = CC_STATE_SIZE(SHA224_DIGEST_SIZE),
+ },
},
.hash_mode = DRV_HASH_SHA224,
.hw_mode = DRV_HASH_HW_SHA256,
@@ -2071,27 +1958,22 @@ static struct ssi_hash_template driver_hash[] = {
{
.name = "sha384",
.driver_name = "sha384-dx",
- .hmac_name = "hmac(sha384)",
- .hmac_driver_name = "hmac-sha384-dx",
+ .mac_name = "hmac(sha384)",
+ .mac_driver_name = "hmac-sha384-dx",
.blocksize = SHA384_BLOCK_SIZE,
- .synchronize = false,
- {
- .template_ahash = {
- .init = ssi_ahash_init,
- .update = ssi_ahash_update,
- .final = ssi_ahash_final,
- .finup = ssi_ahash_finup,
- .digest = ssi_ahash_digest,
-#ifdef EXPORT_FIXED
- .export = ssi_ahash_export,
- .import = ssi_ahash_import,
-#endif
- .setkey = ssi_ahash_setkey,
- .halg = {
- .digestsize = SHA384_DIGEST_SIZE,
- .statesize = sizeof(struct sha512_state),
- },
- },
+ .template_ahash = {
+ .init = ssi_ahash_init,
+ .update = ssi_ahash_update,
+ .final = ssi_ahash_final,
+ .finup = ssi_ahash_finup,
+ .digest = ssi_ahash_digest,
+ .export = ssi_ahash_export,
+ .import = ssi_ahash_import,
+ .setkey = ssi_ahash_setkey,
+ .halg = {
+ .digestsize = SHA384_DIGEST_SIZE,
+ .statesize = CC_STATE_SIZE(SHA384_DIGEST_SIZE),
+ },
},
.hash_mode = DRV_HASH_SHA384,
.hw_mode = DRV_HASH_HW_SHA512,
@@ -2100,27 +1982,22 @@ static struct ssi_hash_template driver_hash[] = {
{
.name = "sha512",
.driver_name = "sha512-dx",
- .hmac_name = "hmac(sha512)",
- .hmac_driver_name = "hmac-sha512-dx",
+ .mac_name = "hmac(sha512)",
+ .mac_driver_name = "hmac-sha512-dx",
.blocksize = SHA512_BLOCK_SIZE,
- .synchronize = false,
- {
- .template_ahash = {
- .init = ssi_ahash_init,
- .update = ssi_ahash_update,
- .final = ssi_ahash_final,
- .finup = ssi_ahash_finup,
- .digest = ssi_ahash_digest,
-#ifdef EXPORT_FIXED
- .export = ssi_ahash_export,
- .import = ssi_ahash_import,
-#endif
- .setkey = ssi_ahash_setkey,
- .halg = {
- .digestsize = SHA512_DIGEST_SIZE,
- .statesize = sizeof(struct sha512_state),
- },
- },
+ .template_ahash = {
+ .init = ssi_ahash_init,
+ .update = ssi_ahash_update,
+ .final = ssi_ahash_final,
+ .finup = ssi_ahash_finup,
+ .digest = ssi_ahash_digest,
+ .export = ssi_ahash_export,
+ .import = ssi_ahash_import,
+ .setkey = ssi_ahash_setkey,
+ .halg = {
+ .digestsize = SHA512_DIGEST_SIZE,
+ .statesize = CC_STATE_SIZE(SHA512_DIGEST_SIZE),
+ },
},
.hash_mode = DRV_HASH_SHA512,
.hw_mode = DRV_HASH_HW_SHA512,
@@ -2130,54 +2007,44 @@ static struct ssi_hash_template driver_hash[] = {
{
.name = "md5",
.driver_name = "md5-dx",
- .hmac_name = "hmac(md5)",
- .hmac_driver_name = "hmac-md5-dx",
+ .mac_name = "hmac(md5)",
+ .mac_driver_name = "hmac-md5-dx",
.blocksize = MD5_HMAC_BLOCK_SIZE,
- .synchronize = false,
- {
- .template_ahash = {
- .init = ssi_ahash_init,
- .update = ssi_ahash_update,
- .final = ssi_ahash_final,
- .finup = ssi_ahash_finup,
- .digest = ssi_ahash_digest,
-#ifdef EXPORT_FIXED
- .export = ssi_ahash_export,
- .import = ssi_ahash_import,
-#endif
- .setkey = ssi_ahash_setkey,
- .halg = {
- .digestsize = MD5_DIGEST_SIZE,
- .statesize = sizeof(struct md5_state),
- },
- },
+ .template_ahash = {
+ .init = ssi_ahash_init,
+ .update = ssi_ahash_update,
+ .final = ssi_ahash_final,
+ .finup = ssi_ahash_finup,
+ .digest = ssi_ahash_digest,
+ .export = ssi_ahash_export,
+ .import = ssi_ahash_import,
+ .setkey = ssi_ahash_setkey,
+ .halg = {
+ .digestsize = MD5_DIGEST_SIZE,
+ .statesize = CC_STATE_SIZE(MD5_DIGEST_SIZE),
+ },
},
.hash_mode = DRV_HASH_MD5,
.hw_mode = DRV_HASH_HW_MD5,
.inter_digestsize = MD5_DIGEST_SIZE,
},
{
- .name = "xcbc(aes)",
- .driver_name = "xcbc-aes-dx",
+ .mac_name = "xcbc(aes)",
+ .mac_driver_name = "xcbc-aes-dx",
.blocksize = AES_BLOCK_SIZE,
- .synchronize = false,
- {
- .template_ahash = {
- .init = ssi_ahash_init,
- .update = ssi_mac_update,
- .final = ssi_mac_final,
- .finup = ssi_mac_finup,
- .digest = ssi_mac_digest,
- .setkey = ssi_xcbc_setkey,
-#ifdef EXPORT_FIXED
- .export = ssi_ahash_export,
- .import = ssi_ahash_import,
-#endif
- .halg = {
- .digestsize = AES_BLOCK_SIZE,
- .statesize = sizeof(struct aeshash_state),
- },
- },
+ .template_ahash = {
+ .init = ssi_ahash_init,
+ .update = ssi_mac_update,
+ .final = ssi_mac_final,
+ .finup = ssi_mac_finup,
+ .digest = ssi_mac_digest,
+ .setkey = ssi_xcbc_setkey,
+ .export = ssi_ahash_export,
+ .import = ssi_ahash_import,
+ .halg = {
+ .digestsize = AES_BLOCK_SIZE,
+ .statesize = CC_STATE_SIZE(AES_BLOCK_SIZE),
+ },
},
.hash_mode = DRV_HASH_NULL,
.hw_mode = DRV_CIPHER_XCBC_MAC,
@@ -2185,34 +2052,29 @@ static struct ssi_hash_template driver_hash[] = {
},
#if SSI_CC_HAS_CMAC
{
- .name = "cmac(aes)",
- .driver_name = "cmac-aes-dx",
+ .mac_name = "cmac(aes)",
+ .mac_driver_name = "cmac-aes-dx",
.blocksize = AES_BLOCK_SIZE,
- .synchronize = false,
- {
- .template_ahash = {
- .init = ssi_ahash_init,
- .update = ssi_mac_update,
- .final = ssi_mac_final,
- .finup = ssi_mac_finup,
- .digest = ssi_mac_digest,
- .setkey = ssi_cmac_setkey,
-#ifdef EXPORT_FIXED
- .export = ssi_ahash_export,
- .import = ssi_ahash_import,
-#endif
- .halg = {
- .digestsize = AES_BLOCK_SIZE,
- .statesize = sizeof(struct aeshash_state),
- },
- },
+ .template_ahash = {
+ .init = ssi_ahash_init,
+ .update = ssi_mac_update,
+ .final = ssi_mac_final,
+ .finup = ssi_mac_finup,
+ .digest = ssi_mac_digest,
+ .setkey = ssi_cmac_setkey,
+ .export = ssi_ahash_export,
+ .import = ssi_ahash_import,
+ .halg = {
+ .digestsize = AES_BLOCK_SIZE,
+ .statesize = CC_STATE_SIZE(AES_BLOCK_SIZE),
+ },
},
.hash_mode = DRV_HASH_NULL,
.hw_mode = DRV_CIPHER_CMAC,
.inter_digestsize = AES_BLOCK_SIZE,
},
#endif
-
+
};
static struct ssi_hash_alg *
@@ -2220,6 +2082,7 @@ ssi_hash_create_alg(struct ssi_hash_template *template, bool keyed)
{
struct ssi_hash_alg *t_crypto_alg;
struct crypto_alg *alg;
+ struct ahash_alg *halg;
t_crypto_alg = kzalloc(sizeof(struct ssi_hash_alg), GFP_KERNEL);
if (!t_crypto_alg) {
@@ -2227,27 +2090,17 @@ ssi_hash_create_alg(struct ssi_hash_template *template, bool keyed)
return ERR_PTR(-ENOMEM);
}
- t_crypto_alg->synchronize = template->synchronize;
- if (template->synchronize) {
- struct shash_alg *halg;
- t_crypto_alg->shash_alg = template->template_shash;
- halg = &t_crypto_alg->shash_alg;
- alg = &halg->base;
- if (!keyed) halg->setkey = NULL;
- } else {
- struct ahash_alg *halg;
- t_crypto_alg->ahash_alg = template->template_ahash;
- halg = &t_crypto_alg->ahash_alg;
- alg = &halg->halg.base;
- if (!keyed) halg->setkey = NULL;
- }
+ t_crypto_alg->ahash_alg = template->template_ahash;
+ halg = &t_crypto_alg->ahash_alg;
+ alg = &halg->halg.base;
if (keyed) {
snprintf(alg->cra_name, CRYPTO_MAX_ALG_NAME, "%s",
- template->hmac_name);
+ template->mac_name);
snprintf(alg->cra_driver_name, CRYPTO_MAX_ALG_NAME, "%s",
- template->hmac_driver_name);
+ template->mac_driver_name);
} else {
+ halg->setkey = NULL;
snprintf(alg->cra_name, CRYPTO_MAX_ALG_NAME, "%s",
template->name);
snprintf(alg->cra_driver_name, CRYPTO_MAX_ALG_NAME, "%s",
@@ -2259,18 +2112,11 @@ ssi_hash_create_alg(struct ssi_hash_template *template, bool keyed)
alg->cra_blocksize = template->blocksize;
alg->cra_alignmask = 0;
alg->cra_exit = ssi_hash_cra_exit;
-
- if (template->synchronize) {
- alg->cra_init = ssi_shash_cra_init;
- alg->cra_flags = CRYPTO_ALG_TYPE_SHASH |
- CRYPTO_ALG_KERN_DRIVER_ONLY;
- alg->cra_type = &crypto_shash_type;
- } else {
- alg->cra_init = ssi_ahash_cra_init;
- alg->cra_flags = CRYPTO_ALG_ASYNC | CRYPTO_ALG_TYPE_AHASH |
+
+ alg->cra_init = ssi_ahash_cra_init;
+ alg->cra_flags = CRYPTO_ALG_ASYNC | CRYPTO_ALG_TYPE_AHASH |
CRYPTO_ALG_KERN_DRIVER_ONLY;
- alg->cra_type = &crypto_ahash_type;
- }
+ alg->cra_type = &crypto_ahash_type;
t_crypto_alg->hash_mode = template->hash_mode;
t_crypto_alg->hw_mode = template->hw_mode;
@@ -2284,7 +2130,7 @@ int ssi_hash_init_sram_digest_consts(struct ssi_drvdata *drvdata)
struct ssi_hash_handle *hash_handle = drvdata->hash_handle;
ssi_sram_addr_t sram_buff_ofs = hash_handle->digest_len_sram_addr;
unsigned int larval_seq_len = 0;
- HwDesc_s larval_seq[CC_DIGEST_SIZE_MAX/sizeof(uint32_t)];
+ struct cc_hw_desc larval_seq[CC_DIGEST_SIZE_MAX / sizeof(u32)];
int rc = 0;
#if (DX_DEV_SHA_MAX > 256)
int i;
@@ -2351,15 +2197,15 @@ int ssi_hash_init_sram_digest_consts(struct ssi_drvdata *drvdata)
#if (DX_DEV_SHA_MAX > 256)
/* We are forced to swap each double-word larval before copying to sram */
for (i = 0; i < ARRAY_SIZE(sha384_init); i++) {
- const uint32_t const0 = ((uint32_t *)((uint64_t *)&sha384_init[i]))[1];
- const uint32_t const1 = ((uint32_t *)((uint64_t *)&sha384_init[i]))[0];
+ const u32 const0 = ((u32 *)((u64 *)&sha384_init[i]))[1];
+ const u32 const1 = ((u32 *)((u64 *)&sha384_init[i]))[0];
ssi_sram_mgr_const2sram_desc(&const0, sram_buff_ofs, 1,
larval_seq, &larval_seq_len);
- sram_buff_ofs += sizeof(uint32_t);
+ sram_buff_ofs += sizeof(u32);
ssi_sram_mgr_const2sram_desc(&const1, sram_buff_ofs, 1,
larval_seq, &larval_seq_len);
- sram_buff_ofs += sizeof(uint32_t);
+ sram_buff_ofs += sizeof(u32);
}
rc = send_request_init(drvdata, larval_seq, larval_seq_len);
if (unlikely(rc != 0)) {
@@ -2369,15 +2215,15 @@ int ssi_hash_init_sram_digest_consts(struct ssi_drvdata *drvdata)
larval_seq_len = 0;
for (i = 0; i < ARRAY_SIZE(sha512_init); i++) {
- const uint32_t const0 = ((uint32_t *)((uint64_t *)&sha512_init[i]))[1];
- const uint32_t const1 = ((uint32_t *)((uint64_t *)&sha512_init[i]))[0];
+ const u32 const0 = ((u32 *)((u64 *)&sha512_init[i]))[1];
+ const u32 const1 = ((u32 *)((u64 *)&sha512_init[i]))[0];
ssi_sram_mgr_const2sram_desc(&const0, sram_buff_ofs, 1,
larval_seq, &larval_seq_len);
- sram_buff_ofs += sizeof(uint32_t);
+ sram_buff_ofs += sizeof(u32);
ssi_sram_mgr_const2sram_desc(&const1, sram_buff_ofs, 1,
larval_seq, &larval_seq_len);
- sram_buff_ofs += sizeof(uint32_t);
+ sram_buff_ofs += sizeof(u32);
}
rc = send_request_init(drvdata, larval_seq, larval_seq_len);
if (unlikely(rc != 0)) {
@@ -2394,12 +2240,12 @@ int ssi_hash_alloc(struct ssi_drvdata *drvdata)
{
struct ssi_hash_handle *hash_handle;
ssi_sram_addr_t sram_buff;
- uint32_t sram_size_to_alloc;
+ u32 sram_size_to_alloc;
int rc = 0;
int alg;
hash_handle = kzalloc(sizeof(struct ssi_hash_handle), GFP_KERNEL);
- if (hash_handle == NULL) {
+ if (!hash_handle) {
SSI_LOG_ERR("kzalloc failed to allocate %zu B\n",
sizeof(struct ssi_hash_handle));
rc = -ENOMEM;
@@ -2418,7 +2264,7 @@ int ssi_hash_alloc(struct ssi_drvdata *drvdata)
sizeof(sha1_init) +
sizeof(sha224_init) +
sizeof(sha256_init);
-
+
sram_buff = ssi_sram_mgr_alloc(drvdata, sram_size_to_alloc);
if (sram_buff == NULL_SRAM_ADDR) {
SSI_LOG_ERR("SRAM pool exhausted\n");
@@ -2441,41 +2287,33 @@ int ssi_hash_alloc(struct ssi_drvdata *drvdata)
/* ahash registration */
for (alg = 0; alg < ARRAY_SIZE(driver_hash); alg++) {
struct ssi_hash_alg *t_alg;
-
+ int hw_mode = driver_hash[alg].hw_mode;
+
/* register hmac version */
+ t_alg = ssi_hash_create_alg(&driver_hash[alg], true);
+ if (IS_ERR(t_alg)) {
+ rc = PTR_ERR(t_alg);
+ SSI_LOG_ERR("%s alg allocation failed\n",
+ driver_hash[alg].driver_name);
+ goto fail;
+ }
+ t_alg->drvdata = drvdata;
- if ((((struct ssi_hash_template)driver_hash[alg]).hw_mode != DRV_CIPHER_XCBC_MAC) &&
- (((struct ssi_hash_template)driver_hash[alg]).hw_mode != DRV_CIPHER_CMAC)) {
- t_alg = ssi_hash_create_alg(&driver_hash[alg], true);
- if (IS_ERR(t_alg)) {
- rc = PTR_ERR(t_alg);
- SSI_LOG_ERR("%s alg allocation failed\n",
- driver_hash[alg].driver_name);
- goto fail;
- }
- t_alg->drvdata = drvdata;
-
- if (t_alg->synchronize) {
- rc = crypto_register_shash(&t_alg->shash_alg);
- if (unlikely(rc != 0)) {
- SSI_LOG_ERR("%s alg registration failed\n",
- t_alg->shash_alg.base.cra_driver_name);
- kfree(t_alg);
- goto fail;
- } else
- list_add_tail(&t_alg->entry, &hash_handle->hash_list);
- } else {
- rc = crypto_register_ahash(&t_alg->ahash_alg);
- if (unlikely(rc != 0)) {
- SSI_LOG_ERR("%s alg registration failed\n",
- t_alg->ahash_alg.halg.base.cra_driver_name);
- kfree(t_alg);
- goto fail;
- } else
- list_add_tail(&t_alg->entry, &hash_handle->hash_list);
- }
+ rc = crypto_register_ahash(&t_alg->ahash_alg);
+ if (unlikely(rc)) {
+ SSI_LOG_ERR("%s alg registration failed\n",
+ driver_hash[alg].driver_name);
+ kfree(t_alg);
+ goto fail;
+ } else {
+ list_add_tail(&t_alg->entry,
+ &hash_handle->hash_list);
}
+ if ((hw_mode == DRV_CIPHER_XCBC_MAC) ||
+ (hw_mode == DRV_CIPHER_CMAC))
+ continue;
+
/* register hash version */
t_alg = ssi_hash_create_alg(&driver_hash[alg], false);
if (IS_ERR(t_alg)) {
@@ -2485,26 +2323,15 @@ int ssi_hash_alloc(struct ssi_drvdata *drvdata)
goto fail;
}
t_alg->drvdata = drvdata;
-
- if (t_alg->synchronize) {
- rc = crypto_register_shash(&t_alg->shash_alg);
- if (unlikely(rc != 0)) {
- SSI_LOG_ERR("%s alg registration failed\n",
- t_alg->shash_alg.base.cra_driver_name);
- kfree(t_alg);
- goto fail;
- } else
- list_add_tail(&t_alg->entry, &hash_handle->hash_list);
-
+
+ rc = crypto_register_ahash(&t_alg->ahash_alg);
+ if (unlikely(rc)) {
+ SSI_LOG_ERR("%s alg registration failed\n",
+ driver_hash[alg].driver_name);
+ kfree(t_alg);
+ goto fail;
} else {
- rc = crypto_register_ahash(&t_alg->ahash_alg);
- if (unlikely(rc != 0)) {
- SSI_LOG_ERR("%s alg registration failed\n",
- t_alg->ahash_alg.halg.base.cra_driver_name);
- kfree(t_alg);
- goto fail;
- } else
- list_add_tail(&t_alg->entry, &hash_handle->hash_list);
+ list_add_tail(&t_alg->entry, &hash_handle->hash_list);
}
}
@@ -2512,7 +2339,7 @@ int ssi_hash_alloc(struct ssi_drvdata *drvdata)
fail:
- if (drvdata->hash_handle != NULL) {
+ if (drvdata->hash_handle) {
kfree(drvdata->hash_handle);
drvdata->hash_handle = NULL;
}
@@ -2524,26 +2351,21 @@ int ssi_hash_free(struct ssi_drvdata *drvdata)
struct ssi_hash_alg *t_hash_alg, *hash_n;
struct ssi_hash_handle *hash_handle = drvdata->hash_handle;
- if (hash_handle != NULL) {
-
+ if (hash_handle) {
list_for_each_entry_safe(t_hash_alg, hash_n, &hash_handle->hash_list, entry) {
- if (t_hash_alg->synchronize) {
- crypto_unregister_shash(&t_hash_alg->shash_alg);
- } else {
- crypto_unregister_ahash(&t_hash_alg->ahash_alg);
- }
+ crypto_unregister_ahash(&t_hash_alg->ahash_alg);
list_del(&t_hash_alg->entry);
kfree(t_hash_alg);
}
-
+
kfree(hash_handle);
drvdata->hash_handle = NULL;
}
return 0;
}
-static void ssi_hash_create_xcbc_setup(struct ahash_request *areq,
- HwDesc_s desc[],
+static void ssi_hash_create_xcbc_setup(struct ahash_request *areq,
+ struct cc_hw_desc desc[],
unsigned int *seq_size) {
unsigned int idx = *seq_size;
struct ahash_req_ctx *state = ahash_request_ctx(areq);
@@ -2551,55 +2373,56 @@ static void ssi_hash_create_xcbc_setup(struct ahash_request *areq,
struct ssi_hash_ctx *ctx = crypto_ahash_ctx(tfm);
/* Setup XCBC MAC K1 */
- HW_DESC_INIT(&desc[idx]);
- HW_DESC_SET_DIN_TYPE(&desc[idx], DMA_DLLI, (ctx->opad_tmp_keys_dma_addr
- + XCBC_MAC_K1_OFFSET),
- CC_AES_128_BIT_KEY_SIZE, NS_BIT);
- HW_DESC_SET_SETUP_MODE(&desc[idx], SETUP_LOAD_KEY0);
- HW_DESC_SET_CIPHER_MODE(&desc[idx], DRV_CIPHER_XCBC_MAC);
- HW_DESC_SET_CIPHER_CONFIG0(&desc[idx], DESC_DIRECTION_ENCRYPT_ENCRYPT);
- HW_DESC_SET_KEY_SIZE_AES(&desc[idx], CC_AES_128_BIT_KEY_SIZE);
- HW_DESC_SET_FLOW_MODE(&desc[idx], S_DIN_to_AES);
+ hw_desc_init(&desc[idx]);
+ set_din_type(&desc[idx], DMA_DLLI, (ctx->opad_tmp_keys_dma_addr +
+ XCBC_MAC_K1_OFFSET),
+ CC_AES_128_BIT_KEY_SIZE, NS_BIT);
+ set_setup_mode(&desc[idx], SETUP_LOAD_KEY0);
+ set_cipher_mode(&desc[idx], DRV_CIPHER_XCBC_MAC);
+ set_cipher_config0(&desc[idx], DESC_DIRECTION_ENCRYPT_ENCRYPT);
+ set_key_size_aes(&desc[idx], CC_AES_128_BIT_KEY_SIZE);
+ set_flow_mode(&desc[idx], S_DIN_to_AES);
idx++;
/* Setup XCBC MAC K2 */
- HW_DESC_INIT(&desc[idx]);
- HW_DESC_SET_DIN_TYPE(&desc[idx], DMA_DLLI, (ctx->opad_tmp_keys_dma_addr
- + XCBC_MAC_K2_OFFSET),
- CC_AES_128_BIT_KEY_SIZE, NS_BIT);
- HW_DESC_SET_SETUP_MODE(&desc[idx], SETUP_LOAD_STATE1);
- HW_DESC_SET_CIPHER_MODE(&desc[idx], DRV_CIPHER_XCBC_MAC);
- HW_DESC_SET_CIPHER_CONFIG0(&desc[idx], DESC_DIRECTION_ENCRYPT_ENCRYPT);
- HW_DESC_SET_KEY_SIZE_AES(&desc[idx], CC_AES_128_BIT_KEY_SIZE);
- HW_DESC_SET_FLOW_MODE(&desc[idx], S_DIN_to_AES);
+ hw_desc_init(&desc[idx]);
+ set_din_type(&desc[idx], DMA_DLLI, (ctx->opad_tmp_keys_dma_addr +
+ XCBC_MAC_K2_OFFSET),
+ CC_AES_128_BIT_KEY_SIZE, NS_BIT);
+ set_setup_mode(&desc[idx], SETUP_LOAD_STATE1);
+ set_cipher_mode(&desc[idx], DRV_CIPHER_XCBC_MAC);
+ set_cipher_config0(&desc[idx], DESC_DIRECTION_ENCRYPT_ENCRYPT);
+ set_key_size_aes(&desc[idx], CC_AES_128_BIT_KEY_SIZE);
+ set_flow_mode(&desc[idx], S_DIN_to_AES);
idx++;
/* Setup XCBC MAC K3 */
- HW_DESC_INIT(&desc[idx]);
- HW_DESC_SET_DIN_TYPE(&desc[idx], DMA_DLLI, (ctx->opad_tmp_keys_dma_addr
- + XCBC_MAC_K3_OFFSET),
- CC_AES_128_BIT_KEY_SIZE, NS_BIT);
- HW_DESC_SET_SETUP_MODE(&desc[idx], SETUP_LOAD_STATE2);
- HW_DESC_SET_CIPHER_MODE(&desc[idx], DRV_CIPHER_XCBC_MAC);
- HW_DESC_SET_CIPHER_CONFIG0(&desc[idx], DESC_DIRECTION_ENCRYPT_ENCRYPT);
- HW_DESC_SET_KEY_SIZE_AES(&desc[idx], CC_AES_128_BIT_KEY_SIZE);
- HW_DESC_SET_FLOW_MODE(&desc[idx], S_DIN_to_AES);
+ hw_desc_init(&desc[idx]);
+ set_din_type(&desc[idx], DMA_DLLI, (ctx->opad_tmp_keys_dma_addr +
+ XCBC_MAC_K3_OFFSET),
+ CC_AES_128_BIT_KEY_SIZE, NS_BIT);
+ set_setup_mode(&desc[idx], SETUP_LOAD_STATE2);
+ set_cipher_mode(&desc[idx], DRV_CIPHER_XCBC_MAC);
+ set_cipher_config0(&desc[idx], DESC_DIRECTION_ENCRYPT_ENCRYPT);
+ set_key_size_aes(&desc[idx], CC_AES_128_BIT_KEY_SIZE);
+ set_flow_mode(&desc[idx], S_DIN_to_AES);
idx++;
/* Loading MAC state */
- HW_DESC_INIT(&desc[idx]);
- HW_DESC_SET_DIN_TYPE(&desc[idx], DMA_DLLI, state->digest_buff_dma_addr, CC_AES_BLOCK_SIZE, NS_BIT);
- HW_DESC_SET_SETUP_MODE(&desc[idx], SETUP_LOAD_STATE0);
- HW_DESC_SET_CIPHER_MODE(&desc[idx], DRV_CIPHER_XCBC_MAC);
- HW_DESC_SET_CIPHER_CONFIG0(&desc[idx], DESC_DIRECTION_ENCRYPT_ENCRYPT);
- HW_DESC_SET_KEY_SIZE_AES(&desc[idx], CC_AES_128_BIT_KEY_SIZE);
- HW_DESC_SET_FLOW_MODE(&desc[idx], S_DIN_to_AES);
+ hw_desc_init(&desc[idx]);
+ set_din_type(&desc[idx], DMA_DLLI, state->digest_buff_dma_addr,
+ CC_AES_BLOCK_SIZE, NS_BIT);
+ set_setup_mode(&desc[idx], SETUP_LOAD_STATE0);
+ set_cipher_mode(&desc[idx], DRV_CIPHER_XCBC_MAC);
+ set_cipher_config0(&desc[idx], DESC_DIRECTION_ENCRYPT_ENCRYPT);
+ set_key_size_aes(&desc[idx], CC_AES_128_BIT_KEY_SIZE);
+ set_flow_mode(&desc[idx], S_DIN_to_AES);
idx++;
*seq_size = idx;
}
-static void ssi_hash_create_cmac_setup(struct ahash_request *areq,
- HwDesc_s desc[],
+static void ssi_hash_create_cmac_setup(struct ahash_request *areq,
+ struct cc_hw_desc desc[],
unsigned int *seq_size)
{
unsigned int idx = *seq_size;
@@ -2608,24 +2431,26 @@ static void ssi_hash_create_cmac_setup(struct ahash_request *areq,
struct ssi_hash_ctx *ctx = crypto_ahash_ctx(tfm);
/* Setup CMAC Key */
- HW_DESC_INIT(&desc[idx]);
- HW_DESC_SET_DIN_TYPE(&desc[idx], DMA_DLLI, ctx->opad_tmp_keys_dma_addr,
- ((ctx->key_params.keylen == 24) ? AES_MAX_KEY_SIZE : ctx->key_params.keylen), NS_BIT);
- HW_DESC_SET_SETUP_MODE(&desc[idx], SETUP_LOAD_KEY0);
- HW_DESC_SET_CIPHER_MODE(&desc[idx], DRV_CIPHER_CMAC);
- HW_DESC_SET_CIPHER_CONFIG0(&desc[idx], DESC_DIRECTION_ENCRYPT_ENCRYPT);
- HW_DESC_SET_KEY_SIZE_AES(&desc[idx], ctx->key_params.keylen);
- HW_DESC_SET_FLOW_MODE(&desc[idx], S_DIN_to_AES);
+ hw_desc_init(&desc[idx]);
+ set_din_type(&desc[idx], DMA_DLLI, ctx->opad_tmp_keys_dma_addr,
+ ((ctx->key_params.keylen == 24) ? AES_MAX_KEY_SIZE :
+ ctx->key_params.keylen), NS_BIT);
+ set_setup_mode(&desc[idx], SETUP_LOAD_KEY0);
+ set_cipher_mode(&desc[idx], DRV_CIPHER_CMAC);
+ set_cipher_config0(&desc[idx], DESC_DIRECTION_ENCRYPT_ENCRYPT);
+ set_key_size_aes(&desc[idx], ctx->key_params.keylen);
+ set_flow_mode(&desc[idx], S_DIN_to_AES);
idx++;
/* Load MAC state */
- HW_DESC_INIT(&desc[idx]);
- HW_DESC_SET_DIN_TYPE(&desc[idx], DMA_DLLI, state->digest_buff_dma_addr, CC_AES_BLOCK_SIZE, NS_BIT);
- HW_DESC_SET_SETUP_MODE(&desc[idx], SETUP_LOAD_STATE0);
- HW_DESC_SET_CIPHER_MODE(&desc[idx], DRV_CIPHER_CMAC);
- HW_DESC_SET_CIPHER_CONFIG0(&desc[idx], DESC_DIRECTION_ENCRYPT_ENCRYPT);
- HW_DESC_SET_KEY_SIZE_AES(&desc[idx], ctx->key_params.keylen);
- HW_DESC_SET_FLOW_MODE(&desc[idx], S_DIN_to_AES);
+ hw_desc_init(&desc[idx]);
+ set_din_type(&desc[idx], DMA_DLLI, state->digest_buff_dma_addr,
+ CC_AES_BLOCK_SIZE, NS_BIT);
+ set_setup_mode(&desc[idx], SETUP_LOAD_STATE0);
+ set_cipher_mode(&desc[idx], DRV_CIPHER_CMAC);
+ set_cipher_config0(&desc[idx], DESC_DIRECTION_ENCRYPT_ENCRYPT);
+ set_key_size_aes(&desc[idx], ctx->key_params.keylen);
+ set_flow_mode(&desc[idx], S_DIN_to_AES);
idx++;
*seq_size = idx;
}
@@ -2633,18 +2458,18 @@ static void ssi_hash_create_cmac_setup(struct ahash_request *areq,
static void ssi_hash_create_data_desc(struct ahash_req_ctx *areq_ctx,
struct ssi_hash_ctx *ctx,
unsigned int flow_mode,
- HwDesc_s desc[],
- bool is_not_last_data,
+ struct cc_hw_desc desc[],
+ bool is_not_last_data,
unsigned int *seq_size)
{
unsigned int idx = *seq_size;
if (likely(areq_ctx->data_dma_buf_type == SSI_DMA_BUF_DLLI)) {
- HW_DESC_INIT(&desc[idx]);
- HW_DESC_SET_DIN_TYPE(&desc[idx], DMA_DLLI,
- sg_dma_address(areq_ctx->curr_sg),
- areq_ctx->curr_sg->length, NS_BIT);
- HW_DESC_SET_FLOW_MODE(&desc[idx], flow_mode);
+ hw_desc_init(&desc[idx]);
+ set_din_type(&desc[idx], DMA_DLLI,
+ sg_dma_address(areq_ctx->curr_sg),
+ areq_ctx->curr_sg->length, NS_BIT);
+ set_flow_mode(&desc[idx], flow_mode);
idx++;
} else {
if (areq_ctx->data_dma_buf_type == SSI_DMA_BUF_NULL) {
@@ -2653,42 +2478,38 @@ static void ssi_hash_create_data_desc(struct ahash_req_ctx *areq_ctx,
return;
}
/* bypass */
- HW_DESC_INIT(&desc[idx]);
- HW_DESC_SET_DIN_TYPE(&desc[idx], DMA_DLLI,
- areq_ctx->mlli_params.mlli_dma_addr,
- areq_ctx->mlli_params.mlli_len,
- NS_BIT);
- HW_DESC_SET_DOUT_SRAM(&desc[idx],
- ctx->drvdata->mlli_sram_addr,
- areq_ctx->mlli_params.mlli_len);
- HW_DESC_SET_FLOW_MODE(&desc[idx], BYPASS);
+ hw_desc_init(&desc[idx]);
+ set_din_type(&desc[idx], DMA_DLLI,
+ areq_ctx->mlli_params.mlli_dma_addr,
+ areq_ctx->mlli_params.mlli_len, NS_BIT);
+ set_dout_sram(&desc[idx], ctx->drvdata->mlli_sram_addr,
+ areq_ctx->mlli_params.mlli_len);
+ set_flow_mode(&desc[idx], BYPASS);
idx++;
/* process */
- HW_DESC_INIT(&desc[idx]);
- HW_DESC_SET_DIN_TYPE(&desc[idx], DMA_MLLI,
- ctx->drvdata->mlli_sram_addr,
- areq_ctx->mlli_nents,
- NS_BIT);
- HW_DESC_SET_FLOW_MODE(&desc[idx], flow_mode);
+ hw_desc_init(&desc[idx]);
+ set_din_type(&desc[idx], DMA_MLLI,
+ ctx->drvdata->mlli_sram_addr,
+ areq_ctx->mlli_nents, NS_BIT);
+ set_flow_mode(&desc[idx], flow_mode);
idx++;
}
- if (is_not_last_data) {
- HW_DESC_SET_DIN_NOT_LAST_INDICATION(&desc[idx-1]);
- }
+ if (is_not_last_data)
+ set_din_not_last_indication(&desc[(idx - 1)]);
/* return updated desc sequence size */
*seq_size = idx;
}
/*!
- * Gets the address of the initial digest in SRAM
+ * Gets the address of the initial digest in SRAM
* according to the given hash mode
- *
+ *
* \param drvdata
* \param mode The Hash mode. Supported modes: MD5/SHA1/SHA224/SHA256
- *
- * \return uint32_t The address of the inital digest in SRAM
+ *
+ * \return u32 The address of the inital digest in SRAM
*/
-ssi_sram_addr_t ssi_ahash_get_larval_digest_sram_addr(void *drvdata, uint32_t mode)
+ssi_sram_addr_t ssi_ahash_get_larval_digest_sram_addr(void *drvdata, u32 mode)
{
struct ssi_drvdata *_drvdata = (struct ssi_drvdata *)drvdata;
struct ssi_hash_handle *hash_handle = _drvdata->hash_handle;
@@ -2734,7 +2555,7 @@ ssi_sram_addr_t ssi_ahash_get_larval_digest_sram_addr(void *drvdata, uint32_t mo
}
ssi_sram_addr_t
-ssi_ahash_get_initial_digest_len_sram_addr(void *drvdata, uint32_t mode)
+ssi_ahash_get_initial_digest_len_sram_addr(void *drvdata, u32 mode)
{
struct ssi_drvdata *_drvdata = (struct ssi_drvdata *)drvdata;
struct ssi_hash_handle *hash_handle = _drvdata->hash_handle;
diff --git a/drivers/staging/ccree/ssi_hash.h b/drivers/staging/ccree/ssi_hash.h
index a2b076d3af72..2400e389d65a 100644
--- a/drivers/staging/ccree/ssi_hash.h
+++ b/drivers/staging/ccree/ssi_hash.h
@@ -1,21 +1,21 @@
/*
* Copyright (C) 2012-2017 ARM Limited or its affiliates.
- *
+ *
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
- *
+ *
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
- *
+ *
* You should have received a copy of the GNU General Public License
* along with this program; if not, see <http://www.gnu.org/licenses/>.
*/
/* \file ssi_hash.h
- ARM CryptoCell Hash Crypto API
+ * ARM CryptoCell Hash Crypto API
*/
#ifndef __SSI_HASH_H__
@@ -39,6 +39,8 @@
#define XCBC_MAC_K2_OFFSET 16
#define XCBC_MAC_K3_OFFSET 32
+#define CC_EXPORT_MAGIC 0xC2EE1070U
+
// this struct was taken from drivers/crypto/nx/nx-aes-xcbc.c and it is used for xcbc/cmac statesize
struct aeshash_state {
u8 state[AES_BLOCK_SIZE];
@@ -48,27 +50,27 @@ struct aeshash_state {
/* ahash state */
struct ahash_req_ctx {
- uint8_t* buff0;
- uint8_t* buff1;
- uint8_t* digest_result_buff;
+ u8 *buff0;
+ u8 *buff1;
+ u8 *digest_result_buff;
struct async_gen_req_ctx gen_ctx;
enum ssi_req_dma_buf_type data_dma_buf_type;
- uint8_t *digest_buff;
- uint8_t *opad_digest_buff;
- uint8_t *digest_bytes_len;
+ u8 *digest_buff;
+ u8 *opad_digest_buff;
+ u8 *digest_bytes_len;
dma_addr_t opad_digest_dma_addr;
dma_addr_t digest_buff_dma_addr;
dma_addr_t digest_bytes_len_dma_addr;
dma_addr_t digest_result_dma_addr;
- uint32_t buff0_cnt;
- uint32_t buff1_cnt;
- uint32_t buff_index;
- uint32_t xcbc_count; /* count xcbc update operatations */
+ u32 buff0_cnt;
+ u32 buff1_cnt;
+ u32 buff_index;
+ u32 xcbc_count; /* count xcbc update operatations */
struct scatterlist buff_sg[2];
struct scatterlist *curr_sg;
- uint32_t in_nents;
- uint32_t mlli_nents;
- struct mlli_params mlli_params;
+ u32 in_nents;
+ u32 mlli_nents;
+ struct mlli_params mlli_params;
};
int ssi_hash_alloc(struct ssi_drvdata *drvdata);
@@ -77,25 +79,25 @@ int ssi_hash_free(struct ssi_drvdata *drvdata);
/*!
* Gets the initial digest length
- *
- * \param drvdata
+ *
+ * \param drvdata
* \param mode The Hash mode. Supported modes: MD5/SHA1/SHA224/SHA256/SHA384/SHA512
- *
- * \return uint32_t returns the address of the initial digest length in SRAM
+ *
+ * \return u32 returns the address of the initial digest length in SRAM
*/
ssi_sram_addr_t
-ssi_ahash_get_initial_digest_len_sram_addr(void *drvdata, uint32_t mode);
+ssi_ahash_get_initial_digest_len_sram_addr(void *drvdata, u32 mode);
/*!
- * Gets the address of the initial digest in SRAM
+ * Gets the address of the initial digest in SRAM
* according to the given hash mode
- *
- * \param drvdata
+ *
+ * \param drvdata
* \param mode The Hash mode. Supported modes: MD5/SHA1/SHA224/SHA256/SHA384/SHA512
- *
- * \return uint32_t The address of the inital digest in SRAM
+ *
+ * \return u32 The address of the inital digest in SRAM
*/
-ssi_sram_addr_t ssi_ahash_get_larval_digest_sram_addr(void *drvdata, uint32_t mode);
+ssi_sram_addr_t ssi_ahash_get_larval_digest_sram_addr(void *drvdata, u32 mode);
#endif /*__SSI_HASH_H__*/
diff --git a/drivers/staging/ccree/ssi_ivgen.c b/drivers/staging/ccree/ssi_ivgen.c
index f16f4692f404..5ff3368c04d9 100644
--- a/drivers/staging/ccree/ssi_ivgen.c
+++ b/drivers/staging/ccree/ssi_ivgen.c
@@ -1,15 +1,15 @@
/*
* Copyright (C) 2012-2017 ARM Limited or its affiliates.
- *
+ *
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
- *
+ *
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
- *
+ *
* You should have received a copy of the GNU General Public License
* along with this program; if not, see <http://www.gnu.org/licenses/>.
*/
@@ -26,13 +26,14 @@
/* The max. size of pool *MUST* be <= SRAM total size */
#define SSI_IVPOOL_SIZE 1024
/* The first 32B fraction of pool are dedicated to the
- next encryption "key" & "IV" for pool regeneration */
+ * next encryption "key" & "IV" for pool regeneration
+ */
#define SSI_IVPOOL_META_SIZE (CC_AES_IV_SIZE + AES_KEYSIZE_128)
#define SSI_IVPOOL_GEN_SEQ_LEN 4
/**
- * struct ssi_ivgen_ctx -IV pool generation context
- * @pool: the start address of the iv-pool resides in internal RAM
+ * struct ssi_ivgen_ctx -IV pool generation context
+ * @pool: the start address of the iv-pool resides in internal RAM
* @ctr_key_dma: address of pool's encryption key material in internal RAM
* @ctr_iv_dma: address of pool's counter iv in internal RAM
* @next_iv_ofs: the offset to the next available IV in pool
@@ -43,62 +44,62 @@ struct ssi_ivgen_ctx {
ssi_sram_addr_t pool;
ssi_sram_addr_t ctr_key;
ssi_sram_addr_t ctr_iv;
- uint32_t next_iv_ofs;
- uint8_t *pool_meta;
+ u32 next_iv_ofs;
+ u8 *pool_meta;
dma_addr_t pool_meta_dma;
};
/*!
- * Generates SSI_IVPOOL_SIZE of random bytes by
+ * Generates SSI_IVPOOL_SIZE of random bytes by
* encrypting 0's using AES128-CTR.
- *
+ *
* \param ivgen iv-pool context
* \param iv_seq IN/OUT array to the descriptors sequence
- * \param iv_seq_len IN/OUT pointer to the sequence length
+ * \param iv_seq_len IN/OUT pointer to the sequence length
*/
static int ssi_ivgen_generate_pool(
struct ssi_ivgen_ctx *ivgen_ctx,
- HwDesc_s iv_seq[],
+ struct cc_hw_desc iv_seq[],
unsigned int *iv_seq_len)
{
unsigned int idx = *iv_seq_len;
- if ( (*iv_seq_len + SSI_IVPOOL_GEN_SEQ_LEN) > SSI_IVPOOL_SEQ_LEN) {
+ if ((*iv_seq_len + SSI_IVPOOL_GEN_SEQ_LEN) > SSI_IVPOOL_SEQ_LEN) {
/* The sequence will be longer than allowed */
return -EINVAL;
}
/* Setup key */
- HW_DESC_INIT(&iv_seq[idx]);
- HW_DESC_SET_DIN_SRAM(&iv_seq[idx], ivgen_ctx->ctr_key, AES_KEYSIZE_128);
- HW_DESC_SET_SETUP_MODE(&iv_seq[idx], SETUP_LOAD_KEY0);
- HW_DESC_SET_CIPHER_CONFIG0(&iv_seq[idx], DESC_DIRECTION_ENCRYPT_ENCRYPT);
- HW_DESC_SET_FLOW_MODE(&iv_seq[idx], S_DIN_to_AES);
- HW_DESC_SET_KEY_SIZE_AES(&iv_seq[idx], CC_AES_128_BIT_KEY_SIZE);
- HW_DESC_SET_CIPHER_MODE(&iv_seq[idx], DRV_CIPHER_CTR);
+ hw_desc_init(&iv_seq[idx]);
+ set_din_sram(&iv_seq[idx], ivgen_ctx->ctr_key, AES_KEYSIZE_128);
+ set_setup_mode(&iv_seq[idx], SETUP_LOAD_KEY0);
+ set_cipher_config0(&iv_seq[idx], DESC_DIRECTION_ENCRYPT_ENCRYPT);
+ set_flow_mode(&iv_seq[idx], S_DIN_to_AES);
+ set_key_size_aes(&iv_seq[idx], CC_AES_128_BIT_KEY_SIZE);
+ set_cipher_mode(&iv_seq[idx], DRV_CIPHER_CTR);
idx++;
/* Setup cipher state */
- HW_DESC_INIT(&iv_seq[idx]);
- HW_DESC_SET_DIN_SRAM(&iv_seq[idx], ivgen_ctx->ctr_iv, CC_AES_IV_SIZE);
- HW_DESC_SET_CIPHER_CONFIG0(&iv_seq[idx], DESC_DIRECTION_ENCRYPT_ENCRYPT);
- HW_DESC_SET_FLOW_MODE(&iv_seq[idx], S_DIN_to_AES);
- HW_DESC_SET_SETUP_MODE(&iv_seq[idx], SETUP_LOAD_STATE1);
- HW_DESC_SET_KEY_SIZE_AES(&iv_seq[idx], CC_AES_128_BIT_KEY_SIZE);
- HW_DESC_SET_CIPHER_MODE(&iv_seq[idx], DRV_CIPHER_CTR);
+ hw_desc_init(&iv_seq[idx]);
+ set_din_sram(&iv_seq[idx], ivgen_ctx->ctr_iv, CC_AES_IV_SIZE);
+ set_cipher_config0(&iv_seq[idx], DESC_DIRECTION_ENCRYPT_ENCRYPT);
+ set_flow_mode(&iv_seq[idx], S_DIN_to_AES);
+ set_setup_mode(&iv_seq[idx], SETUP_LOAD_STATE1);
+ set_key_size_aes(&iv_seq[idx], CC_AES_128_BIT_KEY_SIZE);
+ set_cipher_mode(&iv_seq[idx], DRV_CIPHER_CTR);
idx++;
/* Perform dummy encrypt to skip first block */
- HW_DESC_INIT(&iv_seq[idx]);
- HW_DESC_SET_DIN_CONST(&iv_seq[idx], 0, CC_AES_IV_SIZE);
- HW_DESC_SET_DOUT_SRAM(&iv_seq[idx], ivgen_ctx->pool, CC_AES_IV_SIZE);
- HW_DESC_SET_FLOW_MODE(&iv_seq[idx], DIN_AES_DOUT);
+ hw_desc_init(&iv_seq[idx]);
+ set_din_const(&iv_seq[idx], 0, CC_AES_IV_SIZE);
+ set_dout_sram(&iv_seq[idx], ivgen_ctx->pool, CC_AES_IV_SIZE);
+ set_flow_mode(&iv_seq[idx], DIN_AES_DOUT);
idx++;
/* Generate IV pool */
- HW_DESC_INIT(&iv_seq[idx]);
- HW_DESC_SET_DIN_CONST(&iv_seq[idx], 0, SSI_IVPOOL_SIZE);
- HW_DESC_SET_DOUT_SRAM(&iv_seq[idx], ivgen_ctx->pool, SSI_IVPOOL_SIZE);
- HW_DESC_SET_FLOW_MODE(&iv_seq[idx], DIN_AES_DOUT);
+ hw_desc_init(&iv_seq[idx]);
+ set_din_const(&iv_seq[idx], 0, SSI_IVPOOL_SIZE);
+ set_dout_sram(&iv_seq[idx], ivgen_ctx->pool, SSI_IVPOOL_SIZE);
+ set_flow_mode(&iv_seq[idx], DIN_AES_DOUT);
idx++;
*iv_seq_len = idx; /* Update sequence length */
@@ -110,17 +111,17 @@ static int ssi_ivgen_generate_pool(
}
/*!
- * Generates the initial pool in SRAM.
- * This function should be invoked when resuming DX driver.
- *
- * \param drvdata
- *
+ * Generates the initial pool in SRAM.
+ * This function should be invoked when resuming DX driver.
+ *
+ * \param drvdata
+ *
* \return int Zero for success, negative value otherwise.
*/
int ssi_ivgen_init_sram_pool(struct ssi_drvdata *drvdata)
{
struct ssi_ivgen_ctx *ivgen_ctx = drvdata->ivgen_handle;
- HwDesc_s iv_seq[SSI_IVPOOL_SEQ_LEN];
+ struct cc_hw_desc iv_seq[SSI_IVPOOL_SEQ_LEN];
unsigned int iv_seq_len = 0;
int rc;
@@ -132,40 +133,38 @@ int ssi_ivgen_init_sram_pool(struct ssi_drvdata *drvdata)
ivgen_ctx->ctr_iv = ivgen_ctx->pool + AES_KEYSIZE_128;
/* Copy initial enc. key and IV to SRAM at a single descriptor */
- HW_DESC_INIT(&iv_seq[iv_seq_len]);
- HW_DESC_SET_DIN_TYPE(&iv_seq[iv_seq_len], DMA_DLLI,
- ivgen_ctx->pool_meta_dma, SSI_IVPOOL_META_SIZE,
- NS_BIT);
- HW_DESC_SET_DOUT_SRAM(&iv_seq[iv_seq_len], ivgen_ctx->pool,
- SSI_IVPOOL_META_SIZE);
- HW_DESC_SET_FLOW_MODE(&iv_seq[iv_seq_len], BYPASS);
+ hw_desc_init(&iv_seq[iv_seq_len]);
+ set_din_type(&iv_seq[iv_seq_len], DMA_DLLI, ivgen_ctx->pool_meta_dma,
+ SSI_IVPOOL_META_SIZE, NS_BIT);
+ set_dout_sram(&iv_seq[iv_seq_len], ivgen_ctx->pool,
+ SSI_IVPOOL_META_SIZE);
+ set_flow_mode(&iv_seq[iv_seq_len], BYPASS);
iv_seq_len++;
/* Generate initial pool */
rc = ssi_ivgen_generate_pool(ivgen_ctx, iv_seq, &iv_seq_len);
- if (unlikely(rc != 0)) {
+ if (unlikely(rc != 0))
return rc;
- }
+
/* Fire-and-forget */
return send_request_init(drvdata, iv_seq, iv_seq_len);
}
/*!
* Free iv-pool and ivgen context.
- *
- * \param drvdata
+ *
+ * \param drvdata
*/
void ssi_ivgen_fini(struct ssi_drvdata *drvdata)
{
struct ssi_ivgen_ctx *ivgen_ctx = drvdata->ivgen_handle;
struct device *device = &(drvdata->plat_dev->dev);
- if (ivgen_ctx == NULL)
+ if (!ivgen_ctx)
return;
- if (ivgen_ctx->pool_meta != NULL) {
+ if (ivgen_ctx->pool_meta) {
memset(ivgen_ctx->pool_meta, 0, SSI_IVPOOL_META_SIZE);
- SSI_RESTORE_DMA_ADDR_TO_48BIT(ivgen_ctx->pool_meta_dma);
dma_free_coherent(device, SSI_IVPOOL_META_SIZE,
ivgen_ctx->pool_meta, ivgen_ctx->pool_meta_dma);
}
@@ -177,11 +176,11 @@ void ssi_ivgen_fini(struct ssi_drvdata *drvdata)
}
/*!
- * Allocates iv-pool and maps resources.
- * This function generates the first IV pool.
- *
+ * Allocates iv-pool and maps resources.
+ * This function generates the first IV pool.
+ *
* \param drvdata Driver's private context
- *
+ *
* \return int Zero for success, negative value otherwise.
*/
int ssi_ivgen_init(struct ssi_drvdata *drvdata)
@@ -209,8 +208,6 @@ int ssi_ivgen_init(struct ssi_drvdata *drvdata)
rc = -ENOMEM;
goto out;
}
- SSI_UPDATE_DMA_ADDR_TO_48BIT(ivgen_ctx->pool_meta_dma,
- SSI_IVPOOL_META_SIZE);
/* Allocate IV pool in SRAM */
ivgen_ctx->pool = ssi_sram_mgr_alloc(drvdata, SSI_IVPOOL_SIZE);
if (ivgen_ctx->pool == NULL_SRAM_ADDR) {
@@ -228,22 +225,22 @@ out:
/*!
* Acquires 16 Bytes IV from the iv-pool
- *
+ *
* \param drvdata Driver private context
* \param iv_out_dma Array of physical IV out addresses
* \param iv_out_dma_len Length of iv_out_dma array (additional elements of iv_out_dma array are ignore)
- * \param iv_out_size May be 8 or 16 bytes long
+ * \param iv_out_size May be 8 or 16 bytes long
* \param iv_seq IN/OUT array to the descriptors sequence
- * \param iv_seq_len IN/OUT pointer to the sequence length
- *
- * \return int Zero for success, negative value otherwise.
+ * \param iv_seq_len IN/OUT pointer to the sequence length
+ *
+ * \return int Zero for success, negative value otherwise.
*/
int ssi_ivgen_getiv(
struct ssi_drvdata *drvdata,
dma_addr_t iv_out_dma[],
unsigned int iv_out_dma_len,
unsigned int iv_out_size,
- HwDesc_s iv_seq[],
+ struct cc_hw_desc iv_seq[],
unsigned int *iv_seq_len)
{
struct ssi_ivgen_ctx *ivgen_ctx = drvdata->ivgen_handle;
@@ -254,34 +251,35 @@ int ssi_ivgen_getiv(
(iv_out_size != CTR_RFC3686_IV_SIZE)) {
return -EINVAL;
}
- if ( (iv_out_dma_len + 1) > SSI_IVPOOL_SEQ_LEN) {
+ if ((iv_out_dma_len + 1) > SSI_IVPOOL_SEQ_LEN) {
/* The sequence will be longer than allowed */
return -EINVAL;
}
//check that number of generated IV is limited to max dma address iv buffer size
- if ( iv_out_dma_len > SSI_MAX_IVGEN_DMA_ADDRESSES) {
+ if (iv_out_dma_len > SSI_MAX_IVGEN_DMA_ADDRESSES) {
/* The sequence will be longer than allowed */
return -EINVAL;
}
for (t = 0; t < iv_out_dma_len; t++) {
/* Acquire IV from pool */
- HW_DESC_INIT(&iv_seq[idx]);
- HW_DESC_SET_DIN_SRAM(&iv_seq[idx],
- ivgen_ctx->pool + ivgen_ctx->next_iv_ofs,
- iv_out_size);
- HW_DESC_SET_DOUT_DLLI(&iv_seq[idx], iv_out_dma[t],
- iv_out_size, NS_BIT, 0);
- HW_DESC_SET_FLOW_MODE(&iv_seq[idx], BYPASS);
+ hw_desc_init(&iv_seq[idx]);
+ set_din_sram(&iv_seq[idx], (ivgen_ctx->pool +
+ ivgen_ctx->next_iv_ofs),
+ iv_out_size);
+ set_dout_dlli(&iv_seq[idx], iv_out_dma[t], iv_out_size,
+ NS_BIT, 0);
+ set_flow_mode(&iv_seq[idx], BYPASS);
idx++;
}
/* Bypass operation is proceeded by crypto sequence, hence must
- * assure bypass-write-transaction by a memory barrier */
- HW_DESC_INIT(&iv_seq[idx]);
- HW_DESC_SET_DIN_NO_DMA(&iv_seq[idx], 0, 0xfffff0);
- HW_DESC_SET_DOUT_NO_DMA(&iv_seq[idx], 0, 0, 1);
+ * assure bypass-write-transaction by a memory barrier
+ */
+ hw_desc_init(&iv_seq[idx]);
+ set_din_no_dma(&iv_seq[idx], 0, 0xfffff0);
+ set_dout_no_dma(&iv_seq[idx], 0, 0, 1);
idx++;
*iv_seq_len = idx; /* update seq length */
@@ -298,4 +296,3 @@ int ssi_ivgen_getiv(
return 0;
}
-
diff --git a/drivers/staging/ccree/ssi_ivgen.h b/drivers/staging/ccree/ssi_ivgen.h
index bc69cd8ca418..961aea411cb3 100644
--- a/drivers/staging/ccree/ssi_ivgen.h
+++ b/drivers/staging/ccree/ssi_ivgen.h
@@ -1,15 +1,15 @@
/*
* Copyright (C) 2012-2017 ARM Limited or its affiliates.
- *
+ *
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
- *
+ *
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
- *
+ *
* You should have received a copy of the GNU General Public License
* along with this program; if not, see <http://www.gnu.org/licenses/>.
*/
@@ -19,54 +19,53 @@
#include "cc_hw_queue_defs.h"
-
#define SSI_IVPOOL_SEQ_LEN 8
/*!
- * Allocates iv-pool and maps resources.
- * This function generates the first IV pool.
- *
+ * Allocates iv-pool and maps resources.
+ * This function generates the first IV pool.
+ *
* \param drvdata Driver's private context
- *
+ *
* \return int Zero for success, negative value otherwise.
*/
int ssi_ivgen_init(struct ssi_drvdata *drvdata);
/*!
* Free iv-pool and ivgen context.
- *
- * \param drvdata
+ *
+ * \param drvdata
*/
void ssi_ivgen_fini(struct ssi_drvdata *drvdata);
/*!
- * Generates the initial pool in SRAM.
- * This function should be invoked when resuming DX driver.
- *
- * \param drvdata
- *
+ * Generates the initial pool in SRAM.
+ * This function should be invoked when resuming DX driver.
+ *
+ * \param drvdata
+ *
* \return int Zero for success, negative value otherwise.
*/
int ssi_ivgen_init_sram_pool(struct ssi_drvdata *drvdata);
/*!
* Acquires 16 Bytes IV from the iv-pool
- *
+ *
* \param drvdata Driver private context
* \param iv_out_dma Array of physical IV out addresses
* \param iv_out_dma_len Length of iv_out_dma array (additional elements of iv_out_dma array are ignore)
- * \param iv_out_size May be 8 or 16 bytes long
+ * \param iv_out_size May be 8 or 16 bytes long
* \param iv_seq IN/OUT array to the descriptors sequence
- * \param iv_seq_len IN/OUT pointer to the sequence length
- *
- * \return int Zero for success, negative value otherwise.
+ * \param iv_seq_len IN/OUT pointer to the sequence length
+ *
+ * \return int Zero for success, negative value otherwise.
*/
int ssi_ivgen_getiv(
struct ssi_drvdata *drvdata,
dma_addr_t iv_out_dma[],
unsigned int iv_out_dma_len,
unsigned int iv_out_size,
- HwDesc_s iv_seq[],
+ struct cc_hw_desc iv_seq[],
unsigned int *iv_seq_len);
#endif /*__SSI_IVGEN_H__*/
diff --git a/drivers/staging/ccree/ssi_pm.c b/drivers/staging/ccree/ssi_pm.c
index dd399f28a68c..52a8ed579177 100644
--- a/drivers/staging/ccree/ssi_pm.c
+++ b/drivers/staging/ccree/ssi_pm.c
@@ -1,20 +1,19 @@
/*
* Copyright (C) 2012-2017 ARM Limited or its affiliates.
- *
+ *
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
- *
+ *
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
- *
+ *
* You should have received a copy of the GNU General Public License
* along with this program; if not, see <http://www.gnu.org/licenses/>.
*/
-
#include "ssi_config.h"
#include <linux/kernel.h>
#include <linux/platform_device.h>
@@ -29,15 +28,12 @@
#include "ssi_ivgen.h"
#include "ssi_hash.h"
#include "ssi_pm.h"
-#include "ssi_pm_ext.h"
-
-#if defined (CONFIG_PM_RUNTIME) || defined (CONFIG_PM_SLEEP)
+#if defined(CONFIG_PM_RUNTIME) || defined(CONFIG_PM_SLEEP)
#define POWER_DOWN_ENABLE 0x01
#define POWER_DOWN_DISABLE 0x00
-
int ssi_power_mgr_runtime_suspend(struct device *dev)
{
struct ssi_drvdata *drvdata =
@@ -52,9 +48,7 @@ int ssi_power_mgr_runtime_suspend(struct device *dev)
return rc;
}
fini_cc_regs(drvdata);
-
- /* Specific HW suspend code */
- ssi_pm_ext_hw_suspend(dev);
+ cc_clk_off(drvdata);
return 0;
}
@@ -66,24 +60,28 @@ int ssi_power_mgr_runtime_resume(struct device *dev)
SSI_LOG_DEBUG("ssi_power_mgr_runtime_resume , unset HOST_POWER_DOWN_EN\n");
WRITE_REGISTER(drvdata->cc_base + CC_REG_OFFSET(HOST_RGF, HOST_POWER_DOWN_EN), POWER_DOWN_DISABLE);
- /* Specific HW resume code */
- ssi_pm_ext_hw_resume(dev);
+
+ rc = cc_clk_on(drvdata);
+ if (rc) {
+ SSI_LOG_ERR("failed getting clock back on. We're toast.\n");
+ return rc;
+ }
rc = init_cc_regs(drvdata, false);
- if (rc !=0) {
- SSI_LOG_ERR("init_cc_regs (%x)\n",rc);
+ if (rc != 0) {
+ SSI_LOG_ERR("init_cc_regs (%x)\n", rc);
return rc;
}
rc = ssi_request_mgr_runtime_resume_queue(drvdata);
- if (rc !=0) {
- SSI_LOG_ERR("ssi_request_mgr_runtime_resume_queue (%x)\n",rc);
+ if (rc != 0) {
+ SSI_LOG_ERR("ssi_request_mgr_runtime_resume_queue (%x)\n", rc);
return rc;
}
/* must be after the queue resuming as it uses the HW queue*/
ssi_hash_init_sram_digest_consts(drvdata);
-
+
ssi_ivgen_init_sram_pool(drvdata);
return 0;
}
@@ -109,26 +107,22 @@ int ssi_power_mgr_runtime_put_suspend(struct device *dev)
(struct ssi_drvdata *)dev_get_drvdata(dev))) {
pm_runtime_mark_last_busy(dev);
rc = pm_runtime_put_autosuspend(dev);
- }
- else {
+ } else {
/* Something wrong happens*/
BUG();
}
return rc;
-
}
#endif
-
-
int ssi_power_mgr_init(struct ssi_drvdata *drvdata)
{
int rc = 0;
-#if defined (CONFIG_PM_RUNTIME) || defined (CONFIG_PM_SLEEP)
+#if defined(CONFIG_PM_RUNTIME) || defined(CONFIG_PM_SLEEP)
struct platform_device *plat_dev = drvdata->plat_dev;
/* must be before the enabling to avoid resdundent suspending */
- pm_runtime_set_autosuspend_delay(&plat_dev->dev,SSI_SUSPEND_TIMEOUT);
+ pm_runtime_set_autosuspend_delay(&plat_dev->dev, SSI_SUSPEND_TIMEOUT);
pm_runtime_use_autosuspend(&plat_dev->dev);
/* activate the PM module */
rc = pm_runtime_set_active(&plat_dev->dev);
@@ -142,7 +136,7 @@ int ssi_power_mgr_init(struct ssi_drvdata *drvdata)
void ssi_power_mgr_fini(struct ssi_drvdata *drvdata)
{
-#if defined (CONFIG_PM_RUNTIME) || defined (CONFIG_PM_SLEEP)
+#if defined(CONFIG_PM_RUNTIME) || defined(CONFIG_PM_SLEEP)
struct platform_device *plat_dev = drvdata->plat_dev;
pm_runtime_disable(&plat_dev->dev);
diff --git a/drivers/staging/ccree/ssi_pm.h b/drivers/staging/ccree/ssi_pm.h
index 516fc3f445a8..63673f60d2d8 100644
--- a/drivers/staging/ccree/ssi_pm.h
+++ b/drivers/staging/ccree/ssi_pm.h
@@ -1,38 +1,35 @@
/*
* Copyright (C) 2012-2017 ARM Limited or its affiliates.
- *
+ *
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
- *
+ *
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
- *
+ *
* You should have received a copy of the GNU General Public License
* along with this program; if not, see <http://www.gnu.org/licenses/>.
*/
/* \file ssi_pm.h
- */
+ */
#ifndef __SSI_POWER_MGR_H__
#define __SSI_POWER_MGR_H__
-
#include "ssi_config.h"
#include "ssi_driver.h"
-
#define SSI_SUSPEND_TIMEOUT 3000
-
int ssi_power_mgr_init(struct ssi_drvdata *drvdata);
void ssi_power_mgr_fini(struct ssi_drvdata *drvdata);
-#if defined (CONFIG_PM_RUNTIME) || defined (CONFIG_PM_SLEEP)
+#if defined(CONFIG_PM_RUNTIME) || defined(CONFIG_PM_SLEEP)
int ssi_power_mgr_runtime_suspend(struct device *dev);
int ssi_power_mgr_runtime_resume(struct device *dev);
diff --git a/drivers/staging/ccree/ssi_pm_ext.c b/drivers/staging/ccree/ssi_pm_ext.c
deleted file mode 100644
index f86bbab22073..000000000000
--- a/drivers/staging/ccree/ssi_pm_ext.c
+++ /dev/null
@@ -1,60 +0,0 @@
-/*
- * Copyright (C) 2012-2017 ARM Limited or its affiliates.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, see <http://www.gnu.org/licenses/>.
- */
-
-
-#include "ssi_config.h"
-#include <linux/kernel.h>
-#include <linux/platform_device.h>
-#include <linux/interrupt.h>
-#include <crypto/ctr.h>
-#include <linux/pm_runtime.h>
-#include "ssi_driver.h"
-#include "ssi_sram_mgr.h"
-#include "ssi_pm_ext.h"
-
-/*
-This function should suspend the HW (if possiable), It should be implemented by
-the driver user.
-The reference code clears the internal SRAM to imitate lose of state.
-*/
-void ssi_pm_ext_hw_suspend(struct device *dev)
-{
- struct ssi_drvdata *drvdata =
- (struct ssi_drvdata *)dev_get_drvdata(dev);
- unsigned int val;
- void __iomem *cc_base = drvdata->cc_base;
- unsigned int sram_addr = 0;
-
- CC_HAL_WRITE_REGISTER(CC_REG_OFFSET(HOST_RGF, SRAM_ADDR), sram_addr);
-
- for (;sram_addr < SSI_CC_SRAM_SIZE ; sram_addr+=4) {
- CC_HAL_WRITE_REGISTER(CC_REG_OFFSET(HOST_RGF, SRAM_DATA), 0x0);
-
- do {
- val = CC_HAL_READ_REGISTER(CC_REG_OFFSET(HOST_RGF, SRAM_DATA_READY));
- } while (!(val &0x1));
- }
-}
-
-/*
-This function should resume the HW (if possiable).It should be implemented by
-the driver user.
-*/
-void ssi_pm_ext_hw_resume(struct device *dev)
-{
- return;
-}
-
diff --git a/drivers/staging/ccree/ssi_pm_ext.h b/drivers/staging/ccree/ssi_pm_ext.h
deleted file mode 100644
index b4e2795de29e..000000000000
--- a/drivers/staging/ccree/ssi_pm_ext.h
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- * Copyright (C) 2012-2017 ARM Limited or its affiliates.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, see <http://www.gnu.org/licenses/>.
- */
-
-/* \file ssi_pm_ext.h
- */
-
-#ifndef __PM_EXT_H__
-#define __PM_EXT_H__
-
-
-#include "ssi_config.h"
-#include "ssi_driver.h"
-
-void ssi_pm_ext_hw_suspend(struct device *dev);
-
-void ssi_pm_ext_hw_resume(struct device *dev);
-
-
-#endif /*__POWER_MGR_H__*/
-
diff --git a/drivers/staging/ccree/ssi_request_mgr.c b/drivers/staging/ccree/ssi_request_mgr.c
index 8611adf3bb2e..46d9396f9ff9 100644
--- a/drivers/staging/ccree/ssi_request_mgr.c
+++ b/drivers/staging/ccree/ssi_request_mgr.c
@@ -1,15 +1,15 @@
/*
* Copyright (C) 2012-2017 ARM Limited or its affiliates.
- *
+ *
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
- *
+ *
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
- *
+ *
* You should have received a copy of the GNU General Public License
* along with this program; if not, see <http://www.gnu.org/licenses/>.
*/
@@ -35,91 +35,22 @@
#define SSI_MAX_POLL_ITER 10
-#define AXIM_MON_BASE_OFFSET CC_REG_OFFSET(CRY_KERNEL, AXIM_MON_COMP)
-
-#ifdef CC_CYCLE_COUNT
-
-#define MONITOR_CNTR_BIT 0
-
-/**
- * Monitor descriptor.
- * Used to measure CC performance.
- */
-#define INIT_CC_MONITOR_DESC(desc_p) \
-do { \
- HW_DESC_INIT(desc_p); \
- HW_DESC_SET_DIN_MONITOR_CNTR(desc_p); \
-} while (0)
-
-/**
- * Try adding monitor descriptor BEFORE enqueuing sequence.
- */
-#define CC_CYCLE_DESC_HEAD(cc_base_addr, desc_p, lock_p, is_monitored_p) \
-do { \
- if (!test_and_set_bit(MONITOR_CNTR_BIT, (lock_p))) { \
- enqueue_seq((cc_base_addr), (desc_p), 1); \
- *(is_monitored_p) = true; \
- } else { \
- *(is_monitored_p) = false; \
- } \
-} while (0)
-
-/**
- * If CC_CYCLE_DESC_HEAD was successfully added:
- * 1. Add memory barrier descriptor to ensure last AXI transaction.
- * 2. Add monitor descriptor to sequence tail AFTER enqueuing sequence.
- */
-#define CC_CYCLE_DESC_TAIL(cc_base_addr, desc_p, is_monitored) \
-do { \
- if ((is_monitored) == true) { \
- HwDesc_s barrier_desc; \
- HW_DESC_INIT(&barrier_desc); \
- HW_DESC_SET_DIN_NO_DMA(&barrier_desc, 0, 0xfffff0); \
- HW_DESC_SET_DOUT_NO_DMA(&barrier_desc, 0, 0, 1); \
- enqueue_seq((cc_base_addr), &barrier_desc, 1); \
- enqueue_seq((cc_base_addr), (desc_p), 1); \
- } \
-} while (0)
-
-/**
- * Try reading CC monitor counter value upon sequence complete.
- * Can only succeed if the lock_p is taken by the owner of the given request.
- */
-#define END_CC_MONITOR_COUNT(cc_base_addr, stat_op_type, stat_phase, monitor_null_cycles, lock_p, is_monitored) \
-do { \
- uint32_t elapsed_cycles; \
- if ((is_monitored) == true) { \
- elapsed_cycles = READ_REGISTER((cc_base_addr) + CC_REG_OFFSET(CRY_KERNEL, DSCRPTR_MEASURE_CNTR)); \
- clear_bit(MONITOR_CNTR_BIT, (lock_p)); \
- if (elapsed_cycles > 0) \
- update_cc_stat(stat_op_type, stat_phase, (elapsed_cycles - monitor_null_cycles)); \
- } \
-} while (0)
-
-#else /*CC_CYCLE_COUNT*/
-
-#define INIT_CC_MONITOR_DESC(desc_p) do { } while (0)
-#define CC_CYCLE_DESC_HEAD(cc_base_addr, desc_p, lock_p, is_monitored_p) do { } while (0)
-#define CC_CYCLE_DESC_TAIL(cc_base_addr, desc_p, is_monitored) do { } while (0)
-#define END_CC_MONITOR_COUNT(cc_base_addr, stat_op_type, stat_phase, monitor_null_cycles, lock_p, is_monitored) do { } while (0)
-#endif /*CC_CYCLE_COUNT*/
-
-
struct ssi_request_mgr_handle {
/* Request manager resources */
unsigned int hw_queue_size; /* HW capability */
unsigned int min_free_hw_slots;
unsigned int max_used_sw_slots;
struct ssi_crypto_req req_queue[MAX_REQUEST_QUEUE_SIZE];
- uint32_t req_queue_head;
- uint32_t req_queue_tail;
- uint32_t axi_completed;
- uint32_t q_free_slots;
+ u32 req_queue_head;
+ u32 req_queue_tail;
+ u32 axi_completed;
+ u32 q_free_slots;
spinlock_t hw_lock;
- HwDesc_s compl_desc;
- uint8_t *dummy_comp_buff;
+ struct cc_hw_desc compl_desc;
+ u8 *dummy_comp_buff;
dma_addr_t dummy_comp_buff_dma;
- HwDesc_s monitor_desc;
+ struct cc_hw_desc monitor_desc;
+
volatile unsigned long monitor_lock;
#ifdef COMP_IN_WQ
struct workqueue_struct *workq;
@@ -127,7 +58,7 @@ struct ssi_request_mgr_handle {
#else
struct tasklet_struct comptask;
#endif
-#if defined (CONFIG_PM_RUNTIME) || defined (CONFIG_PM_SLEEP)
+#if defined(CONFIG_PM_RUNTIME) || defined(CONFIG_PM_SLEEP)
bool is_runtime_suspended;
#endif
};
@@ -141,18 +72,17 @@ void request_mgr_fini(struct ssi_drvdata *drvdata)
{
struct ssi_request_mgr_handle *req_mgr_h = drvdata->request_mgr_handle;
- if (req_mgr_h == NULL)
+ if (!req_mgr_h)
return; /* Not allocated */
if (req_mgr_h->dummy_comp_buff_dma != 0) {
- SSI_RESTORE_DMA_ADDR_TO_48BIT(req_mgr_h->dummy_comp_buff_dma);
dma_free_coherent(&drvdata->plat_dev->dev,
- sizeof(uint32_t), req_mgr_h->dummy_comp_buff,
+ sizeof(u32), req_mgr_h->dummy_comp_buff,
req_mgr_h->dummy_comp_buff_dma);
}
SSI_LOG_DEBUG("max_used_hw_slots=%d\n", (req_mgr_h->hw_queue_size -
- req_mgr_h->min_free_hw_slots) );
+ req_mgr_h->min_free_hw_slots));
SSI_LOG_DEBUG("max_used_sw_slots=%d\n", req_mgr_h->max_used_sw_slots);
#ifdef COMP_IN_WQ
@@ -169,15 +99,11 @@ void request_mgr_fini(struct ssi_drvdata *drvdata)
int request_mgr_init(struct ssi_drvdata *drvdata)
{
-#ifdef CC_CYCLE_COUNT
- HwDesc_s monitor_desc[2];
- struct ssi_crypto_req monitor_req = {0};
-#endif
struct ssi_request_mgr_handle *req_mgr_h;
int rc = 0;
- req_mgr_h = kzalloc(sizeof(struct ssi_request_mgr_handle),GFP_KERNEL);
- if (req_mgr_h == NULL) {
+ req_mgr_h = kzalloc(sizeof(struct ssi_request_mgr_handle), GFP_KERNEL);
+ if (!req_mgr_h) {
rc = -ENOMEM;
goto req_mgr_init_err;
}
@@ -188,7 +114,7 @@ int request_mgr_init(struct ssi_drvdata *drvdata)
#ifdef COMP_IN_WQ
SSI_LOG_DEBUG("Initializing completion workqueue\n");
req_mgr_h->workq = create_singlethread_workqueue("arm_cc7x_wq");
- if (unlikely(req_mgr_h->workq == NULL)) {
+ if (unlikely(!req_mgr_h->workq)) {
SSI_LOG_ERR("Failed creating work queue\n");
rc = -ENOMEM;
goto req_mgr_init_err;
@@ -210,45 +136,23 @@ int request_mgr_init(struct ssi_drvdata *drvdata)
req_mgr_h->min_free_hw_slots = req_mgr_h->hw_queue_size;
req_mgr_h->max_used_sw_slots = 0;
-
/* Allocate DMA word for "dummy" completion descriptor use */
req_mgr_h->dummy_comp_buff = dma_alloc_coherent(&drvdata->plat_dev->dev,
- sizeof(uint32_t), &req_mgr_h->dummy_comp_buff_dma, GFP_KERNEL);
+ sizeof(u32), &req_mgr_h->dummy_comp_buff_dma, GFP_KERNEL);
if (!req_mgr_h->dummy_comp_buff) {
SSI_LOG_ERR("Not enough memory to allocate DMA (%zu) dropped "
- "buffer\n", sizeof(uint32_t));
+ "buffer\n", sizeof(u32));
rc = -ENOMEM;
goto req_mgr_init_err;
}
- SSI_UPDATE_DMA_ADDR_TO_48BIT(req_mgr_h->dummy_comp_buff_dma,
- sizeof(uint32_t));
/* Init. "dummy" completion descriptor */
- HW_DESC_INIT(&req_mgr_h->compl_desc);
- HW_DESC_SET_DIN_CONST(&req_mgr_h->compl_desc, 0, sizeof(uint32_t));
- HW_DESC_SET_DOUT_DLLI(&req_mgr_h->compl_desc,
- req_mgr_h->dummy_comp_buff_dma,
- sizeof(uint32_t), NS_BIT, 1);
- HW_DESC_SET_FLOW_MODE(&req_mgr_h->compl_desc, BYPASS);
- HW_DESC_SET_QUEUE_LAST_IND(&req_mgr_h->compl_desc);
-
-#ifdef CC_CYCLE_COUNT
- /* For CC-HW cycle performance trace */
- INIT_CC_MONITOR_DESC(&req_mgr_h->monitor_desc);
- set_bit(MONITOR_CNTR_BIT, &req_mgr_h->monitor_lock);
- monitor_desc[0] = req_mgr_h->monitor_desc;
- monitor_desc[1] = req_mgr_h->monitor_desc;
-
- rc = send_request(drvdata, &monitor_req, monitor_desc, 2, 0);
- if (unlikely(rc != 0))
- goto req_mgr_init_err;
-
- drvdata->monitor_null_cycles = READ_REGISTER(drvdata->cc_base +
- CC_REG_OFFSET(CRY_KERNEL, DSCRPTR_MEASURE_CNTR));
- SSI_LOG_ERR("Calibration time=0x%08x\n", drvdata->monitor_null_cycles);
-
- clear_bit(MONITOR_CNTR_BIT, &req_mgr_h->monitor_lock);
-#endif
+ hw_desc_init(&req_mgr_h->compl_desc);
+ set_din_const(&req_mgr_h->compl_desc, 0, sizeof(u32));
+ set_dout_dlli(&req_mgr_h->compl_desc, req_mgr_h->dummy_comp_buff_dma,
+ sizeof(u32), NS_BIT, 1);
+ set_flow_mode(&req_mgr_h->compl_desc, BYPASS);
+ set_queue_last_ind(&req_mgr_h->compl_desc);
return 0;
@@ -259,18 +163,18 @@ req_mgr_init_err:
static inline void enqueue_seq(
void __iomem *cc_base,
- HwDesc_s seq[], unsigned int seq_len)
+ struct cc_hw_desc seq[], unsigned int seq_len)
{
int i;
for (i = 0; i < seq_len; i++) {
- writel_relaxed(seq[i].word[0], (volatile void __iomem *)(cc_base+CC_REG_OFFSET(CRY_KERNEL, DSCRPTR_QUEUE_WORD0)));
- writel_relaxed(seq[i].word[1], (volatile void __iomem *)(cc_base+CC_REG_OFFSET(CRY_KERNEL, DSCRPTR_QUEUE_WORD0)));
- writel_relaxed(seq[i].word[2], (volatile void __iomem *)(cc_base+CC_REG_OFFSET(CRY_KERNEL, DSCRPTR_QUEUE_WORD0)));
- writel_relaxed(seq[i].word[3], (volatile void __iomem *)(cc_base+CC_REG_OFFSET(CRY_KERNEL, DSCRPTR_QUEUE_WORD0)));
- writel_relaxed(seq[i].word[4], (volatile void __iomem *)(cc_base+CC_REG_OFFSET(CRY_KERNEL, DSCRPTR_QUEUE_WORD0)));
+ writel_relaxed(seq[i].word[0], (volatile void __iomem *)(cc_base + CC_REG_OFFSET(CRY_KERNEL, DSCRPTR_QUEUE_WORD0)));
+ writel_relaxed(seq[i].word[1], (volatile void __iomem *)(cc_base + CC_REG_OFFSET(CRY_KERNEL, DSCRPTR_QUEUE_WORD0)));
+ writel_relaxed(seq[i].word[2], (volatile void __iomem *)(cc_base + CC_REG_OFFSET(CRY_KERNEL, DSCRPTR_QUEUE_WORD0)));
+ writel_relaxed(seq[i].word[3], (volatile void __iomem *)(cc_base + CC_REG_OFFSET(CRY_KERNEL, DSCRPTR_QUEUE_WORD0)));
+ writel_relaxed(seq[i].word[4], (volatile void __iomem *)(cc_base + CC_REG_OFFSET(CRY_KERNEL, DSCRPTR_QUEUE_WORD0)));
wmb();
- writel_relaxed(seq[i].word[5], (volatile void __iomem *)(cc_base+CC_REG_OFFSET(CRY_KERNEL, DSCRPTR_QUEUE_WORD0)));
+ writel_relaxed(seq[i].word[5], (volatile void __iomem *)(cc_base + CC_REG_OFFSET(CRY_KERNEL, DSCRPTR_QUEUE_WORD0)));
#ifdef DX_DUMP_DESCS
SSI_LOG_DEBUG("desc[%02d]: 0x%08X 0x%08X 0x%08X 0x%08X 0x%08X 0x%08X\n", i,
seq[i].word[0], seq[i].word[1], seq[i].word[2], seq[i].word[3], seq[i].word[4], seq[i].word[5]);
@@ -279,62 +183,63 @@ static inline void enqueue_seq(
}
/*!
- * Completion will take place if and only if user requested completion
- * by setting "is_dout = 0" in send_request().
- *
- * \param dev
+ * Completion will take place if and only if user requested completion
+ * by setting "is_dout = 0" in send_request().
+ *
+ * \param dev
* \param dx_compl_h The completion event to signal
*/
static void request_mgr_complete(struct device *dev, void *dx_compl_h, void __iomem *cc_base)
{
struct completion *this_compl = dx_compl_h;
+
complete(this_compl);
}
-
static inline int request_mgr_queues_status_check(
struct ssi_request_mgr_handle *req_mgr_h,
void __iomem *cc_base,
unsigned int total_seq_len)
{
unsigned long poll_queue;
-
- /* SW queue is checked only once as it will not
- be chaned during the poll becasue the spinlock_bh
- is held by the thread */
+
+ /* SW queue is checked only once as it will not
+ * be chaned during the poll becasue the spinlock_bh
+ * is held by the thread
+ */
if (unlikely(((req_mgr_h->req_queue_head + 1) &
- (MAX_REQUEST_QUEUE_SIZE - 1)) ==
+ (MAX_REQUEST_QUEUE_SIZE - 1)) ==
req_mgr_h->req_queue_tail)) {
- SSI_LOG_ERR("SW FIFO is full. req_queue_head=%d sw_fifo_len=%d\n",
+ SSI_LOG_ERR("SW FIFO is full. req_queue_head=%d sw_fifo_len=%d\n",
req_mgr_h->req_queue_head, MAX_REQUEST_QUEUE_SIZE);
return -EBUSY;
}
- if ((likely(req_mgr_h->q_free_slots >= total_seq_len)) ) {
+ if ((likely(req_mgr_h->q_free_slots >= total_seq_len)))
return 0;
- }
+
/* Wait for space in HW queue. Poll constant num of iterations. */
- for (poll_queue =0; poll_queue < SSI_MAX_POLL_ITER ; poll_queue ++) {
- req_mgr_h->q_free_slots =
+ for (poll_queue = 0; poll_queue < SSI_MAX_POLL_ITER ; poll_queue++) {
+ req_mgr_h->q_free_slots =
CC_HAL_READ_REGISTER(
CC_REG_OFFSET(CRY_KERNEL,
DSCRPTR_QUEUE_CONTENT));
- if (unlikely(req_mgr_h->q_free_slots <
+ if (unlikely(req_mgr_h->q_free_slots <
req_mgr_h->min_free_hw_slots)) {
req_mgr_h->min_free_hw_slots = req_mgr_h->q_free_slots;
}
- if (likely (req_mgr_h->q_free_slots >= total_seq_len)) {
+ if (likely(req_mgr_h->q_free_slots >= total_seq_len)) {
/* If there is enough place return */
return 0;
}
- SSI_LOG_DEBUG("HW FIFO is full. q_free_slots=%d total_seq_len=%d\n",
+ SSI_LOG_DEBUG("HW FIFO is full. q_free_slots=%d total_seq_len=%d\n",
req_mgr_h->q_free_slots, total_seq_len);
}
/* No room in the HW queue try again later */
SSI_LOG_DEBUG("HW FIFO full, timeout. req_queue_head=%d "
- "sw_fifo_len=%d q_free_slots=%d total_seq_len=%d\n",
+ "sw_fifo_len=%d q_free_slots=%d total_seq_len=%d\n",
req_mgr_h->req_queue_head,
MAX_REQUEST_QUEUE_SIZE,
req_mgr_h->q_free_slots,
@@ -344,38 +249,37 @@ static inline int request_mgr_queues_status_check(
/*!
* Enqueue caller request to crypto hardware.
- *
- * \param drvdata
+ *
+ * \param drvdata
* \param ssi_req The request to enqueue
* \param desc The crypto sequence
* \param len The crypto sequence length
- * \param is_dout If "true": completion is handled by the caller
- * If "false": this function adds a dummy descriptor completion
- * and waits upon completion signal.
- *
+ * \param is_dout If "true": completion is handled by the caller
+ * If "false": this function adds a dummy descriptor completion
+ * and waits upon completion signal.
+ *
* \return int Returns -EINPROGRESS if "is_dout=true"; "0" if "is_dout=false"
*/
int send_request(
struct ssi_drvdata *drvdata, struct ssi_crypto_req *ssi_req,
- HwDesc_s *desc, unsigned int len, bool is_dout)
+ struct cc_hw_desc *desc, unsigned int len, bool is_dout)
{
void __iomem *cc_base = drvdata->cc_base;
struct ssi_request_mgr_handle *req_mgr_h = drvdata->request_mgr_handle;
unsigned int used_sw_slots;
unsigned int iv_seq_len = 0;
unsigned int total_seq_len = len; /*initial sequence length*/
- HwDesc_s iv_seq[SSI_IVPOOL_SEQ_LEN];
+ struct cc_hw_desc iv_seq[SSI_IVPOOL_SEQ_LEN];
int rc;
unsigned int max_required_seq_len = (total_seq_len +
((ssi_req->ivgen_dma_addr_len == 0) ? 0 :
- SSI_IVPOOL_SEQ_LEN ) +
- ((is_dout == 0 )? 1 : 0));
- DECL_CYCLE_COUNT_RESOURCES;
+ SSI_IVPOOL_SEQ_LEN) +
+ ((is_dout == 0) ? 1 : 0));
-#if defined (CONFIG_PM_RUNTIME) || defined (CONFIG_PM_SLEEP)
+#if defined(CONFIG_PM_RUNTIME) || defined(CONFIG_PM_SLEEP)
rc = ssi_power_mgr_runtime_get(&drvdata->plat_dev->dev);
if (rc != 0) {
- SSI_LOG_ERR("ssi_power_mgr_runtime_get returned %x\n",rc);
+ SSI_LOG_ERR("ssi_power_mgr_runtime_get returned %x\n", rc);
return rc;
}
#endif
@@ -384,21 +288,23 @@ int send_request(
spin_lock_bh(&req_mgr_h->hw_lock);
/* Check if there is enough place in the SW/HW queues
- in case iv gen add the max size and in case of no dout add 1
- for the internal completion descriptor */
+ * in case iv gen add the max size and in case of no dout add 1
+ * for the internal completion descriptor
+ */
rc = request_mgr_queues_status_check(req_mgr_h,
cc_base,
max_required_seq_len);
- if (likely(rc == 0 ))
+ if (likely(rc == 0))
/* There is enough place in the queue */
break;
/* something wrong release the spinlock*/
spin_unlock_bh(&req_mgr_h->hw_lock);
if (rc != -EAGAIN) {
- /* Any error other than HW queue full
- (SW queue is full) */
-#if defined (CONFIG_PM_RUNTIME) || defined (CONFIG_PM_SLEEP)
+ /* Any error other than HW queue full
+ * (SW queue is full)
+ */
+#if defined(CONFIG_PM_RUNTIME) || defined(CONFIG_PM_SLEEP)
ssi_power_mgr_runtime_put_suspend(&drvdata->plat_dev->dev);
#endif
return rc;
@@ -409,7 +315,8 @@ int send_request(
} while (1);
/* Additional completion descriptor is needed incase caller did not
- enabled any DLLI/MLLI DOUT bit in the given sequence */
+ * enabled any DLLI/MLLI DOUT bit in the given sequence
+ */
if (!is_dout) {
init_completion(&ssi_req->seq_compl);
ssi_req->user_cb = request_mgr_complete;
@@ -432,7 +339,7 @@ int send_request(
if (unlikely(rc != 0)) {
SSI_LOG_ERR("Failed to generate IV (rc=%d)\n", rc);
spin_unlock_bh(&req_mgr_h->hw_lock);
-#if defined (CONFIG_PM_RUNTIME) || defined (CONFIG_PM_SLEEP)
+#if defined(CONFIG_PM_RUNTIME) || defined(CONFIG_PM_SLEEP)
ssi_power_mgr_runtime_put_suspend(&drvdata->plat_dev->dev);
#endif
return rc;
@@ -440,18 +347,13 @@ int send_request(
total_seq_len += iv_seq_len;
}
-
- used_sw_slots = ((req_mgr_h->req_queue_head - req_mgr_h->req_queue_tail) & (MAX_REQUEST_QUEUE_SIZE-1));
- if (unlikely(used_sw_slots > req_mgr_h->max_used_sw_slots)) {
+
+ used_sw_slots = ((req_mgr_h->req_queue_head - req_mgr_h->req_queue_tail) & (MAX_REQUEST_QUEUE_SIZE - 1));
+ if (unlikely(used_sw_slots > req_mgr_h->max_used_sw_slots))
req_mgr_h->max_used_sw_slots = used_sw_slots;
- }
-
- CC_CYCLE_DESC_HEAD(cc_base, &req_mgr_h->monitor_desc,
- &req_mgr_h->monitor_lock, &ssi_req->is_monitored_p);
/* Enqueue request - must be locked with HW lock*/
req_mgr_h->req_queue[req_mgr_h->req_queue_head] = *ssi_req;
- START_CYCLE_COUNT_AT(req_mgr_h->req_queue[req_mgr_h->req_queue_head].submit_cycle);
req_mgr_h->req_queue_head = (req_mgr_h->req_queue_head + 1) & (MAX_REQUEST_QUEUE_SIZE - 1);
/* TODO: Use circ_buf.h ? */
@@ -462,13 +364,9 @@ int send_request(
#endif
/* STAT_PHASE_4: Push sequence */
- START_CYCLE_COUNT();
enqueue_seq(cc_base, iv_seq, iv_seq_len);
enqueue_seq(cc_base, desc, len);
enqueue_seq(cc_base, &req_mgr_h->compl_desc, (is_dout ? 0 : 1));
- END_CYCLE_COUNT(ssi_req->op_type, STAT_PHASE_4);
-
- CC_CYCLE_DESC_TAIL(cc_base, &req_mgr_h->monitor_desc, ssi_req->is_monitored_p);
if (unlikely(req_mgr_h->q_free_slots < total_seq_len)) {
/*This means that there was a problem with the resume*/
@@ -481,28 +379,29 @@ int send_request(
if (!is_dout) {
/* Wait upon sequence completion.
- * Return "0" -Operation done successfully. */
- return wait_for_completion_interruptible(&ssi_req->seq_compl);
+ * Return "0" -Operation done successfully.
+ */
+ wait_for_completion(&ssi_req->seq_compl);
+ return 0;
} else {
/* Operation still in process */
return -EINPROGRESS;
}
}
-
/*!
* Enqueue caller request to crypto hardware during init process.
* assume this function is not called in middle of a flow,
* since we set QUEUE_LAST_IND flag in the last descriptor.
- *
- * \param drvdata
+ *
+ * \param drvdata
* \param desc The crypto sequence
* \param len The crypto sequence length
- *
+ *
* \return int Returns "0" upon success
*/
int send_request_init(
- struct ssi_drvdata *drvdata, HwDesc_s *desc, unsigned int len)
+ struct ssi_drvdata *drvdata, struct cc_hw_desc *desc, unsigned int len)
{
void __iomem *cc_base = drvdata->cc_base;
struct ssi_request_mgr_handle *req_mgr_h = drvdata->request_mgr_handle;
@@ -511,10 +410,10 @@ int send_request_init(
/* Wait for space in HW and SW FIFO. Poll for as much as FIFO_TIMEOUT. */
rc = request_mgr_queues_status_check(req_mgr_h, cc_base, total_seq_len);
- if (unlikely(rc != 0 )) {
+ if (unlikely(rc != 0))
return rc;
- }
- HW_DESC_SET_QUEUE_LAST_IND(&desc[len-1]);
+
+ set_queue_last_ind(&desc[(len - 1)]);
enqueue_seq(cc_base, desc, len);
@@ -526,10 +425,9 @@ int send_request_init(
return 0;
}
-
void complete_request(struct ssi_drvdata *drvdata)
{
- struct ssi_request_mgr_handle *request_mgr_handle =
+ struct ssi_request_mgr_handle *request_mgr_handle =
drvdata->request_mgr_handle;
#ifdef COMP_IN_WQ
queue_delayed_work(request_mgr_handle->workq, &request_mgr_handle->compwork, 0);
@@ -552,14 +450,13 @@ static void proc_completions(struct ssi_drvdata *drvdata)
{
struct ssi_crypto_req *ssi_req;
struct platform_device *plat_dev = drvdata->plat_dev;
- struct ssi_request_mgr_handle * request_mgr_handle =
+ struct ssi_request_mgr_handle *request_mgr_handle =
drvdata->request_mgr_handle;
-#if defined (CONFIG_PM_RUNTIME) || defined (CONFIG_PM_SLEEP)
+#if defined(CONFIG_PM_RUNTIME) || defined(CONFIG_PM_SLEEP)
int rc = 0;
#endif
- DECL_CYCLE_COUNT_RESOURCES;
- while(request_mgr_handle->axi_completed) {
+ while (request_mgr_handle->axi_completed) {
request_mgr_handle->axi_completed--;
/* Dequeue request */
@@ -569,9 +466,6 @@ static void proc_completions(struct ssi_drvdata *drvdata)
}
ssi_req = &request_mgr_handle->req_queue[request_mgr_handle->req_queue_tail];
- END_CYCLE_COUNT_AT(ssi_req->submit_cycle, ssi_req->op_type, STAT_PHASE_5); /* Seq. Comp. */
- END_CC_MONITOR_COUNT(drvdata->cc_base, ssi_req->op_type, STAT_PHASE_6,
- drvdata->monitor_null_cycles, &request_mgr_handle->monitor_lock, ssi_req->is_monitored_p);
#ifdef FLUSH_CACHE_ALL
flush_cache_all();
@@ -580,116 +474,109 @@ static void proc_completions(struct ssi_drvdata *drvdata)
#ifdef COMPLETION_DELAY
/* Delay */
{
- uint32_t axi_err;
+ u32 axi_err;
int i;
+
SSI_LOG_INFO("Delay\n");
- for (i=0;i<1000000;i++) {
+ for (i = 0; i < 1000000; i++)
axi_err = READ_REGISTER(drvdata->cc_base + CC_REG_OFFSET(CRY_KERNEL, AXIM_MON_ERR));
- }
}
#endif /* COMPLETION_DELAY */
- if (likely(ssi_req->user_cb != NULL)) {
- START_CYCLE_COUNT();
+ if (likely(ssi_req->user_cb))
ssi_req->user_cb(&plat_dev->dev, ssi_req->user_arg, drvdata->cc_base);
- END_CYCLE_COUNT(STAT_OP_TYPE_GENERIC, STAT_PHASE_3);
- }
request_mgr_handle->req_queue_tail = (request_mgr_handle->req_queue_tail + 1) & (MAX_REQUEST_QUEUE_SIZE - 1);
SSI_LOG_DEBUG("Dequeue request tail=%u\n", request_mgr_handle->req_queue_tail);
SSI_LOG_DEBUG("Request completed. axi_completed=%d\n", request_mgr_handle->axi_completed);
-#if defined (CONFIG_PM_RUNTIME) || defined (CONFIG_PM_SLEEP)
+#if defined(CONFIG_PM_RUNTIME) || defined(CONFIG_PM_SLEEP)
rc = ssi_power_mgr_runtime_put_suspend(&plat_dev->dev);
- if (rc != 0) {
- SSI_LOG_ERR("Failed to set runtime suspension %d\n",rc);
- }
+ if (rc != 0)
+ SSI_LOG_ERR("Failed to set runtime suspension %d\n", rc);
#endif
}
}
+static inline u32 cc_axi_comp_count(void __iomem *cc_base)
+{
+ /* The CC_HAL_READ_REGISTER macro implictly requires and uses
+ * a base MMIO register address variable named cc_base.
+ */
+ return FIELD_GET(AXIM_MON_COMP_VALUE,
+ CC_HAL_READ_REGISTER(AXIM_MON_BASE_OFFSET));
+}
+
/* Deferred service handler, run as interrupt-fired tasklet */
static void comp_handler(unsigned long devarg)
{
struct ssi_drvdata *drvdata = (struct ssi_drvdata *)devarg;
void __iomem *cc_base = drvdata->cc_base;
- struct ssi_request_mgr_handle * request_mgr_handle =
+ struct ssi_request_mgr_handle *request_mgr_handle =
drvdata->request_mgr_handle;
- uint32_t irq;
-
- DECL_CYCLE_COUNT_RESOURCES;
-
- START_CYCLE_COUNT();
+ u32 irq;
irq = (drvdata->irq & SSI_COMP_IRQ_MASK);
if (irq & SSI_COMP_IRQ_MASK) {
/* To avoid the interrupt from firing as we unmask it, we clear it now */
CC_HAL_WRITE_REGISTER(CC_REG_OFFSET(HOST_RGF, HOST_ICR), SSI_COMP_IRQ_MASK);
-
+
/* Avoid race with above clear: Test completion counter once more */
- request_mgr_handle->axi_completed += CC_REG_FLD_GET(CRY_KERNEL, AXIM_MON_COMP, VALUE,
- CC_HAL_READ_REGISTER(AXIM_MON_BASE_OFFSET));
-
- /* ISR-to-Tasklet latency */
- if (request_mgr_handle->axi_completed) {
- /* Only if actually reflects ISR-to-completion-handling latency, i.e.,
- not duplicate as a result of interrupt after AXIM_MON_ERR clear, before end of loop */
- END_CYCLE_COUNT_AT(drvdata->isr_exit_cycles, STAT_OP_TYPE_GENERIC, STAT_PHASE_1);
- }
-
+ request_mgr_handle->axi_completed +=
+ cc_axi_comp_count(cc_base);
+
while (request_mgr_handle->axi_completed) {
do {
proc_completions(drvdata);
- /* At this point (after proc_completions()), request_mgr_handle->axi_completed is always 0.
- The following assignment was changed to = (previously was +=) to conform KW restrictions. */
- request_mgr_handle->axi_completed = CC_REG_FLD_GET(CRY_KERNEL, AXIM_MON_COMP, VALUE,
- CC_HAL_READ_REGISTER(AXIM_MON_BASE_OFFSET));
+ /* At this point (after proc_completions()),
+ * request_mgr_handle->axi_completed is 0.
+ */
+ request_mgr_handle->axi_completed =
+ cc_axi_comp_count(cc_base);
} while (request_mgr_handle->axi_completed > 0);
-
+
/* To avoid the interrupt from firing as we unmask it, we clear it now */
CC_HAL_WRITE_REGISTER(CC_REG_OFFSET(HOST_RGF, HOST_ICR), SSI_COMP_IRQ_MASK);
-
+
/* Avoid race with above clear: Test completion counter once more */
- request_mgr_handle->axi_completed += CC_REG_FLD_GET(CRY_KERNEL, AXIM_MON_COMP, VALUE,
- CC_HAL_READ_REGISTER(AXIM_MON_BASE_OFFSET));
+ request_mgr_handle->axi_completed +=
+ cc_axi_comp_count(cc_base);
}
-
}
/* after verifing that there is nothing to do, Unmask AXI completion interrupt */
- CC_HAL_WRITE_REGISTER(CC_REG_OFFSET(HOST_RGF, HOST_IMR),
+ CC_HAL_WRITE_REGISTER(CC_REG_OFFSET(HOST_RGF, HOST_IMR),
CC_HAL_READ_REGISTER(
CC_REG_OFFSET(HOST_RGF, HOST_IMR)) & ~irq);
- END_CYCLE_COUNT(STAT_OP_TYPE_GENERIC, STAT_PHASE_2);
}
/*
-resume the queue configuration - no need to take the lock as this happens inside
-the spin lock protection
-*/
-#if defined (CONFIG_PM_RUNTIME) || defined (CONFIG_PM_SLEEP)
+ * resume the queue configuration - no need to take the lock as this happens inside
+ * the spin lock protection
+ */
+#if defined(CONFIG_PM_RUNTIME) || defined(CONFIG_PM_SLEEP)
int ssi_request_mgr_runtime_resume_queue(struct ssi_drvdata *drvdata)
{
- struct ssi_request_mgr_handle * request_mgr_handle = drvdata->request_mgr_handle;
+ struct ssi_request_mgr_handle *request_mgr_handle = drvdata->request_mgr_handle;
spin_lock_bh(&request_mgr_handle->hw_lock);
request_mgr_handle->is_runtime_suspended = false;
spin_unlock_bh(&request_mgr_handle->hw_lock);
- return 0 ;
+ return 0;
}
/*
-suspend the queue configuration. Since it is used for the runtime suspend
-only verify that the queue can be suspended.
-*/
+ * suspend the queue configuration. Since it is used for the runtime suspend
+ * only verify that the queue can be suspended.
+ */
int ssi_request_mgr_runtime_suspend_queue(struct ssi_drvdata *drvdata)
{
- struct ssi_request_mgr_handle * request_mgr_handle =
+ struct ssi_request_mgr_handle *request_mgr_handle =
drvdata->request_mgr_handle;
-
+
/* lock the send_request */
spin_lock_bh(&request_mgr_handle->hw_lock);
- if (request_mgr_handle->req_queue_head !=
+ if (request_mgr_handle->req_queue_head !=
request_mgr_handle->req_queue_tail) {
spin_unlock_bh(&request_mgr_handle->hw_lock);
return -EBUSY;
@@ -702,10 +589,10 @@ int ssi_request_mgr_runtime_suspend_queue(struct ssi_drvdata *drvdata)
bool ssi_request_mgr_is_queue_runtime_suspend(struct ssi_drvdata *drvdata)
{
- struct ssi_request_mgr_handle * request_mgr_handle =
+ struct ssi_request_mgr_handle *request_mgr_handle =
drvdata->request_mgr_handle;
- return request_mgr_handle->is_runtime_suspended;
+ return request_mgr_handle->is_runtime_suspended;
}
#endif
diff --git a/drivers/staging/ccree/ssi_request_mgr.h b/drivers/staging/ccree/ssi_request_mgr.h
index c09339b566d0..bdbbf89e5367 100644
--- a/drivers/staging/ccree/ssi_request_mgr.h
+++ b/drivers/staging/ccree/ssi_request_mgr.h
@@ -1,21 +1,21 @@
/*
* Copyright (C) 2012-2017 ARM Limited or its affiliates.
- *
+ *
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
- *
+ *
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
- *
+ *
* You should have received a copy of the GNU General Public License
* along with this program; if not, see <http://www.gnu.org/licenses/>.
*/
/* \file request_mgr.h
- Request Manager
+ * Request Manager
*/
#ifndef __REQUEST_MGR_H__
@@ -27,29 +27,29 @@ int request_mgr_init(struct ssi_drvdata *drvdata);
/*!
* Enqueue caller request to crypto hardware.
- *
- * \param drvdata
+ *
+ * \param drvdata
* \param ssi_req The request to enqueue
* \param desc The crypto sequence
* \param len The crypto sequence length
- * \param is_dout If "true": completion is handled by the caller
- * If "false": this function adds a dummy descriptor completion
- * and waits upon completion signal.
- *
+ * \param is_dout If "true": completion is handled by the caller
+ * If "false": this function adds a dummy descriptor completion
+ * and waits upon completion signal.
+ *
* \return int Returns -EINPROGRESS if "is_dout=ture"; "0" if "is_dout=false"
*/
int send_request(
struct ssi_drvdata *drvdata, struct ssi_crypto_req *ssi_req,
- HwDesc_s *desc, unsigned int len, bool is_dout);
+ struct cc_hw_desc *desc, unsigned int len, bool is_dout);
int send_request_init(
- struct ssi_drvdata *drvdata, HwDesc_s *desc, unsigned int len);
+ struct ssi_drvdata *drvdata, struct cc_hw_desc *desc, unsigned int len);
void complete_request(struct ssi_drvdata *drvdata);
void request_mgr_fini(struct ssi_drvdata *drvdata);
-#if defined (CONFIG_PM_RUNTIME) || defined (CONFIG_PM_SLEEP)
+#if defined(CONFIG_PM_RUNTIME) || defined(CONFIG_PM_SLEEP)
int ssi_request_mgr_runtime_resume_queue(struct ssi_drvdata *drvdata);
int ssi_request_mgr_runtime_suspend_queue(struct ssi_drvdata *drvdata);
diff --git a/drivers/staging/ccree/ssi_sram_mgr.c b/drivers/staging/ccree/ssi_sram_mgr.c
index 50066e17d1d3..e05c0c13c2eb 100644
--- a/drivers/staging/ccree/ssi_sram_mgr.c
+++ b/drivers/staging/ccree/ssi_sram_mgr.c
@@ -1,15 +1,15 @@
/*
* Copyright (C) 2012-2017 ARM Limited or its affiliates.
- *
+ *
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
- *
+ *
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
- *
+ *
* You should have received a copy of the GNU General Public License
* along with this program; if not, see <http://www.gnu.org/licenses/>.
*/
@@ -17,7 +17,6 @@
#include "ssi_driver.h"
#include "ssi_sram_mgr.h"
-
/**
* struct ssi_sram_mgr_ctx -Internal RAM context manager
* @sram_free_offset: the offset to the non-allocated area
@@ -26,10 +25,9 @@ struct ssi_sram_mgr_ctx {
ssi_sram_addr_t sram_free_offset;
};
-
/**
* ssi_sram_mgr_fini() - Cleanup SRAM pool.
- *
+ *
* @drvdata: Associated device driver context
*/
void ssi_sram_mgr_fini(struct ssi_drvdata *drvdata)
@@ -37,17 +35,17 @@ void ssi_sram_mgr_fini(struct ssi_drvdata *drvdata)
struct ssi_sram_mgr_ctx *smgr_ctx = drvdata->sram_mgr_handle;
/* Free "this" context */
- if (smgr_ctx != NULL) {
+ if (smgr_ctx) {
memset(smgr_ctx, 0, sizeof(struct ssi_sram_mgr_ctx));
kfree(smgr_ctx);
}
}
/**
- * ssi_sram_mgr_init() - Initializes SRAM pool.
+ * ssi_sram_mgr_init() - Initializes SRAM pool.
* The pool starts right at the beginning of SRAM.
* Returns zero for success, negative value otherwise.
- *
+ *
* @drvdata: Associated device driver context
*/
int ssi_sram_mgr_init(struct ssi_drvdata *drvdata)
@@ -77,15 +75,15 @@ out:
}
/*!
- * Allocated buffer from SRAM pool.
- * Note: Caller is responsible to free the LAST allocated buffer.
- * This function does not taking care of any fragmentation may occur
- * by the order of calls to alloc/free.
- *
- * \param drvdata
+ * Allocated buffer from SRAM pool.
+ * Note: Caller is responsible to free the LAST allocated buffer.
+ * This function does not taking care of any fragmentation may occur
+ * by the order of calls to alloc/free.
+ *
+ * \param drvdata
* \param size The requested bytes to allocate
*/
-ssi_sram_addr_t ssi_sram_mgr_alloc(struct ssi_drvdata *drvdata, uint32_t size)
+ssi_sram_addr_t ssi_sram_mgr_alloc(struct ssi_drvdata *drvdata, u32 size)
{
struct ssi_sram_mgr_ctx *smgr_ctx = drvdata->sram_mgr_handle;
ssi_sram_addr_t p;
@@ -100,7 +98,7 @@ ssi_sram_addr_t ssi_sram_mgr_alloc(struct ssi_drvdata *drvdata, uint32_t size)
size, smgr_ctx->sram_free_offset);
return NULL_SRAM_ADDR;
}
-
+
p = smgr_ctx->sram_free_offset;
smgr_ctx->sram_free_offset += size;
SSI_LOG_DEBUG("Allocated %u B @ %u\n", size, (unsigned int)p);
@@ -109,9 +107,9 @@ ssi_sram_addr_t ssi_sram_mgr_alloc(struct ssi_drvdata *drvdata, uint32_t size)
/**
* ssi_sram_mgr_const2sram_desc() - Create const descriptors sequence to
- * set values in given array into SRAM.
+ * set values in given array into SRAM.
* Note: each const value can't exceed word size.
- *
+ *
* @src: A pointer to array of words to set as consts.
* @dst: The target SRAM buffer to set into
* @nelements: The number of words in "src" array
@@ -119,18 +117,18 @@ ssi_sram_addr_t ssi_sram_mgr_alloc(struct ssi_drvdata *drvdata, uint32_t size)
* @seq_len: A pointer to the given IN/OUT sequence length
*/
void ssi_sram_mgr_const2sram_desc(
- const uint32_t *src, ssi_sram_addr_t dst,
+ const u32 *src, ssi_sram_addr_t dst,
unsigned int nelement,
- HwDesc_s *seq, unsigned int *seq_len)
+ struct cc_hw_desc *seq, unsigned int *seq_len)
{
- uint32_t i;
+ u32 i;
unsigned int idx = *seq_len;
for (i = 0; i < nelement; i++, idx++) {
- HW_DESC_INIT(&seq[idx]);
- HW_DESC_SET_DIN_CONST(&seq[idx], src[i], sizeof(uint32_t));
- HW_DESC_SET_DOUT_SRAM(&seq[idx], dst + (i * sizeof(uint32_t)), sizeof(uint32_t));
- HW_DESC_SET_FLOW_MODE(&seq[idx], BYPASS);
+ hw_desc_init(&seq[idx]);
+ set_din_const(&seq[idx], src[i], sizeof(u32));
+ set_dout_sram(&seq[idx], dst + (i * sizeof(u32)), sizeof(u32));
+ set_flow_mode(&seq[idx], BYPASS);
}
*seq_len = idx;
diff --git a/drivers/staging/ccree/ssi_sram_mgr.h b/drivers/staging/ccree/ssi_sram_mgr.h
index d71fbaf9ac44..9ba1d59a0bae 100644
--- a/drivers/staging/ccree/ssi_sram_mgr.h
+++ b/drivers/staging/ccree/ssi_sram_mgr.h
@@ -1,15 +1,15 @@
/*
* Copyright (C) 2012-2017 ARM Limited or its affiliates.
- *
+ *
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
- *
+ *
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
- *
+ *
* You should have received a copy of the GNU General Public License
* along with this program; if not, see <http://www.gnu.org/licenses/>.
*/
@@ -17,7 +17,6 @@
#ifndef __SSI_SRAM_MGR_H__
#define __SSI_SRAM_MGR_H__
-
#ifndef SSI_CC_SRAM_SIZE
#define SSI_CC_SRAM_SIZE 4096
#endif
@@ -28,44 +27,44 @@ struct ssi_drvdata;
* Address (offset) within CC internal SRAM
*/
-typedef uint64_t ssi_sram_addr_t;
+typedef u64 ssi_sram_addr_t;
#define NULL_SRAM_ADDR ((ssi_sram_addr_t)-1)
/*!
- * Initializes SRAM pool.
- * The first X bytes of SRAM are reserved for ROM usage, hence, pool
- * starts right after X bytes.
- *
- * \param drvdata
- *
+ * Initializes SRAM pool.
+ * The first X bytes of SRAM are reserved for ROM usage, hence, pool
+ * starts right after X bytes.
+ *
+ * \param drvdata
+ *
* \return int Zero for success, negative value otherwise.
*/
int ssi_sram_mgr_init(struct ssi_drvdata *drvdata);
/*!
* Uninits SRAM pool.
- *
- * \param drvdata
+ *
+ * \param drvdata
*/
void ssi_sram_mgr_fini(struct ssi_drvdata *drvdata);
/*!
- * Allocated buffer from SRAM pool.
- * Note: Caller is responsible to free the LAST allocated buffer.
- * This function does not taking care of any fragmentation may occur
- * by the order of calls to alloc/free.
- *
- * \param drvdata
+ * Allocated buffer from SRAM pool.
+ * Note: Caller is responsible to free the LAST allocated buffer.
+ * This function does not taking care of any fragmentation may occur
+ * by the order of calls to alloc/free.
+ *
+ * \param drvdata
* \param size The requested bytes to allocate
*/
-ssi_sram_addr_t ssi_sram_mgr_alloc(struct ssi_drvdata *drvdata, uint32_t size);
+ssi_sram_addr_t ssi_sram_mgr_alloc(struct ssi_drvdata *drvdata, u32 size);
/**
* ssi_sram_mgr_const2sram_desc() - Create const descriptors sequence to
- * set values in given array into SRAM.
+ * set values in given array into SRAM.
* Note: each const value can't exceed word size.
- *
+ *
* @src: A pointer to array of words to set as consts.
* @dst: The target SRAM buffer to set into
* @nelements: The number of words in "src" array
@@ -73,8 +72,8 @@ ssi_sram_addr_t ssi_sram_mgr_alloc(struct ssi_drvdata *drvdata, uint32_t size);
* @seq_len: A pointer to the given IN/OUT sequence length
*/
void ssi_sram_mgr_const2sram_desc(
- const uint32_t *src, ssi_sram_addr_t dst,
+ const u32 *src, ssi_sram_addr_t dst,
unsigned int nelement,
- HwDesc_s *seq, unsigned int *seq_len);
+ struct cc_hw_desc *seq, unsigned int *seq_len);
#endif /*__SSI_SRAM_MGR_H__*/
diff --git a/drivers/staging/ccree/ssi_sysfs.c b/drivers/staging/ccree/ssi_sysfs.c
index 7c514c1072a9..dbcd1634aad1 100644
--- a/drivers/staging/ccree/ssi_sysfs.c
+++ b/drivers/staging/ccree/ssi_sysfs.c
@@ -1,15 +1,15 @@
/*
* Copyright (C) 2012-2017 ARM Limited or its affiliates.
- *
+ *
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
- *
+ *
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
- *
+ *
* You should have received a copy of the GNU General Public License
* along with this program; if not, see <http://www.gnu.org/licenses/>.
*/
@@ -40,7 +40,7 @@ struct stat_name {
const char *stat_phase_name[MAX_STAT_PHASES];
};
-static struct stat_name stat_name_db[MAX_STAT_OP_TYPES] =
+static struct stat_name stat_name_db[MAX_STAT_OP_TYPES] =
{
{
/* STAT_OP_TYPE_NULL */
@@ -50,8 +50,8 @@ static struct stat_name stat_name_db[MAX_STAT_OP_TYPES] =
{
.op_type_name = "Encode",
.stat_phase_name[STAT_PHASE_0] = "Init and sanity checks",
- .stat_phase_name[STAT_PHASE_1] = "Map buffers",
- .stat_phase_name[STAT_PHASE_2] = "Create sequence",
+ .stat_phase_name[STAT_PHASE_1] = "Map buffers",
+ .stat_phase_name[STAT_PHASE_2] = "Create sequence",
.stat_phase_name[STAT_PHASE_3] = "Send Request",
.stat_phase_name[STAT_PHASE_4] = "HW-Q push",
.stat_phase_name[STAT_PHASE_5] = "Sequence completion",
@@ -59,14 +59,14 @@ static struct stat_name stat_name_db[MAX_STAT_OP_TYPES] =
},
{ .op_type_name = "Decode",
.stat_phase_name[STAT_PHASE_0] = "Init and sanity checks",
- .stat_phase_name[STAT_PHASE_1] = "Map buffers",
- .stat_phase_name[STAT_PHASE_2] = "Create sequence",
+ .stat_phase_name[STAT_PHASE_1] = "Map buffers",
+ .stat_phase_name[STAT_PHASE_2] = "Create sequence",
.stat_phase_name[STAT_PHASE_3] = "Send Request",
.stat_phase_name[STAT_PHASE_4] = "HW-Q push",
.stat_phase_name[STAT_PHASE_5] = "Sequence completion",
.stat_phase_name[STAT_PHASE_6] = "HW cycles",
},
- { .op_type_name = "Setkey",
+ { .op_type_name = "Setkey",
.stat_phase_name[STAT_PHASE_0] = "Init and sanity checks",
.stat_phase_name[STAT_PHASE_1] = "Copy key to ctx",
.stat_phase_name[STAT_PHASE_2] = "Create sequence",
@@ -88,14 +88,14 @@ static struct stat_name stat_name_db[MAX_STAT_OP_TYPES] =
};
/*
- * Structure used to create a directory
+ * Structure used to create a directory
* and its attributes in sysfs.
*/
struct sys_dir {
struct kobject *sys_dir_kobj;
struct attribute_group sys_dir_attr_group;
struct attribute **sys_dir_attr_list;
- uint32_t num_of_attrs;
+ u32 num_of_attrs;
struct ssi_drvdata *drvdata; /* Associated driver context */
};
@@ -108,14 +108,13 @@ static DEFINE_SPINLOCK(stat_lock);
static struct stat_item stat_host_db[MAX_STAT_OP_TYPES][MAX_STAT_PHASES];
static struct stat_item stat_cc_db[MAX_STAT_OP_TYPES][MAX_STAT_PHASES];
-
static void init_db(struct stat_item item[MAX_STAT_OP_TYPES][MAX_STAT_PHASES])
{
unsigned int i, j;
/* Clear db */
- for (i=0; i<MAX_STAT_OP_TYPES; i++) {
- for (j=0; j<MAX_STAT_PHASES; j++) {
+ for (i = 0; i < MAX_STAT_OP_TYPES; i++) {
+ for (j = 0; j < MAX_STAT_PHASES; j++) {
item[i][j].min = 0xFFFFFFFF;
item[i][j].max = 0;
item[i][j].sum = 0;
@@ -130,29 +129,28 @@ static void update_db(struct stat_item *item, unsigned int result)
item->sum += result;
if (result < item->min)
item->min = result;
- if (result > item->max )
+ if (result > item->max)
item->max = result;
}
static void display_db(struct stat_item item[MAX_STAT_OP_TYPES][MAX_STAT_PHASES])
{
unsigned int i, j;
- uint64_t avg;
+ u64 avg;
- for (i=STAT_OP_TYPE_ENCODE; i<MAX_STAT_OP_TYPES; i++) {
- for (j=0; j<MAX_STAT_PHASES; j++) {
+ for (i = STAT_OP_TYPE_ENCODE; i < MAX_STAT_OP_TYPES; i++) {
+ for (j = 0; j < MAX_STAT_PHASES; j++) {
if (item[i][j].count > 0) {
- avg = (uint64_t)item[i][j].sum;
+ avg = (u64)item[i][j].sum;
do_div(avg, item[i][j].count);
- SSI_LOG_ERR("%s, %s: min=%d avg=%d max=%d sum=%lld count=%d\n",
- stat_name_db[i].op_type_name, stat_name_db[i].stat_phase_name[j],
+ SSI_LOG_ERR("%s, %s: min=%d avg=%d max=%d sum=%lld count=%d\n",
+ stat_name_db[i].op_type_name, stat_name_db[i].stat_phase_name[j],
item[i][j].min, (int)avg, item[i][j].max, (long long)item[i][j].sum, item[i][j].count);
}
}
}
}
-
/**************************************
* Attributes show functions section *
**************************************/
@@ -174,38 +172,38 @@ static ssize_t ssi_sys_stats_cc_db_clear(struct kobject *kobj,
static ssize_t ssi_sys_stat_host_db_show(struct kobject *kobj,
struct kobj_attribute *attr, char *buf)
{
- int i, j ;
+ int i, j;
char line[512];
- uint32_t min_cyc, max_cyc;
- uint64_t avg;
- ssize_t buf_len, tmp_len=0;
+ u32 min_cyc, max_cyc;
+ u64 avg;
+ ssize_t buf_len, tmp_len = 0;
- buf_len = scnprintf(buf,PAGE_SIZE,
+ buf_len = scnprintf(buf, PAGE_SIZE,
"phase\t\t\t\t\t\t\tmin[cy]\tavg[cy]\tmax[cy]\t#samples\n");
- if ( buf_len <0 )/* scnprintf shouldn't return negative value according to its implementation*/
+ if (buf_len < 0)/* scnprintf shouldn't return negative value according to its implementation*/
return buf_len;
- for (i=STAT_OP_TYPE_ENCODE; i<MAX_STAT_OP_TYPES; i++) {
- for (j=0; j<MAX_STAT_PHASES-1; j++) {
+ for (i = STAT_OP_TYPE_ENCODE; i < MAX_STAT_OP_TYPES; i++) {
+ for (j = 0; j < MAX_STAT_PHASES - 1; j++) {
if (stat_host_db[i][j].count > 0) {
- avg = (uint64_t)stat_host_db[i][j].sum;
+ avg = (u64)stat_host_db[i][j].sum;
do_div(avg, stat_host_db[i][j].count);
min_cyc = stat_host_db[i][j].min;
max_cyc = stat_host_db[i][j].max;
} else {
avg = min_cyc = max_cyc = 0;
}
- tmp_len = scnprintf(line,512,
+ tmp_len = scnprintf(line, 512,
"%s::%s\t\t\t\t\t%6u\t%6u\t%6u\t%7u\n",
stat_name_db[i].op_type_name,
stat_name_db[i].stat_phase_name[j],
min_cyc, (unsigned int)avg, max_cyc,
stat_host_db[i][j].count);
- if ( tmp_len <0 )/* scnprintf shouldn't return negative value according to its implementation*/
+ if (tmp_len < 0)/* scnprintf shouldn't return negative value according to its implementation*/
return buf_len;
- if ( buf_len + tmp_len >= PAGE_SIZE)
+ if (buf_len + tmp_len >= PAGE_SIZE)
return buf_len;
buf_len += tmp_len;
- strncat(buf, line,512);
+ strncat(buf, line, 512);
}
}
return buf_len;
@@ -216,24 +214,24 @@ static ssize_t ssi_sys_stat_cc_db_show(struct kobject *kobj,
{
int i;
char line[256];
- uint32_t min_cyc, max_cyc;
- uint64_t avg;
- ssize_t buf_len,tmp_len=0;
+ u32 min_cyc, max_cyc;
+ u64 avg;
+ ssize_t buf_len, tmp_len = 0;
- buf_len = scnprintf(buf,PAGE_SIZE,
+ buf_len = scnprintf(buf, PAGE_SIZE,
"phase\tmin[cy]\tavg[cy]\tmax[cy]\t#samples\n");
- if ( buf_len <0 )/* scnprintf shouldn't return negative value according to its implementation*/
+ if (buf_len < 0)/* scnprintf shouldn't return negative value according to its implementation*/
return buf_len;
- for (i=STAT_OP_TYPE_ENCODE; i<MAX_STAT_OP_TYPES; i++) {
+ for (i = STAT_OP_TYPE_ENCODE; i < MAX_STAT_OP_TYPES; i++) {
if (stat_cc_db[i][STAT_PHASE_6].count > 0) {
- avg = (uint64_t)stat_cc_db[i][STAT_PHASE_6].sum;
+ avg = (u64)stat_cc_db[i][STAT_PHASE_6].sum;
do_div(avg, stat_cc_db[i][STAT_PHASE_6].count);
min_cyc = stat_cc_db[i][STAT_PHASE_6].min;
max_cyc = stat_cc_db[i][STAT_PHASE_6].max;
} else {
avg = min_cyc = max_cyc = 0;
}
- tmp_len = scnprintf(line,256,
+ tmp_len = scnprintf(line, 256,
"%s\t%6u\t%6u\t%6u\t%7u\n",
stat_name_db[i].op_type_name,
min_cyc,
@@ -241,13 +239,13 @@ static ssize_t ssi_sys_stat_cc_db_show(struct kobject *kobj,
max_cyc,
stat_cc_db[i][STAT_PHASE_6].count);
- if ( tmp_len < 0 )/* scnprintf shouldn't return negative value according to its implementation*/
+ if (tmp_len < 0)/* scnprintf shouldn't return negative value according to its implementation*/
return buf_len;
- if ( buf_len + tmp_len >= PAGE_SIZE)
+ if (buf_len + tmp_len >= PAGE_SIZE)
return buf_len;
buf_len += tmp_len;
- strncat(buf, line,256);
+ strncat(buf, line, 256);
}
return buf_len;
}
@@ -271,21 +269,19 @@ void update_cc_stat(
void display_all_stat_db(void)
{
- SSI_LOG_ERR("\n======= CYCLE COUNT STATS =======\n");
+ SSI_LOG_ERR("\n======= CYCLE COUNT STATS =======\n");
display_db(stat_host_db);
- SSI_LOG_ERR("\n======= CC HW CYCLE COUNT STATS =======\n");
+ SSI_LOG_ERR("\n======= CC HW CYCLE COUNT STATS =======\n");
display_db(stat_cc_db);
}
#endif /*CC_CYCLE_COUNT*/
-
-
static ssize_t ssi_sys_regdump_show(struct kobject *kobj,
struct kobj_attribute *attr, char *buf)
{
struct ssi_drvdata *drvdata = sys_get_drvdata();
- uint32_t register_value;
- void __iomem* cc_base = drvdata->cc_base;
+ u32 register_value;
+ void __iomem *cc_base = drvdata->cc_base;
int offset = 0;
register_value = CC_HAL_READ_REGISTER(CC_REG_OFFSET(HOST_RGF, HOST_SIGNATURE));
@@ -304,7 +300,7 @@ static ssize_t ssi_sys_regdump_show(struct kobject *kobj,
static ssize_t ssi_sys_help_show(struct kobject *kobj,
struct kobj_attribute *attr, char *buf)
{
- char* help_str[]={
+ char *help_str[] = {
"cat reg_dump ", "Print several of CC register values",
#if defined CC_CYCLE_COUNT
"cat stats_host ", "Print host statistics",
@@ -313,12 +309,12 @@ static ssize_t ssi_sys_help_show(struct kobject *kobj,
"echo <number> > stats_cc ", "Clear CC statistics database",
#endif
};
- int i=0, offset = 0;
+ int i = 0, offset = 0;
offset += scnprintf(buf + offset, PAGE_SIZE - offset, "Usage:\n");
- for ( i = 0; i < ARRAY_SIZE(help_str); i+=2) {
- offset += scnprintf(buf + offset, PAGE_SIZE - offset, "%s\t\t%s\n", help_str[i], help_str[i+1]);
- }
+ for (i = 0; i < ARRAY_SIZE(help_str); i += 2)
+ offset += scnprintf(buf + offset, PAGE_SIZE - offset, "%s\t\t%s\n", help_str[i], help_str[i + 1]);
+
return offset;
}
@@ -333,7 +329,7 @@ struct sys_dir {
struct kobject *sys_dir_kobj;
struct attribute_group sys_dir_attr_group;
struct attribute **sys_dir_attr_list;
- uint32_t num_of_attrs;
+ u32 num_of_attrs;
struct ssi_drvdata *drvdata; /* Associated driver context */
};
@@ -355,13 +351,14 @@ static struct ssi_drvdata *sys_get_drvdata(void)
{
/* TODO: supporting multiple SeP devices would require avoiding
* global "top_dir" and finding associated "top_dir" by traversing
- * up the tree to the kobject which matches one of the top_dir's */
+ * up the tree to the kobject which matches one of the top_dir's
+ */
return sys_top_dir.drvdata;
}
static int sys_init_dir(struct sys_dir *sys_dir, struct ssi_drvdata *drvdata,
struct kobject *parent_dir_kobj, const char *dir_name,
- struct kobj_attribute *attrs, uint32_t num_of_attrs)
+ struct kobj_attribute *attrs, u32 num_of_attrs)
{
int i;
@@ -407,7 +404,7 @@ static void sys_free_dir(struct sys_dir *sys_dir)
kfree(sys_dir->sys_dir_attr_list);
- if (sys_dir->sys_dir_kobj != NULL)
+ if (sys_dir->sys_dir_kobj)
kobject_put(sys_dir->sys_dir_kobj);
}
diff --git a/drivers/staging/ccree/ssi_sysfs.h b/drivers/staging/ccree/ssi_sysfs.h
index baeac1d99c07..44ae3d4c40b3 100644
--- a/drivers/staging/ccree/ssi_sysfs.h
+++ b/drivers/staging/ccree/ssi_sysfs.h
@@ -1,21 +1,21 @@
/*
* Copyright (C) 2012-2017 ARM Limited or its affiliates.
- *
+ *
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
- *
+ *
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
- *
+ *
* You should have received a copy of the GNU General Public License
* along with this program; if not, see <http://www.gnu.org/licenses/>.
*/
/* \file ssi_sysfs.h
- ARM CryptoCell sysfs APIs
+ * ARM CryptoCell sysfs APIs
*/
#ifndef __SSI_SYSFS_H__
@@ -36,6 +36,7 @@ enum stat_phase {
STAT_PHASE_6,
MAX_STAT_PHASES,
};
+
enum stat_op {
STAT_OP_TYPE_NULL = 0,
STAT_OP_TYPE_ENCODE,
diff --git a/drivers/staging/comedi/comedi_fops.c b/drivers/staging/comedi/comedi_fops.c
index f191c2a75732..ca11be21f64b 100644
--- a/drivers/staging/comedi/comedi_fops.c
+++ b/drivers/staging/comedi/comedi_fops.c
@@ -2881,29 +2881,25 @@ static int __init comedi_init(void)
retval = register_chrdev_region(MKDEV(COMEDI_MAJOR, 0),
COMEDI_NUM_MINORS, "comedi");
if (retval)
- return -EIO;
+ return retval;
+
cdev_init(&comedi_cdev, &comedi_fops);
comedi_cdev.owner = THIS_MODULE;
retval = kobject_set_name(&comedi_cdev.kobj, "comedi");
- if (retval) {
- unregister_chrdev_region(MKDEV(COMEDI_MAJOR, 0),
- COMEDI_NUM_MINORS);
- return retval;
- }
+ if (retval)
+ goto out_unregister_chrdev_region;
+
+ retval = cdev_add(&comedi_cdev, MKDEV(COMEDI_MAJOR, 0),
+ COMEDI_NUM_MINORS);
+ if (retval)
+ goto out_unregister_chrdev_region;
- if (cdev_add(&comedi_cdev, MKDEV(COMEDI_MAJOR, 0), COMEDI_NUM_MINORS)) {
- unregister_chrdev_region(MKDEV(COMEDI_MAJOR, 0),
- COMEDI_NUM_MINORS);
- return -EIO;
- }
comedi_class = class_create(THIS_MODULE, "comedi");
if (IS_ERR(comedi_class)) {
+ retval = PTR_ERR(comedi_class);
pr_err("failed to create class\n");
- cdev_del(&comedi_cdev);
- unregister_chrdev_region(MKDEV(COMEDI_MAJOR, 0),
- COMEDI_NUM_MINORS);
- return PTR_ERR(comedi_class);
+ goto out_cdev_del;
}
comedi_class->dev_groups = comedi_dev_groups;
@@ -2914,11 +2910,8 @@ static int __init comedi_init(void)
dev = comedi_alloc_board_minor(NULL);
if (IS_ERR(dev)) {
- comedi_cleanup_board_minors();
- cdev_del(&comedi_cdev);
- unregister_chrdev_region(MKDEV(COMEDI_MAJOR, 0),
- COMEDI_NUM_MINORS);
- return PTR_ERR(dev);
+ retval = PTR_ERR(dev);
+ goto out_cleanup_board_minors;
}
/* comedi_alloc_board_minor() locked the mutex */
mutex_unlock(&dev->mutex);
@@ -2928,6 +2921,15 @@ static int __init comedi_init(void)
comedi_proc_init();
return 0;
+
+out_cleanup_board_minors:
+ comedi_cleanup_board_minors();
+ class_destroy(comedi_class);
+out_cdev_del:
+ cdev_del(&comedi_cdev);
+out_unregister_chrdev_region:
+ unregister_chrdev_region(MKDEV(COMEDI_MAJOR, 0), COMEDI_NUM_MINORS);
+ return retval;
}
module_init(comedi_init);
diff --git a/drivers/staging/comedi/drivers/ni_labpc_isadma.h b/drivers/staging/comedi/drivers/ni_labpc_isadma.h
index b8a1b0ee6290..e93f79050e60 100644
--- a/drivers/staging/comedi/drivers/ni_labpc_isadma.h
+++ b/drivers/staging/comedi/drivers/ni_labpc_isadma.h
@@ -1,6 +1,6 @@
/*
* ni_labpc ISA DMA support.
-*/
+ */
#ifndef _NI_LABPC_ISADMA_H
#define _NI_LABPC_ISADMA_H
diff --git a/drivers/staging/comedi/drivers/ni_labpc_regs.h b/drivers/staging/comedi/drivers/ni_labpc_regs.h
index 8c52179e36fc..6003e9d5fe37 100644
--- a/drivers/staging/comedi/drivers/ni_labpc_regs.h
+++ b/drivers/staging/comedi/drivers/ni_labpc_regs.h
@@ -1,6 +1,6 @@
/*
* ni_labpc register definitions.
-*/
+ */
#ifndef _NI_LABPC_REGS_H
#define _NI_LABPC_REGS_H
diff --git a/drivers/staging/comedi/drivers/s626.c b/drivers/staging/comedi/drivers/s626.c
index 4b9c22665748..c906c9a5d944 100644
--- a/drivers/staging/comedi/drivers/s626.c
+++ b/drivers/staging/comedi/drivers/s626.c
@@ -580,11 +580,14 @@ static int s626_set_dac(struct comedi_device *dev,
* running after the packet has been sent to the target DAC.
*/
val = 0x0F000000; /* Continue clock after target DAC data
- * (write to non-existent trimdac). */
+ * (write to non-existent trimdac).
+ */
val |= 0x00004000; /* Address the two main dual-DAC devices
- * (TSL's chip select enables target device). */
+ * (TSL's chip select enables target device).
+ */
val |= ((u32)(chan & 1) << 15); /* Address the DAC channel
- * within the device. */
+ * within the device.
+ */
val |= (u32)dacdata; /* Include DAC setpoint data. */
return s626_send_dac(dev, val);
}
diff --git a/drivers/staging/dgnc/dgnc_driver.c b/drivers/staging/dgnc/dgnc_driver.c
index 253f38b25a54..c1b6079384e9 100644
--- a/drivers/staging/dgnc/dgnc_driver.c
+++ b/drivers/staging/dgnc/dgnc_driver.c
@@ -96,7 +96,6 @@ static int dgnc_do_remap(struct dgnc_board *brd)
return 0;
}
-
/* A board has been found, initialize it. */
static struct dgnc_board *dgnc_found_board(struct pci_dev *pdev, int id)
{
@@ -287,7 +286,6 @@ static void dgnc_free_irq(struct dgnc_board *brd)
free_irq(brd->irq, brd);
}
-
/*
* As each timer expires, it determines (a) whether the "transmit"
* waiter needs to be woken up, and (b) whether the poller needs to
diff --git a/drivers/staging/dgnc/dgnc_driver.h b/drivers/staging/dgnc/dgnc_driver.h
index 980410fc4801..764d6fe0d030 100644
--- a/drivers/staging/dgnc/dgnc_driver.h
+++ b/drivers/staging/dgnc/dgnc_driver.h
@@ -52,19 +52,6 @@
#define dgnc_jiffies_from_ms(a) (((a) * HZ) / 1000)
-/*
- * Define a local default termios struct. All ports will be created
- * with this termios initially. This is the same structure that is defined
- * as the default in tty_io.c with the same settings overridden as in serial.c
- *
- * In short, this should match the internal serial ports' defaults.
- */
-#define DEFAULT_IFLAGS (ICRNL | IXON)
-#define DEFAULT_OFLAGS (OPOST | ONLCR)
-#define DEFAULT_CFLAGS (B9600 | CS8 | CREAD | HUPCL | CLOCAL)
-#define DEFAULT_LFLAGS (ISIG | ICANON | ECHO | ECHOE | ECHOK | \
- ECHOCTL | ECHOKE | IEXTEN)
-
#ifndef _POSIX_VDISABLE
#define _POSIX_VDISABLE '\0'
#endif
diff --git a/drivers/staging/dgnc/dgnc_tty.c b/drivers/staging/dgnc/dgnc_tty.c
index 9e98781ca6fe..d3736daf8cf2 100644
--- a/drivers/staging/dgnc/dgnc_tty.c
+++ b/drivers/staging/dgnc/dgnc_tty.c
@@ -51,22 +51,6 @@ static const struct digi_t dgnc_digi_init = {
.digi_term = "ansi" /* default terminal type */
};
-/*
- * Define a local default termios struct. All ports will be created
- * with this termios initially.
- *
- * This defines a raw port at 9600 baud, 8 data bits, no parity,
- * 1 stop bit.
- */
-static const struct ktermios default_termios = {
- .c_iflag = (DEFAULT_IFLAGS),
- .c_oflag = (DEFAULT_OFLAGS),
- .c_cflag = (DEFAULT_CFLAGS),
- .c_lflag = (DEFAULT_LFLAGS),
- .c_cc = INIT_C_CC,
- .c_line = 0,
-};
-
static int dgnc_tty_open(struct tty_struct *tty, struct file *file);
static void dgnc_tty_close(struct tty_struct *tty, struct file *file);
static int dgnc_block_til_ready(struct tty_struct *tty, struct file *file,
@@ -129,6 +113,49 @@ static const struct tty_operations dgnc_tty_ops = {
/* TTY Initialization/Cleanup Functions */
+static struct tty_driver *dgnc_tty_create(char *serial_name, uint maxports,
+ int major, int minor)
+{
+ int rc;
+ struct tty_driver *drv;
+
+ drv = tty_alloc_driver(maxports,
+ TTY_DRIVER_REAL_RAW |
+ TTY_DRIVER_DYNAMIC_DEV |
+ TTY_DRIVER_HARDWARE_BREAK);
+ if (IS_ERR(drv))
+ return drv;
+
+ drv->name = serial_name;
+ drv->name_base = 0;
+ drv->major = major;
+ drv->minor_start = minor;
+ drv->type = TTY_DRIVER_TYPE_SERIAL;
+ drv->subtype = SERIAL_TYPE_NORMAL;
+ drv->init_termios = tty_std_termios;
+ drv->init_termios.c_cflag = (B9600 | CS8 | CREAD | HUPCL | CLOCAL);
+ drv->init_termios.c_ispeed = 9600;
+ drv->init_termios.c_ospeed = 9600;
+ drv->driver_name = DRVSTR;
+ /*
+ * Entry points for driver. Called by the kernel from
+ * tty_io.c and n_tty.c.
+ */
+ tty_set_operations(drv, &dgnc_tty_ops);
+ rc = tty_register_driver(drv);
+ if (rc < 0) {
+ put_tty_driver(drv);
+ return ERR_PTR(rc);
+ }
+ return drv;
+}
+
+static void dgnc_tty_free(struct tty_driver *drv)
+{
+ tty_unregister_driver(drv);
+ put_tty_driver(drv);
+}
+
/**
* dgnc_tty_register() - Init the tty subsystem for this board.
*/
@@ -136,95 +163,36 @@ int dgnc_tty_register(struct dgnc_board *brd)
{
int rc;
- brd->serial_driver = tty_alloc_driver(brd->maxports,
- TTY_DRIVER_REAL_RAW |
- TTY_DRIVER_DYNAMIC_DEV |
- TTY_DRIVER_HARDWARE_BREAK);
- if (IS_ERR(brd->serial_driver))
- return PTR_ERR(brd->serial_driver);
-
snprintf(brd->serial_name, MAXTTYNAMELEN, "tty_dgnc_%d_",
brd->boardnum);
- brd->serial_driver->name = brd->serial_name;
- brd->serial_driver->name_base = 0;
- brd->serial_driver->major = 0;
- brd->serial_driver->minor_start = 0;
- brd->serial_driver->type = TTY_DRIVER_TYPE_SERIAL;
- brd->serial_driver->subtype = SERIAL_TYPE_NORMAL;
- brd->serial_driver->init_termios = default_termios;
- brd->serial_driver->driver_name = DRVSTR;
-
- /*
- * Entry points for driver. Called by the kernel from
- * tty_io.c and n_tty.c.
- */
- tty_set_operations(brd->serial_driver, &dgnc_tty_ops);
-
- rc = tty_register_driver(brd->serial_driver);
- if (rc < 0) {
- dev_dbg(&brd->pdev->dev,
- "Can't register tty device (%d)\n", rc);
- goto free_serial_driver;
+ brd->serial_driver = dgnc_tty_create(brd->serial_name,
+ brd->maxports, 0, 0);
+ if (IS_ERR(brd->serial_driver)) {
+ rc = PTR_ERR(brd->serial_driver);
+ dev_dbg(&brd->pdev->dev, "Can't register tty device (%d)\n",
+ rc);
+ return rc;
}
- /*
- * If we're doing transparent print, we have to do all of the above
- * again, separately so we don't get the LD confused about what major
- * we are when we get into the dgnc_tty_open() routine.
- */
- brd->print_driver = tty_alloc_driver(brd->maxports,
- TTY_DRIVER_REAL_RAW |
- TTY_DRIVER_DYNAMIC_DEV |
- TTY_DRIVER_HARDWARE_BREAK);
+ snprintf(brd->print_name, MAXTTYNAMELEN, "pr_dgnc_%d_", brd->boardnum);
+ brd->print_driver = dgnc_tty_create(brd->print_name, brd->maxports,
+ 0x80,
+ brd->serial_driver->major);
if (IS_ERR(brd->print_driver)) {
rc = PTR_ERR(brd->print_driver);
- goto unregister_serial_driver;
- }
-
- snprintf(brd->print_name, MAXTTYNAMELEN, "pr_dgnc_%d_", brd->boardnum);
-
- brd->print_driver->name = brd->print_name;
- brd->print_driver->name_base = 0;
- brd->print_driver->major = brd->serial_driver->major;
- brd->print_driver->minor_start = 0x80;
- brd->print_driver->type = TTY_DRIVER_TYPE_SERIAL;
- brd->print_driver->subtype = SERIAL_TYPE_NORMAL;
- brd->print_driver->init_termios = default_termios;
- brd->print_driver->driver_name = DRVSTR;
-
- /*
- * Entry points for driver. Called by the kernel from
- * tty_io.c and n_tty.c.
- */
- tty_set_operations(brd->print_driver, &dgnc_tty_ops);
-
- rc = tty_register_driver(brd->print_driver);
- if (rc < 0) {
dev_dbg(&brd->pdev->dev,
- "Can't register Transparent Print device(%d)\n",
- rc);
- goto free_print_driver;
+ "Can't register Transparent Print device(%d)\n", rc);
+ dgnc_tty_free(brd->serial_driver);
+ return rc;
}
-
return 0;
-
-free_print_driver:
- put_tty_driver(brd->print_driver);
-unregister_serial_driver:
- tty_unregister_driver(brd->serial_driver);
-free_serial_driver:
- put_tty_driver(brd->serial_driver);
-
- return rc;
}
void dgnc_tty_unregister(struct dgnc_board *brd)
{
- tty_unregister_driver(brd->print_driver);
- tty_unregister_driver(brd->serial_driver);
- put_tty_driver(brd->print_driver);
- put_tty_driver(brd->serial_driver);
+ dgnc_tty_free(brd->print_driver);
+ dgnc_tty_free(brd->serial_driver);
}
/**
diff --git a/drivers/staging/emxx_udc/emxx_udc.c b/drivers/staging/emxx_udc/emxx_udc.c
index 77b242e09932..bb010cb98a1c 100644
--- a/drivers/staging/emxx_udc/emxx_udc.c
+++ b/drivers/staging/emxx_udc/emxx_udc.c
@@ -200,13 +200,13 @@ static u32 _nbu2ss_get_begin_ram_address(struct nbu2ss_udc *udc)
for (num = 0; num < NUM_ENDPOINTS - 1; num++) {
p_ep_regs = &udc->p_regs->EP_REGS[num];
data = _nbu2ss_readl(&p_ep_regs->EP_PCKT_ADRS);
- buf_type = _nbu2ss_readl(&p_ep_regs->EP_CONTROL) & EPn_BUF_TYPE;
+ buf_type = _nbu2ss_readl(&p_ep_regs->EP_CONTROL) & EPN_BUF_TYPE;
if (buf_type == 0) {
/* Single Buffer */
- use_ram_size += (data & EPn_MPKT) / sizeof(u32);
+ use_ram_size += (data & EPN_MPKT) / sizeof(u32);
} else {
/* Double Buffer */
- use_ram_size += ((data & EPn_MPKT) / sizeof(u32)) * 2;
+ use_ram_size += ((data & EPN_MPKT) / sizeof(u32)) * 2;
}
if ((data >> 16) > last_ram_adr)
@@ -245,15 +245,15 @@ static int _nbu2ss_ep_init(struct nbu2ss_udc *udc, struct nbu2ss_ep *ep)
/* Bulk, Interrupt, ISO */
switch (ep->ep_type) {
case USB_ENDPOINT_XFER_BULK:
- data = EPn_BULK;
+ data = EPN_BULK;
break;
case USB_ENDPOINT_XFER_INT:
- data = EPn_BUF_SINGLE | EPn_INTERRUPT;
+ data = EPN_BUF_SINGLE | EPN_INTERRUPT;
break;
case USB_ENDPOINT_XFER_ISOC:
- data = EPn_ISO;
+ data = EPN_ISO;
break;
default:
@@ -267,24 +267,24 @@ static int _nbu2ss_ep_init(struct nbu2ss_udc *udc, struct nbu2ss_ep *ep)
if (ep->direct == USB_DIR_OUT) {
/*---------------------------------------------------------*/
/* OUT */
- data = EPn_EN | EPn_BCLR | EPn_DIR0;
+ data = EPN_EN | EPN_BCLR | EPN_DIR0;
_nbu2ss_bitset(&udc->p_regs->EP_REGS[num].EP_CONTROL, data);
- data = EPn_ONAK | EPn_OSTL_EN | EPn_OSTL;
+ data = EPN_ONAK | EPN_OSTL_EN | EPN_OSTL;
_nbu2ss_bitclr(&udc->p_regs->EP_REGS[num].EP_CONTROL, data);
- data = EPn_OUT_EN | EPn_OUT_END_EN;
+ data = EPN_OUT_EN | EPN_OUT_END_EN;
_nbu2ss_bitset(&udc->p_regs->EP_REGS[num].EP_INT_ENA, data);
} else {
/*---------------------------------------------------------*/
/* IN */
- data = EPn_EN | EPn_BCLR | EPn_AUTO;
+ data = EPN_EN | EPN_BCLR | EPN_AUTO;
_nbu2ss_bitset(&udc->p_regs->EP_REGS[num].EP_CONTROL, data);
- data = EPn_ISTL;
+ data = EPN_ISTL;
_nbu2ss_bitclr(&udc->p_regs->EP_REGS[num].EP_CONTROL, data);
- data = EPn_IN_EN | EPn_IN_END_EN;
+ data = EPN_IN_EN | EPN_IN_END_EN;
_nbu2ss_bitset(&udc->p_regs->EP_REGS[num].EP_INT_ENA, data);
}
@@ -315,24 +315,24 @@ static int _nbu2ss_epn_exit(struct nbu2ss_udc *udc, struct nbu2ss_ep *ep)
if (ep->direct == USB_DIR_OUT) {
/*---------------------------------------------------------*/
/* OUT */
- data = EPn_ONAK | EPn_BCLR;
+ data = EPN_ONAK | EPN_BCLR;
_nbu2ss_bitset(&udc->p_regs->EP_REGS[num].EP_CONTROL, data);
- data = EPn_EN | EPn_DIR0;
+ data = EPN_EN | EPN_DIR0;
_nbu2ss_bitclr(&udc->p_regs->EP_REGS[num].EP_CONTROL, data);
- data = EPn_OUT_EN | EPn_OUT_END_EN;
+ data = EPN_OUT_EN | EPN_OUT_END_EN;
_nbu2ss_bitclr(&udc->p_regs->EP_REGS[num].EP_INT_ENA, data);
} else {
/*---------------------------------------------------------*/
/* IN */
- data = EPn_BCLR;
+ data = EPN_BCLR;
_nbu2ss_bitset(&udc->p_regs->EP_REGS[num].EP_CONTROL, data);
- data = EPn_EN | EPn_AUTO;
+ data = EPN_EN | EPN_AUTO;
_nbu2ss_bitclr(&udc->p_regs->EP_REGS[num].EP_CONTROL, data);
- data = EPn_IN_EN | EPn_IN_END_EN;
+ data = EPN_IN_EN | EPN_IN_END_EN;
_nbu2ss_bitclr(&udc->p_regs->EP_REGS[num].EP_INT_ENA, data);
}
@@ -360,21 +360,21 @@ static void _nbu2ss_ep_dma_init(struct nbu2ss_udc *udc, struct nbu2ss_ep *ep)
/*---------------------------------------------------------*/
/* Transfer Direct */
- data = DCR1_EPn_DIR0;
+ data = DCR1_EPN_DIR0;
_nbu2ss_bitset(&udc->p_regs->EP_DCR[num].EP_DCR1, data);
/*---------------------------------------------------------*/
/* DMA Mode etc. */
- data = EPn_STOP_MODE | EPn_STOP_SET | EPn_DMAMODE0;
+ data = EPN_STOP_MODE | EPN_STOP_SET | EPN_DMAMODE0;
_nbu2ss_writel(&udc->p_regs->EP_REGS[num].EP_DMA_CTRL, data);
} else {
/*---------------------------------------------------------*/
/* IN */
- _nbu2ss_bitset(&udc->p_regs->EP_REGS[num].EP_CONTROL, EPn_AUTO);
+ _nbu2ss_bitset(&udc->p_regs->EP_REGS[num].EP_CONTROL, EPN_AUTO);
/*---------------------------------------------------------*/
/* DMA Mode etc. */
- data = EPn_BURST_SET | EPn_DMAMODE0;
+ data = EPN_BURST_SET | EPN_DMAMODE0;
_nbu2ss_writel(&udc->p_regs->EP_REGS[num].EP_DMA_CTRL, data);
}
}
@@ -402,12 +402,12 @@ static void _nbu2ss_ep_dma_exit(struct nbu2ss_udc *udc, struct nbu2ss_ep *ep)
/*---------------------------------------------------------*/
/* OUT */
_nbu2ss_writel(&preg->EP_DCR[num].EP_DCR2, 0);
- _nbu2ss_bitclr(&preg->EP_DCR[num].EP_DCR1, DCR1_EPn_DIR0);
+ _nbu2ss_bitclr(&preg->EP_DCR[num].EP_DCR1, DCR1_EPN_DIR0);
_nbu2ss_writel(&preg->EP_REGS[num].EP_DMA_CTRL, 0);
} else {
/*---------------------------------------------------------*/
/* IN */
- _nbu2ss_bitclr(&preg->EP_REGS[num].EP_CONTROL, EPn_AUTO);
+ _nbu2ss_bitclr(&preg->EP_REGS[num].EP_CONTROL, EPN_AUTO);
_nbu2ss_writel(&preg->EP_REGS[num].EP_DMA_CTRL, 0);
}
}
@@ -418,9 +418,9 @@ static void _nbu2ss_ep_dma_abort(struct nbu2ss_udc *udc, struct nbu2ss_ep *ep)
{
struct fc_regs *preg = udc->p_regs;
- _nbu2ss_bitclr(&preg->EP_DCR[ep->epnum - 1].EP_DCR1, DCR1_EPn_REQEN);
- mdelay(DMA_DISABLE_TIME); /* DCR1_EPn_REQEN Clear */
- _nbu2ss_bitclr(&preg->EP_REGS[ep->epnum - 1].EP_DMA_CTRL, EPn_DMA_EN);
+ _nbu2ss_bitclr(&preg->EP_DCR[ep->epnum - 1].EP_DCR1, DCR1_EPN_REQEN);
+ mdelay(DMA_DISABLE_TIME); /* DCR1_EPN_REQEN Clear */
+ _nbu2ss_bitclr(&preg->EP_REGS[ep->epnum - 1].EP_DMA_CTRL, EPN_DMA_EN);
}
/*-------------------------------------------------------------------------*/
@@ -453,16 +453,16 @@ static void _nbu2ss_ep_in_end(
} else {
num = epnum - 1;
- _nbu2ss_bitclr(&preg->EP_REGS[num].EP_CONTROL, EPn_AUTO);
+ _nbu2ss_bitclr(&preg->EP_REGS[num].EP_CONTROL, EPN_AUTO);
/* Writing of 1-4 bytes */
if (length)
_nbu2ss_writel(&preg->EP_REGS[num].EP_WRITE, data32);
- data = (((length) << 5) & EPn_DW) | EPn_DEND;
+ data = (((length) << 5) & EPN_DW) | EPN_DEND;
_nbu2ss_bitset(&preg->EP_REGS[num].EP_CONTROL, data);
- _nbu2ss_bitset(&preg->EP_REGS[num].EP_CONTROL, EPn_AUTO);
+ _nbu2ss_bitset(&preg->EP_REGS[num].EP_CONTROL, EPN_AUTO);
}
}
@@ -526,12 +526,13 @@ static void _nbu2ss_dma_unmap_single(
if (direct == USB_DIR_OUT)
memcpy(req->req.buf, ep->virt_buf,
req->req.actual & 0xfffffffc);
- } else
+ } else {
dma_unmap_single(udc->gadget.dev.parent,
req->req.dma, req->req.length,
(direct == USB_DIR_IN)
? DMA_TO_DEVICE
: DMA_FROM_DEVICE);
+ }
req->req.dma = DMA_ADDR_INVALID;
req->mapped = 0;
} else {
@@ -573,65 +574,67 @@ static int ep0_out_pio(struct nbu2ss_udc *udc, u8 *buf, u32 length)
/*-------------------------------------------------------------------------*/
/* Endpoint 0 OUT Transfer (PIO, OverBytes) */
-static int EP0_out_OverBytes(struct nbu2ss_udc *udc, u8 *pBuf, u32 length)
+static int ep0_out_overbytes(struct nbu2ss_udc *udc, u8 *p_buf, u32 length)
{
u32 i;
- u32 iReadSize = 0;
- union usb_reg_access Temp32;
- union usb_reg_access *pBuf32 = (union usb_reg_access *)pBuf;
+ u32 i_read_size = 0;
+ union usb_reg_access temp_32;
+ union usb_reg_access *p_buf_32 = (union usb_reg_access *)p_buf;
if ((length > 0) && (length < sizeof(u32))) {
- Temp32.dw = _nbu2ss_readl(&udc->p_regs->EP0_READ);
+ temp_32.dw = _nbu2ss_readl(&udc->p_regs->EP0_READ);
for (i = 0 ; i < length ; i++)
- pBuf32->byte.DATA[i] = Temp32.byte.DATA[i];
- iReadSize += length;
+ p_buf_32->byte.DATA[i] = temp_32.byte.DATA[i];
+ i_read_size += length;
}
- return iReadSize;
+ return i_read_size;
}
/*-------------------------------------------------------------------------*/
/* Endpoint 0 IN Transfer (PIO) */
-static int EP0_in_PIO(struct nbu2ss_udc *udc, u8 *pBuf, u32 length)
+static int EP0_in_PIO(struct nbu2ss_udc *udc, u8 *p_buf, u32 length)
{
u32 i;
- u32 iMaxLength = EP0_PACKETSIZE;
- u32 iWordLength = 0;
- u32 iWriteLength = 0;
- union usb_reg_access *pBuf32 = (union usb_reg_access *)pBuf;
+ u32 i_max_length = EP0_PACKETSIZE;
+ u32 i_word_length = 0;
+ u32 i_write_length = 0;
+ union usb_reg_access *p_buf_32 = (union usb_reg_access *)p_buf;
/*------------------------------------------------------------*/
/* Transfer Length */
- if (iMaxLength < length)
- iWordLength = iMaxLength / sizeof(u32);
+ if (i_max_length < length)
+ i_word_length = i_max_length / sizeof(u32);
else
- iWordLength = length / sizeof(u32);
+ i_word_length = length / sizeof(u32);
/*------------------------------------------------------------*/
/* PIO */
- for (i = 0; i < iWordLength; i++) {
- _nbu2ss_writel(&udc->p_regs->EP0_WRITE, pBuf32->dw);
- pBuf32++;
- iWriteLength += sizeof(u32);
+ for (i = 0; i < i_word_length; i++) {
+ _nbu2ss_writel(&udc->p_regs->EP0_WRITE, p_buf_32->dw);
+ p_buf_32++;
+ i_write_length += sizeof(u32);
}
- return iWriteLength;
+ return i_write_length;
}
/*-------------------------------------------------------------------------*/
/* Endpoint 0 IN Transfer (PIO, OverBytes) */
-static int EP0_in_OverBytes(struct nbu2ss_udc *udc, u8 *pBuf, u32 iRemainSize)
+static int ep0_in_overbytes(struct nbu2ss_udc *udc,
+ u8 *p_buf,
+ u32 i_remain_size)
{
u32 i;
- union usb_reg_access Temp32;
- union usb_reg_access *pBuf32 = (union usb_reg_access *)pBuf;
+ union usb_reg_access temp_32;
+ union usb_reg_access *p_buf_32 = (union usb_reg_access *)p_buf;
- if ((iRemainSize > 0) && (iRemainSize < sizeof(u32))) {
- for (i = 0 ; i < iRemainSize ; i++)
- Temp32.byte.DATA[i] = pBuf32->byte.DATA[i];
- _nbu2ss_ep_in_end(udc, 0, Temp32.dw, iRemainSize);
+ if ((i_remain_size > 0) && (i_remain_size < sizeof(u32))) {
+ for (i = 0 ; i < i_remain_size ; i++)
+ temp_32.byte.DATA[i] = p_buf_32->byte.DATA[i];
+ _nbu2ss_ep_in_end(udc, 0, temp_32.dw, i_remain_size);
- return iRemainSize;
+ return i_remain_size;
}
return 0;
@@ -679,9 +682,9 @@ static int _nbu2ss_ep0_in_transfer(
struct nbu2ss_req *req
)
{
- u8 *pBuffer; /* IN Data Buffer */
+ u8 *p_buffer; /* IN Data Buffer */
u32 data;
- u32 iRemainSize = 0;
+ u32 i_remain_size = 0;
int result = 0;
/*-------------------------------------------------------------*/
@@ -705,25 +708,25 @@ static int _nbu2ss_ep0_in_transfer(
data &= ~(u32)EP0_INAK;
_nbu2ss_writel(&udc->p_regs->EP0_CONTROL, data);
- iRemainSize = req->req.length - req->req.actual;
- pBuffer = (u8 *)req->req.buf;
- pBuffer += req->req.actual;
+ i_remain_size = req->req.length - req->req.actual;
+ p_buffer = (u8 *)req->req.buf;
+ p_buffer += req->req.actual;
/*-------------------------------------------------------------*/
/* Data transfer */
- result = EP0_in_PIO(udc, pBuffer, iRemainSize);
+ result = EP0_in_PIO(udc, p_buffer, i_remain_size);
req->div_len = result;
- iRemainSize -= result;
+ i_remain_size -= result;
- if (iRemainSize == 0) {
+ if (i_remain_size == 0) {
EP0_send_NULL(udc, FALSE);
return result;
}
- if ((iRemainSize < sizeof(u32)) && (result != EP0_PACKETSIZE)) {
- pBuffer += result;
- result += EP0_in_OverBytes(udc, pBuffer, iRemainSize);
+ if ((i_remain_size < sizeof(u32)) && (result != EP0_PACKETSIZE)) {
+ p_buffer += result;
+ result += ep0_in_overbytes(udc, p_buffer, i_remain_size);
req->div_len = result;
}
@@ -736,40 +739,40 @@ static int _nbu2ss_ep0_out_transfer(
struct nbu2ss_req *req
)
{
- u8 *pBuffer;
- u32 iRemainSize;
- u32 iRecvLength;
+ u8 *p_buffer;
+ u32 i_remain_size;
+ u32 i_recv_length;
int result = 0;
- int fRcvZero;
+ int f_rcv_zero;
/*-------------------------------------------------------------*/
/* Receive data confirmation */
- iRecvLength = _nbu2ss_readl(&udc->p_regs->EP0_LENGTH) & EP0_LDATA;
- if (iRecvLength != 0) {
- fRcvZero = 0;
+ i_recv_length = _nbu2ss_readl(&udc->p_regs->EP0_LENGTH) & EP0_LDATA;
+ if (i_recv_length != 0) {
+ f_rcv_zero = 0;
- iRemainSize = req->req.length - req->req.actual;
- pBuffer = (u8 *)req->req.buf;
- pBuffer += req->req.actual;
+ i_remain_size = req->req.length - req->req.actual;
+ p_buffer = (u8 *)req->req.buf;
+ p_buffer += req->req.actual;
- result = ep0_out_pio(udc, pBuffer
- , min(iRemainSize, iRecvLength));
+ result = ep0_out_pio(udc, p_buffer
+ , min(i_remain_size, i_recv_length));
if (result < 0)
return result;
req->req.actual += result;
- iRecvLength -= result;
+ i_recv_length -= result;
- if ((iRecvLength > 0) && (iRecvLength < sizeof(u32))) {
- pBuffer += result;
- iRemainSize -= result;
+ if ((i_recv_length > 0) && (i_recv_length < sizeof(u32))) {
+ p_buffer += result;
+ i_remain_size -= result;
- result = EP0_out_OverBytes(udc, pBuffer
- , min(iRemainSize, iRecvLength));
+ result = ep0_out_overbytes(udc, p_buffer
+ , min(i_remain_size, i_recv_length));
req->req.actual += result;
}
} else {
- fRcvZero = 1;
+ f_rcv_zero = 1;
}
/*-------------------------------------------------------------*/
@@ -794,9 +797,9 @@ static int _nbu2ss_ep0_out_transfer(
return -EOVERFLOW;
}
- if (fRcvZero != 0) {
- iRemainSize = _nbu2ss_readl(&udc->p_regs->EP0_CONTROL);
- if (iRemainSize & EP0_ONAK) {
+ if (f_rcv_zero != 0) {
+ i_remain_size = _nbu2ss_readl(&udc->p_regs->EP0_CONTROL);
+ if (i_remain_size & EP0_ONAK) {
/*---------------------------------------------------*/
/* NACK release */
_nbu2ss_bitclr(&udc->p_regs->EP0_CONTROL, EP0_ONAK);
@@ -815,7 +818,7 @@ static int _nbu2ss_out_dma(
u32 length
)
{
- dma_addr_t pBuffer;
+ dma_addr_t p_buffer;
u32 mpkt;
u32 lmpkt;
u32 dmacnt;
@@ -828,14 +831,14 @@ static int _nbu2ss_out_dma(
return 1; /* DMA is forwarded */
req->dma_flag = TRUE;
- pBuffer = req->req.dma;
- pBuffer += req->req.actual;
+ p_buffer = req->req.dma;
+ p_buffer += req->req.actual;
/* DMA Address */
- _nbu2ss_writel(&preg->EP_DCR[num].EP_TADR, (u32)pBuffer);
+ _nbu2ss_writel(&preg->EP_DCR[num].EP_TADR, (u32)p_buffer);
/* Number of transfer packets */
- mpkt = _nbu2ss_readl(&preg->EP_REGS[num].EP_PCKT_ADRS) & EPn_MPKT;
+ mpkt = _nbu2ss_readl(&preg->EP_REGS[num].EP_PCKT_ADRS) & EPN_MPKT;
dmacnt = length / mpkt;
lmpkt = (length % mpkt) & ~(u32)0x03;
@@ -851,18 +854,18 @@ static int _nbu2ss_out_dma(
data = mpkt | (lmpkt << 16);
_nbu2ss_writel(&preg->EP_DCR[num].EP_DCR2, data);
- data = ((dmacnt & 0xff) << 16) | DCR1_EPn_DIR0 | DCR1_EPn_REQEN;
+ data = ((dmacnt & 0xff) << 16) | DCR1_EPN_DIR0 | DCR1_EPN_REQEN;
_nbu2ss_writel(&preg->EP_DCR[num].EP_DCR1, data);
if (burst == 0) {
_nbu2ss_writel(&preg->EP_REGS[num].EP_LEN_DCNT, 0);
- _nbu2ss_bitclr(&preg->EP_REGS[num].EP_DMA_CTRL, EPn_BURST_SET);
+ _nbu2ss_bitclr(&preg->EP_REGS[num].EP_DMA_CTRL, EPN_BURST_SET);
} else {
_nbu2ss_writel(&preg->EP_REGS[num].EP_LEN_DCNT
, (dmacnt << 16));
- _nbu2ss_bitset(&preg->EP_REGS[num].EP_DMA_CTRL, EPn_BURST_SET);
+ _nbu2ss_bitset(&preg->EP_REGS[num].EP_DMA_CTRL, EPN_BURST_SET);
}
- _nbu2ss_bitset(&preg->EP_REGS[num].EP_DMA_CTRL, EPn_DMA_EN);
+ _nbu2ss_bitset(&preg->EP_REGS[num].EP_DMA_CTRL, EPN_DMA_EN);
result = length & ~(u32)0x03;
req->div_len = result;
@@ -878,12 +881,12 @@ static int _nbu2ss_epn_out_pio(
u32 length
)
{
- u8 *pBuffer;
+ u8 *p_buffer;
u32 i;
u32 data;
- u32 iWordLength;
- union usb_reg_access Temp32;
- union usb_reg_access *pBuf32;
+ u32 i_word_length;
+ union usb_reg_access temp_32;
+ union usb_reg_access *p_buf_32;
int result = 0;
struct fc_regs *preg = udc->p_regs;
@@ -893,28 +896,29 @@ static int _nbu2ss_epn_out_pio(
if (length == 0)
return 0;
- pBuffer = (u8 *)req->req.buf;
- pBuf32 = (union usb_reg_access *)(pBuffer + req->req.actual);
+ p_buffer = (u8 *)req->req.buf;
+ p_buf_32 = (union usb_reg_access *)(p_buffer + req->req.actual);
- iWordLength = length / sizeof(u32);
- if (iWordLength > 0) {
+ i_word_length = length / sizeof(u32);
+ if (i_word_length > 0) {
/*---------------------------------------------------------*/
/* Copy of every four bytes */
- for (i = 0; i < iWordLength; i++) {
- pBuf32->dw =
+ for (i = 0; i < i_word_length; i++) {
+ p_buf_32->dw =
_nbu2ss_readl(&preg->EP_REGS[ep->epnum - 1].EP_READ);
- pBuf32++;
+ p_buf_32++;
}
- result = iWordLength * sizeof(u32);
+ result = i_word_length * sizeof(u32);
}
data = length - result;
if (data > 0) {
/*---------------------------------------------------------*/
/* Copy of fraction byte */
- Temp32.dw = _nbu2ss_readl(&preg->EP_REGS[ep->epnum - 1].EP_READ);
+ temp_32.dw =
+ _nbu2ss_readl(&preg->EP_REGS[ep->epnum - 1].EP_READ);
for (i = 0 ; i < data ; i++)
- pBuf32->byte.DATA[i] = Temp32.byte.DATA[i];
+ p_buf_32->byte.DATA[i] = temp_32.byte.DATA[i];
result += data;
}
@@ -937,7 +941,7 @@ static int _nbu2ss_epn_out_data(
)
{
u32 num;
- u32 iBufSize;
+ u32 i_buf_size;
int nret = 1;
if (ep->epnum == 0)
@@ -945,14 +949,14 @@ static int _nbu2ss_epn_out_data(
num = ep->epnum - 1;
- iBufSize = min((req->req.length - req->req.actual), data_size);
+ i_buf_size = min((req->req.length - req->req.actual), data_size);
if ((ep->ep_type != USB_ENDPOINT_XFER_INT) && (req->req.dma != 0) &&
- (iBufSize >= sizeof(u32))) {
- nret = _nbu2ss_out_dma(udc, req, num, iBufSize);
+ (i_buf_size >= sizeof(u32))) {
+ nret = _nbu2ss_out_dma(udc, req, num, i_buf_size);
} else {
- iBufSize = min_t(u32, iBufSize, ep->ep.maxpacket);
- nret = _nbu2ss_epn_out_pio(udc, ep, req, iBufSize);
+ i_buf_size = min_t(u32, i_buf_size, ep->ep.maxpacket);
+ nret = _nbu2ss_epn_out_pio(udc, ep, req, i_buf_size);
}
return nret;
@@ -966,7 +970,7 @@ static int _nbu2ss_epn_out_transfer(
)
{
u32 num;
- u32 iRecvLength;
+ u32 i_recv_length;
int result = 1;
struct fc_regs *preg = udc->p_regs;
@@ -977,13 +981,13 @@ static int _nbu2ss_epn_out_transfer(
/*-------------------------------------------------------------*/
/* Receive Length */
- iRecvLength
- = _nbu2ss_readl(&preg->EP_REGS[num].EP_LEN_DCNT) & EPn_LDATA;
+ i_recv_length
+ = _nbu2ss_readl(&preg->EP_REGS[num].EP_LEN_DCNT) & EPN_LDATA;
- if (iRecvLength != 0) {
- result = _nbu2ss_epn_out_data(udc, ep, req, iRecvLength);
- if (iRecvLength < ep->ep.maxpacket) {
- if (iRecvLength == result) {
+ if (i_recv_length != 0) {
+ result = _nbu2ss_epn_out_data(udc, ep, req, i_recv_length);
+ if (i_recv_length < ep->ep.maxpacket) {
+ if (i_recv_length == result) {
req->req.actual += result;
result = 0;
}
@@ -1023,11 +1027,11 @@ static int _nbu2ss_in_dma(
u32 length
)
{
- dma_addr_t pBuffer;
+ dma_addr_t p_buffer;
u32 mpkt; /* MaxPacketSize */
u32 lmpkt; /* Last Packet Data Size */
u32 dmacnt; /* IN Data Size */
- u32 iWriteLength;
+ u32 i_write_length;
u32 data;
int result = -EINVAL;
struct fc_regs *preg = udc->p_regs;
@@ -1042,18 +1046,18 @@ static int _nbu2ss_in_dma(
req->dma_flag = TRUE;
/* MAX Packet Size */
- mpkt = _nbu2ss_readl(&preg->EP_REGS[num].EP_PCKT_ADRS) & EPn_MPKT;
+ mpkt = _nbu2ss_readl(&preg->EP_REGS[num].EP_PCKT_ADRS) & EPN_MPKT;
if ((DMA_MAX_COUNT * mpkt) < length)
- iWriteLength = DMA_MAX_COUNT * mpkt;
+ i_write_length = DMA_MAX_COUNT * mpkt;
else
- iWriteLength = length;
+ i_write_length = length;
/*------------------------------------------------------------*/
/* Number of transmission packets */
- if (mpkt < iWriteLength) {
- dmacnt = iWriteLength / mpkt;
- lmpkt = (iWriteLength % mpkt) & ~(u32)0x3;
+ if (mpkt < i_write_length) {
+ dmacnt = i_write_length / mpkt;
+ lmpkt = (i_write_length % mpkt) & ~(u32)0x3;
if (lmpkt != 0)
dmacnt++;
else
@@ -1061,7 +1065,7 @@ static int _nbu2ss_in_dma(
} else {
dmacnt = 1;
- lmpkt = iWriteLength & ~(u32)0x3;
+ lmpkt = i_write_length & ~(u32)0x3;
}
/* Packet setting */
@@ -1069,12 +1073,12 @@ static int _nbu2ss_in_dma(
_nbu2ss_writel(&preg->EP_DCR[num].EP_DCR2, data);
/* Address setting */
- pBuffer = req->req.dma;
- pBuffer += req->req.actual;
- _nbu2ss_writel(&preg->EP_DCR[num].EP_TADR, (u32)pBuffer);
+ p_buffer = req->req.dma;
+ p_buffer += req->req.actual;
+ _nbu2ss_writel(&preg->EP_DCR[num].EP_TADR, (u32)p_buffer);
/* Packet and DMA setting */
- data = ((dmacnt & 0xff) << 16) | DCR1_EPn_REQEN;
+ data = ((dmacnt & 0xff) << 16) | DCR1_EPN_REQEN;
_nbu2ss_writel(&preg->EP_DCR[num].EP_DCR1, data);
/* Packet setting of EPC */
@@ -1082,9 +1086,9 @@ static int _nbu2ss_in_dma(
_nbu2ss_writel(&preg->EP_REGS[num].EP_LEN_DCNT, data);
/*DMA setting of EPC */
- _nbu2ss_bitset(&preg->EP_REGS[num].EP_DMA_CTRL, EPn_DMA_EN);
+ _nbu2ss_bitset(&preg->EP_REGS[num].EP_DMA_CTRL, EPN_DMA_EN);
- result = iWriteLength & ~(u32)0x3;
+ result = i_write_length & ~(u32)0x3;
req->div_len = result;
return result;
@@ -1098,12 +1102,12 @@ static int _nbu2ss_epn_in_pio(
u32 length
)
{
- u8 *pBuffer;
+ u8 *p_buffer;
u32 i;
u32 data;
- u32 iWordLength;
- union usb_reg_access Temp32;
- union usb_reg_access *pBuf32 = NULL;
+ u32 i_word_length;
+ union usb_reg_access temp_32;
+ union usb_reg_access *p_buf_32 = NULL;
int result = 0;
struct fc_regs *preg = udc->p_regs;
@@ -1111,30 +1115,30 @@ static int _nbu2ss_epn_in_pio(
return 1; /* DMA is forwarded */
if (length > 0) {
- pBuffer = (u8 *)req->req.buf;
- pBuf32 = (union usb_reg_access *)(pBuffer + req->req.actual);
+ p_buffer = (u8 *)req->req.buf;
+ p_buf_32 = (union usb_reg_access *)(p_buffer + req->req.actual);
- iWordLength = length / sizeof(u32);
- if (iWordLength > 0) {
- for (i = 0; i < iWordLength; i++) {
+ i_word_length = length / sizeof(u32);
+ if (i_word_length > 0) {
+ for (i = 0; i < i_word_length; i++) {
_nbu2ss_writel(
&preg->EP_REGS[ep->epnum - 1].EP_WRITE
- , pBuf32->dw
+ , p_buf_32->dw
);
- pBuf32++;
+ p_buf_32++;
}
- result = iWordLength * sizeof(u32);
+ result = i_word_length * sizeof(u32);
}
}
if (result != ep->ep.maxpacket) {
data = length - result;
- Temp32.dw = 0;
+ temp_32.dw = 0;
for (i = 0 ; i < data ; i++)
- Temp32.byte.DATA[i] = pBuf32->byte.DATA[i];
+ temp_32.byte.DATA[i] = p_buf_32->byte.DATA[i];
- _nbu2ss_ep_in_end(udc, ep->epnum, Temp32.dw, data);
+ _nbu2ss_ep_in_end(udc, ep->epnum, temp_32.dw, data);
result += data;
}
@@ -1178,7 +1182,7 @@ static int _nbu2ss_epn_in_transfer(
)
{
u32 num;
- u32 iBufSize;
+ u32 i_buf_size;
int result = 0;
u32 status;
@@ -1192,19 +1196,19 @@ static int _nbu2ss_epn_in_transfer(
/*-------------------------------------------------------------*/
/* State confirmation of FIFO */
if (req->req.actual == 0) {
- if ((status & EPn_IN_EMPTY) == 0)
+ if ((status & EPN_IN_EMPTY) == 0)
return 1; /* Not Empty */
} else {
- if ((status & EPn_IN_FULL) != 0)
+ if ((status & EPN_IN_FULL) != 0)
return 1; /* Not Empty */
}
/*-------------------------------------------------------------*/
/* Start transfer */
- iBufSize = req->req.length - req->req.actual;
- if (iBufSize > 0)
- result = _nbu2ss_epn_in_data(udc, ep, req, iBufSize);
+ i_buf_size = req->req.length - req->req.actual;
+ if (i_buf_size > 0)
+ result = _nbu2ss_epn_in_data(udc, ep, req, i_buf_size);
else if (req->req.length == 0)
_nbu2ss_zero_len_pkt(udc, ep->epnum);
@@ -1252,7 +1256,7 @@ static int _nbu2ss_start_transfer(
}
} else {
- /* EPn */
+ /* EPN */
if (ep->direct == USB_DIR_OUT) {
/* OUT */
if (!bflag)
@@ -1281,7 +1285,7 @@ static void _nbu2ss_restert_transfer(struct nbu2ss_ep *ep)
length = _nbu2ss_readl(
&ep->udc->p_regs->EP_REGS[ep->epnum - 1].EP_LEN_DCNT);
- length &= EPn_LDATA;
+ length &= EPN_LDATA;
if (length < ep->ep.maxpacket)
bflag = TRUE;
}
@@ -1304,9 +1308,9 @@ static void _nbu2ss_endpoint_toggle_reset(
num = (ep_adrs & 0x7F) - 1;
if (ep_adrs & USB_DIR_IN)
- data = EPn_IPIDCLR;
+ data = EPN_IPIDCLR;
else
- data = EPn_BCLR | EPn_OPIDCLR;
+ data = EPN_BCLR | EPN_OPIDCLR;
_nbu2ss_bitset(&udc->p_regs->EP_REGS[num].EP_CONTROL, data);
}
@@ -1341,9 +1345,9 @@ static void _nbu2ss_set_endpoint_stall(
ep->halted = TRUE;
if (ep_adrs & USB_DIR_IN)
- data = EPn_BCLR | EPn_ISTL;
+ data = EPN_BCLR | EPN_ISTL;
else
- data = EPn_OSTL_EN | EPn_OSTL;
+ data = EPN_OSTL_EN | EPN_OSTL;
_nbu2ss_bitset(&preg->EP_REGS[num].EP_CONTROL, data);
} else {
@@ -1351,13 +1355,13 @@ static void _nbu2ss_set_endpoint_stall(
ep->stalled = FALSE;
if (ep_adrs & USB_DIR_IN) {
_nbu2ss_bitclr(&preg->EP_REGS[num].EP_CONTROL
- , EPn_ISTL);
+ , EPN_ISTL);
} else {
data =
_nbu2ss_readl(&preg->EP_REGS[num].EP_CONTROL);
- data &= ~EPn_OSTL;
- data |= EPn_OSTL_EN;
+ data &= ~EPN_OSTL;
+ data |= EPN_OSTL_EN;
_nbu2ss_writel(&preg->EP_REGS[num].EP_CONTROL
, data);
@@ -1453,13 +1457,13 @@ static int _nbu2ss_get_ep_stall(struct nbu2ss_udc *udc, u8 ep_adrs)
} else {
data = _nbu2ss_readl(&preg->EP_REGS[epnum - 1].EP_CONTROL);
- if ((data & EPn_EN) == 0)
+ if ((data & EPN_EN) == 0)
return -1;
if (ep_adrs & USB_ENDPOINT_DIR_MASK)
- bit_data = EPn_ISTL;
+ bit_data = EPN_ISTL;
else
- bit_data = EPn_OSTL;
+ bit_data = EPN_OSTL;
}
if ((data & bit_data) == 0)
@@ -1548,7 +1552,7 @@ static void _nbu2ss_epn_set_stall(
regdata = _nbu2ss_readl(
&preg->EP_REGS[ep->epnum - 1].EP_STATUS);
- if ((regdata & EPn_IN_DATA) == 0)
+ if ((regdata & EPN_IN_DATA) == 0)
break;
mdelay(1);
@@ -1651,7 +1655,7 @@ static int std_req_set_address(struct nbu2ss_udc *udc)
/*-------------------------------------------------------------------------*/
static int std_req_set_configuration(struct nbu2ss_udc *udc)
{
- u32 ConfigValue = (u32)(udc->ctrl.wValue & 0x00ff);
+ u32 config_value = (u32)(udc->ctrl.wValue & 0x00ff);
if ((udc->ctrl.wIndex != 0x0000) ||
(udc->ctrl.wLength != 0x0000) ||
@@ -1659,9 +1663,9 @@ static int std_req_set_configuration(struct nbu2ss_udc *udc)
return -EINVAL;
}
- udc->curr_config = ConfigValue;
+ udc->curr_config = config_value;
- if (ConfigValue > 0) {
+ if (config_value > 0) {
_nbu2ss_bitset(&udc->p_regs->USB_CONTROL, CONF);
udc->devstate = USB_STATE_CONFIGURED;
@@ -1968,7 +1972,7 @@ static inline void _nbu2ss_epn_in_int(
status =
_nbu2ss_readl(&preg->EP_REGS[ep->epnum - 1].EP_STATUS);
- if ((status & EPn_IN_FULL) == 0) {
+ if ((status & EPN_IN_FULL) == 0) {
/*-----------------------------------------*/
/* 0 Length Packet */
req->zero = false;
@@ -2059,18 +2063,18 @@ static inline void _nbu2ss_epn_out_dma_int(
}
ep_dmacnt = _nbu2ss_readl(&preg->EP_REGS[num].EP_LEN_DCNT)
- & EPn_DMACNT;
+ & EPN_DMACNT;
ep_dmacnt >>= 16;
for (i = 0; i < EPC_PLL_LOCK_COUNT; i++) {
dmacnt = _nbu2ss_readl(&preg->EP_DCR[num].EP_DCR1)
- & DCR1_EPn_DMACNT;
+ & DCR1_EPN_DMACNT;
dmacnt >>= 16;
if (ep_dmacnt == dmacnt)
break;
}
- _nbu2ss_bitclr(&preg->EP_DCR[num].EP_DCR1, DCR1_EPn_REQEN);
+ _nbu2ss_bitclr(&preg->EP_DCR[num].EP_DCR1, DCR1_EPN_REQEN);
if (dmacnt != 0) {
mpkt = ep->ep.maxpacket;
@@ -2117,20 +2121,20 @@ static inline void _nbu2ss_epn_int(struct nbu2ss_udc *udc, u32 epnum)
return;
}
- if (status & EPn_OUT_END_INT) {
- status &= ~EPn_OUT_INT;
+ if (status & EPN_OUT_END_INT) {
+ status &= ~EPN_OUT_INT;
_nbu2ss_epn_out_dma_int(udc, ep, req);
}
- if (status & EPn_OUT_INT)
+ if (status & EPN_OUT_INT)
_nbu2ss_epn_out_int(udc, ep, req);
- if (status & EPn_IN_END_INT) {
- status &= ~EPn_IN_INT;
+ if (status & EPN_IN_END_INT) {
+ status &= ~EPN_IN_INT;
_nbu2ss_epn_in_dma_int(udc, ep, req);
}
- if (status & EPn_IN_INT)
+ if (status & EPN_IN_INT)
_nbu2ss_epn_in_int(udc, ep, req);
}
@@ -2231,9 +2235,9 @@ static void _nbu2ss_fifo_flush(struct nbu2ss_udc *udc, struct nbu2ss_ep *ep)
_nbu2ss_bitset(&p->EP0_CONTROL, EP0_BCLR);
} else {
- /* EPn */
+ /* EPN */
_nbu2ss_ep_dma_abort(udc, ep);
- _nbu2ss_bitset(&p->EP_REGS[ep->epnum - 1].EP_CONTROL, EPn_BCLR);
+ _nbu2ss_bitset(&p->EP_REGS[ep->epnum - 1].EP_CONTROL, EPN_BCLR);
}
}
@@ -2478,7 +2482,7 @@ static irqreturn_t _nbu2ss_udc_irq(int irq, void *_udc)
suspend_flag = 1;
}
- if (status & EPn_INT) {
+ if (status & EPN_INT) {
/* EP INT */
int_bit = status >> 8;
@@ -2651,7 +2655,9 @@ static int nbu2ss_ep_queue(
}
req = container_of(_req, struct nbu2ss_req, req);
- if (unlikely(!_req->complete || !_req->buf || !list_empty(&req->queue))) {
+ if (unlikely(!_req->complete ||
+ !_req->buf ||
+ !list_empty(&req->queue))) {
if (!_req->complete)
pr_err("udc: %s --- !_req->complete\n", __func__);
@@ -2868,7 +2874,7 @@ static int nbu2ss_ep_fifo_status(struct usb_ep *_ep)
} else {
data = _nbu2ss_readl(&preg->EP_REGS[ep->epnum - 1].EP_LEN_DCNT)
- & EPn_LDATA;
+ & EPN_LDATA;
}
spin_unlock_irqrestore(&udc->lock, flags);
diff --git a/drivers/staging/emxx_udc/emxx_udc.h b/drivers/staging/emxx_udc/emxx_udc.h
index 78c08e15a1f9..928d531a5115 100644
--- a/drivers/staging/emxx_udc/emxx_udc.h
+++ b/drivers/staging/emxx_udc/emxx_udc.h
@@ -144,7 +144,7 @@
/*------- (0x001C) Setup Data 1 Register */
/*------- (0x0020) USB Interrupt Status Register */
-#define EPn_INT 0x00FFFF00
+#define EPN_INT 0x00FFFF00
#define EP15_INT BIT23
#define EP14_INT BIT22
#define EP13_INT BIT21
@@ -264,102 +264,102 @@
/*------- (0x0038) EP0 Read Register */
/*------- (0x003C) EP0 Write Register */
-/*------- (0x0040:) EPn Control Register */
-#define EPn_EN BIT31
-#define EPn_BUF_TYPE BIT30
-#define EPn_BUF_SINGLE BIT30
-
-#define EPn_DIR0 BIT26
-#define EPn_MODE (BIT25 + BIT24)
-#define EPn_BULK 0
-#define EPn_INTERRUPT BIT24
-#define EPn_ISO BIT25
-
-#define EPn_OVERSEL BIT17
-#define EPn_AUTO BIT16
-
-#define EPn_IPIDCLR BIT11
-#define EPn_OPIDCLR BIT10
-#define EPn_BCLR BIT09
-#define EPn_CBCLR BIT08
-#define EPn_DEND BIT07
-#define EPn_DW (BIT06 + BIT05)
-#define EPn_DW4 0
-#define EPn_DW3 (BIT06 + BIT05)
-#define EPn_DW2 BIT06
-#define EPn_DW1 BIT05
-
-#define EPn_OSTL_EN BIT04
-#define EPn_ISTL BIT03
-#define EPn_OSTL BIT02
-
-#define EPn_ONAK BIT00
-
-/*------- (0x0044:) EPn Status Register */
-#define EPn_ISO_PIDERR BIT29 /* R */
-#define EPn_OPID BIT28 /* R */
-#define EPn_OUT_NOTKN BIT27 /* R */
-#define EPn_ISO_OR BIT26 /* R */
-
-#define EPn_ISO_CRC BIT24 /* R */
-#define EPn_OUT_END_INT BIT23 /* RW */
-#define EPn_OUT_OR_INT BIT22 /* RW */
-#define EPn_OUT_NAK_ERR_INT BIT21 /* RW */
-#define EPn_OUT_STALL_INT BIT20 /* RW */
-#define EPn_OUT_INT BIT19 /* RW */
-#define EPn_OUT_NULL_INT BIT18 /* RW */
-#define EPn_OUT_FULL BIT17 /* R */
-#define EPn_OUT_EMPTY BIT16 /* R */
-
-#define EPn_IPID BIT10 /* R */
-#define EPn_IN_NOTKN BIT09 /* R */
-#define EPn_ISO_UR BIT08 /* R */
-#define EPn_IN_END_INT BIT07 /* RW */
-
-#define EPn_IN_NAK_ERR_INT BIT05 /* RW */
-#define EPn_IN_STALL_INT BIT04 /* RW */
-#define EPn_IN_INT BIT03 /* RW */
-#define EPn_IN_DATA BIT02 /* R */
-#define EPn_IN_FULL BIT01 /* R */
-#define EPn_IN_EMPTY BIT00 /* R */
-
-#define EPn_INT_EN \
- (EPn_OUT_END_INT | EPn_OUT_INT | EPn_IN_END_INT | EPn_IN_INT)
-
-/*------- (0x0048:) EPn Interrupt Enable Register */
-#define EPn_OUT_END_EN BIT23 /* RW */
-#define EPn_OUT_OR_EN BIT22 /* RW */
-#define EPn_OUT_NAK_ERR_EN BIT21 /* RW */
-#define EPn_OUT_STALL_EN BIT20 /* RW */
-#define EPn_OUT_EN BIT19 /* RW */
-#define EPn_OUT_NULL_EN BIT18 /* RW */
-
-#define EPn_IN_END_EN BIT07 /* RW */
-
-#define EPn_IN_NAK_ERR_EN BIT05 /* RW */
-#define EPn_IN_STALL_EN BIT04 /* RW */
-#define EPn_IN_EN BIT03 /* RW */
-
-/*------- (0x004C:) EPn Interrupt Enable Register */
-#define EPn_STOP_MODE BIT11
-#define EPn_DEND_SET BIT10
-#define EPn_BURST_SET BIT09
-#define EPn_STOP_SET BIT08
-
-#define EPn_DMA_EN BIT04
-
-#define EPn_DMAMODE0 BIT00
-
-/*------- (0x0050:) EPn MaxPacket & BaseAddress Register */
-#define EPn_BASEAD 0x1FFF0000
-#define EPn_MPKT 0x000007FF
-
-/*------- (0x0054:) EPn Length & DMA Count Register */
-#define EPn_DMACNT 0x01FF0000
-#define EPn_LDATA 0x000007FF
-
-/*------- (0x0058:) EPn Read Register */
-/*------- (0x005C:) EPn Write Register */
+/*------- (0x0040:) EPN Control Register */
+#define EPN_EN BIT31
+#define EPN_BUF_TYPE BIT30
+#define EPN_BUF_SINGLE BIT30
+
+#define EPN_DIR0 BIT26
+#define EPN_MODE (BIT25 + BIT24)
+#define EPN_BULK 0
+#define EPN_INTERRUPT BIT24
+#define EPN_ISO BIT25
+
+#define EPN_OVERSEL BIT17
+#define EPN_AUTO BIT16
+
+#define EPN_IPIDCLR BIT11
+#define EPN_OPIDCLR BIT10
+#define EPN_BCLR BIT09
+#define EPN_CBCLR BIT08
+#define EPN_DEND BIT07
+#define EPN_DW (BIT06 + BIT05)
+#define EPN_DW4 0
+#define EPN_DW3 (BIT06 + BIT05)
+#define EPN_DW2 BIT06
+#define EPN_DW1 BIT05
+
+#define EPN_OSTL_EN BIT04
+#define EPN_ISTL BIT03
+#define EPN_OSTL BIT02
+
+#define EPN_ONAK BIT00
+
+/*------- (0x0044:) EPN Status Register */
+#define EPN_ISO_PIDERR BIT29 /* R */
+#define EPN_OPID BIT28 /* R */
+#define EPN_OUT_NOTKN BIT27 /* R */
+#define EPN_ISO_OR BIT26 /* R */
+
+#define EPN_ISO_CRC BIT24 /* R */
+#define EPN_OUT_END_INT BIT23 /* RW */
+#define EPN_OUT_OR_INT BIT22 /* RW */
+#define EPN_OUT_NAK_ERR_INT BIT21 /* RW */
+#define EPN_OUT_STALL_INT BIT20 /* RW */
+#define EPN_OUT_INT BIT19 /* RW */
+#define EPN_OUT_NULL_INT BIT18 /* RW */
+#define EPN_OUT_FULL BIT17 /* R */
+#define EPN_OUT_EMPTY BIT16 /* R */
+
+#define EPN_IPID BIT10 /* R */
+#define EPN_IN_NOTKN BIT09 /* R */
+#define EPN_ISO_UR BIT08 /* R */
+#define EPN_IN_END_INT BIT07 /* RW */
+
+#define EPN_IN_NAK_ERR_INT BIT05 /* RW */
+#define EPN_IN_STALL_INT BIT04 /* RW */
+#define EPN_IN_INT BIT03 /* RW */
+#define EPN_IN_DATA BIT02 /* R */
+#define EPN_IN_FULL BIT01 /* R */
+#define EPN_IN_EMPTY BIT00 /* R */
+
+#define EPN_INT_EN \
+ (EPN_OUT_END_INT | EPN_OUT_INT | EPN_IN_END_INT | EPN_IN_INT)
+
+/*------- (0x0048:) EPN Interrupt Enable Register */
+#define EPN_OUT_END_EN BIT23 /* RW */
+#define EPN_OUT_OR_EN BIT22 /* RW */
+#define EPN_OUT_NAK_ERR_EN BIT21 /* RW */
+#define EPN_OUT_STALL_EN BIT20 /* RW */
+#define EPN_OUT_EN BIT19 /* RW */
+#define EPN_OUT_NULL_EN BIT18 /* RW */
+
+#define EPN_IN_END_EN BIT07 /* RW */
+
+#define EPN_IN_NAK_ERR_EN BIT05 /* RW */
+#define EPN_IN_STALL_EN BIT04 /* RW */
+#define EPN_IN_EN BIT03 /* RW */
+
+/*------- (0x004C:) EPN Interrupt Enable Register */
+#define EPN_STOP_MODE BIT11
+#define EPN_DEND_SET BIT10
+#define EPN_BURST_SET BIT09
+#define EPN_STOP_SET BIT08
+
+#define EPN_DMA_EN BIT04
+
+#define EPN_DMAMODE0 BIT00
+
+/*------- (0x0050:) EPN MaxPacket & BaseAddress Register */
+#define EPN_BASEAD 0x1FFF0000
+#define EPN_MPKT 0x000007FF
+
+/*------- (0x0054:) EPN Length & DMA Count Register */
+#define EPN_DMACNT 0x01FF0000
+#define EPN_LDATA 0x000007FF
+
+/*------- (0x0058:) EPN Read Register */
+/*------- (0x005C:) EPN Write Register */
/*------- (0x1000) AHBSCTR Register */
#define WAIT_MODE BIT00
@@ -428,19 +428,19 @@
#define EP_AVAILABLE 0xFFFF0000 /* R */
#define DMA_AVAILABLE 0x0000FFFF /* R */
-/*------- (0x1110:) EPnDCR1 Register */
-#define DCR1_EPn_DMACNT 0x00FF0000 /* RW */
+/*------- (0x1110:) EPNDCR1 Register */
+#define DCR1_EPN_DMACNT 0x00FF0000 /* RW */
-#define DCR1_EPn_DIR0 BIT01 /* RW */
-#define DCR1_EPn_REQEN BIT00 /* RW */
+#define DCR1_EPN_DIR0 BIT01 /* RW */
+#define DCR1_EPN_REQEN BIT00 /* RW */
-/*------- (0x1114:) EPnDCR2 Register */
-#define DCR2_EPn_LMPKT 0x07FF0000 /* RW */
+/*------- (0x1114:) EPNDCR2 Register */
+#define DCR2_EPN_LMPKT 0x07FF0000 /* RW */
-#define DCR2_EPn_MPKT 0x000007FF /* RW */
+#define DCR2_EPN_MPKT 0x000007FF /* RW */
-/*------- (0x1118:) EPnTADR Register */
-#define EPn_TADR 0xFFFFFFFF /* RW */
+/*------- (0x1118:) EPNTADR Register */
+#define EPN_TADR 0xFFFFFFFF /* RW */
/*===========================================================================*/
/* Struct */
@@ -471,7 +471,7 @@ struct fc_regs {
u32 USB_ADDRESS; /* (0x0008) USB Address */
u32 UTMI_CHARACTER_1; /* (0x000C) UTMI Setting */
u32 TEST_CONTROL; /* (0x0010) TEST Control */
- u32 Reserved_14; /* (0x0014) Reserved */
+ u32 reserved_14; /* (0x0014) Reserved */
u32 SETUP_DATA0; /* (0x0018) Setup Data0 */
u32 SETUP_DATA1; /* (0x001C) Setup Data1 */
u32 USB_INT_STA; /* (0x0020) USB Interrupt Status */
@@ -485,7 +485,7 @@ struct fc_regs {
struct ep_regs EP_REGS[REG_EP_NUM]; /* Endpoint Register */
- u8 Reserved220[0x1000 - 0x220]; /* (0x0220:0x0FFF) Reserved */
+ u8 reserved_220[0x1000 - 0x220]; /* (0x0220:0x0FFF) Reserved */
u32 AHBSCTR; /* (0x1000) AHBSCTR */
u32 AHBMCTR; /* (0x1004) AHBMCTR */
@@ -494,25 +494,25 @@ struct fc_regs {
u32 EPCTR; /* (0x1010) EPCTR */
u32 USBF_EPTEST; /* (0x1014) USBF_EPTEST */
- u8 Reserved1018[0x20 - 0x18]; /* (0x1018:0x101F) Reserved */
+ u8 reserved_1018[0x20 - 0x18]; /* (0x1018:0x101F) Reserved */
u32 USBSSVER; /* (0x1020) USBSSVER */
u32 USBSSCONF; /* (0x1024) USBSSCONF */
- u8 Reserved1028[0x110 - 0x28]; /* (0x1028:0x110F) Reserved */
+ u8 reserved_1028[0x110 - 0x28]; /* (0x1028:0x110F) Reserved */
struct ep_dcr EP_DCR[REG_EP_NUM]; /* */
- u8 Reserved1200[0x1000 - 0x200]; /* Reserved */
+ u8 reserved_1200[0x1000 - 0x200]; /* Reserved */
} __aligned(32);
#define EP0_PACKETSIZE 64
#define EP_PACKETSIZE 1024
-/* EPn RAM SIZE */
+/* EPN RAM SIZE */
#define D_RAM_SIZE_CTRL 64
-/* EPn Bulk Endpoint Max Packet Size */
+/* EPN Bulk Endpoint Max Packet Size */
#define D_FS_RAM_SIZE_BULK 64
#define D_HS_RAM_SIZE_BULK 512
diff --git a/drivers/staging/fbtft/fb_agm1264k-fl.c b/drivers/staging/fbtft/fb_agm1264k-fl.c
index 489151a6bf80..456a8dd65caf 100644
--- a/drivers/staging/fbtft/fb_agm1264k-fl.c
+++ b/drivers/staging/fbtft/fb_agm1264k-fl.c
@@ -282,10 +282,10 @@ static void iterate_diffusion_matrix(u32 xres, u32 yres, int x,
continue;
write_pos = &convert_buf[(y + j) * xres + x + i];
coeff = diffusing_matrix[i][j];
- if (-1 == coeff)
+ if (-1 == coeff) {
/* pixel itself */
*write_pos = pixel;
- else {
+ } else {
signed short p = *write_pos + error * coeff;
if (p > WHITE)
diff --git a/drivers/staging/fbtft/fb_hx8340bn.c b/drivers/staging/fbtft/fb_hx8340bn.c
index 1ca1fcd353d6..fbd5ef525243 100644
--- a/drivers/staging/fbtft/fb_hx8340bn.c
+++ b/drivers/staging/fbtft/fb_hx8340bn.c
@@ -157,7 +157,7 @@ static int set_var(struct fbtft_par *par)
* OP0 OP1 CP0 CP1 CP2 CP3 CP4 MP0 MP1 MP2 MP3 MP4 MP5 CGM0 CGM1
* ON0 ON1 CN0 CN1 CN2 CN3 CN4 MN0 MN1 MN2 MN3 MN4 MN5 XXXX GC
*/
-#define CURVE(num, idx) curves[num * par->gamma.num_values + idx]
+#define CURVE(num, idx) curves[(num) * par->gamma.num_values + (idx)]
static int set_gamma(struct fbtft_par *par, u32 *curves)
{
unsigned long mask[] = {
diff --git a/drivers/staging/fbtft/fbtft-io.c b/drivers/staging/fbtft/fbtft-io.c
index d86840548b74..ffb9a3b4d454 100644
--- a/drivers/staging/fbtft/fbtft-io.c
+++ b/drivers/staging/fbtft/fbtft-io.c
@@ -71,7 +71,7 @@ int fbtft_write_spi_emulate_9(struct fbtft_par *par, void *buf, size_t len)
src++;
}
tmp |= ((*src & 0x0100) ? 1 : 0);
- *(u64 *)dst = cpu_to_be64(tmp);
+ *(__be64 *)dst = cpu_to_be64(tmp);
dst += 8;
*dst++ = (u8)(*src++ & 0x00FF);
added++;
diff --git a/drivers/staging/fsl-dpaa2/ethernet/dpaa2-eth.c b/drivers/staging/fsl-dpaa2/ethernet/dpaa2-eth.c
index 6f9eed66c64d..b9a0a315e6fb 100644
--- a/drivers/staging/fsl-dpaa2/ethernet/dpaa2-eth.c
+++ b/drivers/staging/fsl-dpaa2/ethernet/dpaa2-eth.c
@@ -37,9 +37,9 @@
#include <linux/interrupt.h>
#include <linux/msi.h>
#include <linux/kthread.h>
+#include <linux/iommu.h>
#include "../../fsl-mc/include/mc.h"
-#include "../../fsl-mc/include/mc-sys.h"
#include "dpaa2-eth.h"
/* CREATE_TRACE_POINTS only needs to be defined once. Other dpa files
@@ -54,6 +54,16 @@ MODULE_DESCRIPTION("Freescale DPAA2 Ethernet Driver");
const char dpaa2_eth_drv_version[] = "0.1";
+static void *dpaa2_iova_to_virt(struct iommu_domain *domain,
+ dma_addr_t iova_addr)
+{
+ phys_addr_t phys_addr;
+
+ phys_addr = domain ? iommu_iova_to_phys(domain, iova_addr) : iova_addr;
+
+ return phys_to_virt(phys_addr);
+}
+
static void validate_rx_csum(struct dpaa2_eth_priv *priv,
u32 fd_status,
struct sk_buff *skb)
@@ -98,12 +108,11 @@ static void free_rx_fd(struct dpaa2_eth_priv *priv,
sgt = vaddr + dpaa2_fd_get_offset(fd);
for (i = 0; i < DPAA2_ETH_MAX_SG_ENTRIES; i++) {
addr = dpaa2_sg_get_addr(&sgt[i]);
+ sg_vaddr = dpaa2_iova_to_virt(priv->iommu_domain, addr);
dma_unmap_single(dev, addr, DPAA2_ETH_RX_BUF_SIZE,
DMA_FROM_DEVICE);
- sg_vaddr = phys_to_virt(addr);
skb_free_frag(sg_vaddr);
-
if (dpaa2_sg_is_final(&sgt[i]))
break;
}
@@ -159,10 +168,10 @@ static struct sk_buff *build_frag_skb(struct dpaa2_eth_priv *priv,
/* Get the address and length from the S/G entry */
sg_addr = dpaa2_sg_get_addr(sge);
+ sg_vaddr = dpaa2_iova_to_virt(priv->iommu_domain, sg_addr);
dma_unmap_single(dev, sg_addr, DPAA2_ETH_RX_BUF_SIZE,
DMA_FROM_DEVICE);
- sg_vaddr = phys_to_virt(sg_addr);
sg_length = dpaa2_sg_get_len(sge);
if (i == 0) {
@@ -217,16 +226,19 @@ static void dpaa2_eth_rx(struct dpaa2_eth_priv *priv,
struct dpaa2_eth_drv_stats *percpu_extras;
struct device *dev = priv->net_dev->dev.parent;
struct dpaa2_fas *fas;
+ void *buf_data;
u32 status = 0;
/* Tracing point */
trace_dpaa2_rx_fd(priv->net_dev, fd);
+ vaddr = dpaa2_iova_to_virt(priv->iommu_domain, addr);
dma_unmap_single(dev, addr, DPAA2_ETH_RX_BUF_SIZE, DMA_FROM_DEVICE);
- vaddr = phys_to_virt(addr);
- prefetch(vaddr + priv->buf_layout.private_data_size);
- prefetch(vaddr + dpaa2_fd_get_offset(fd));
+ fas = dpaa2_get_fas(vaddr);
+ prefetch(fas);
+ buf_data = vaddr + dpaa2_fd_get_offset(fd);
+ prefetch(buf_data);
percpu_stats = this_cpu_ptr(priv->percpu_stats);
percpu_extras = this_cpu_ptr(priv->percpu_extras);
@@ -234,9 +246,7 @@ static void dpaa2_eth_rx(struct dpaa2_eth_priv *priv,
if (fd_format == dpaa2_fd_single) {
skb = build_linear_skb(priv, ch, fd, vaddr);
} else if (fd_format == dpaa2_fd_sg) {
- struct dpaa2_sg_entry *sgt =
- vaddr + dpaa2_fd_get_offset(fd);
- skb = build_frag_skb(priv, ch, sgt);
+ skb = build_frag_skb(priv, ch, buf_data);
skb_free_frag(vaddr);
percpu_extras->rx_sg_frames++;
percpu_extras->rx_sg_bytes += dpaa2_fd_get_len(fd);
@@ -252,8 +262,6 @@ static void dpaa2_eth_rx(struct dpaa2_eth_priv *priv,
/* Check if we need to validate the L4 csum */
if (likely(dpaa2_fd_get_frc(fd) & DPAA2_FD_FRC_FASV)) {
- fas = (struct dpaa2_fas *)
- (vaddr + priv->buf_layout.private_data_size);
status = le32_to_cpu(fas->status);
validate_rx_csum(priv, status, skb);
}
@@ -263,10 +271,7 @@ static void dpaa2_eth_rx(struct dpaa2_eth_priv *priv,
percpu_stats->rx_packets++;
percpu_stats->rx_bytes += dpaa2_fd_get_len(fd);
- if (priv->net_dev->features & NETIF_F_GRO)
- napi_gro_receive(napi, skb);
- else
- netif_receive_skb(skb);
+ napi_gro_receive(napi, skb);
return;
@@ -320,7 +325,6 @@ static int build_sg_fd(struct dpaa2_eth_priv *priv,
{
struct device *dev = priv->net_dev->dev.parent;
void *sgt_buf = NULL;
- void *hwa;
dma_addr_t addr;
int nr_frags = skb_shinfo(skb)->nr_frags;
struct dpaa2_sg_entry *sgt;
@@ -330,6 +334,7 @@ static int build_sg_fd(struct dpaa2_eth_priv *priv,
int num_sg;
int num_dma_bufs;
struct dpaa2_eth_swa *swa;
+ struct dpaa2_fas *fas;
/* Create and map scatterlist.
* We don't advertise NETIF_F_FRAGLIST, so skb_to_sgvec() will not have
@@ -345,7 +350,7 @@ static int build_sg_fd(struct dpaa2_eth_priv *priv,
sg_init_table(scl, nr_frags + 1);
num_sg = skb_to_sgvec(skb, scl, 0, skb->len);
- num_dma_bufs = dma_map_sg(dev, scl, num_sg, DMA_TO_DEVICE);
+ num_dma_bufs = dma_map_sg(dev, scl, num_sg, DMA_BIDIRECTIONAL);
if (unlikely(!num_dma_bufs)) {
err = -ENOMEM;
goto dma_map_sg_failed;
@@ -366,8 +371,8 @@ static int build_sg_fd(struct dpaa2_eth_priv *priv,
* on TX confirmation. We are clearing FAS (Frame Annotation Status)
* field from the hardware annotation area
*/
- hwa = sgt_buf + priv->buf_layout.private_data_size;
- memset(hwa + DPAA2_FAS_OFFSET, 0, DPAA2_FAS_SIZE);
+ fas = dpaa2_get_fas(sgt_buf);
+ memset(fas, 0, DPAA2_FAS_SIZE);
sgt = (struct dpaa2_sg_entry *)(sgt_buf + priv->tx_data_offset);
@@ -396,7 +401,7 @@ static int build_sg_fd(struct dpaa2_eth_priv *priv,
swa->num_dma_bufs = num_dma_bufs;
/* Separately map the SGT buffer */
- addr = dma_map_single(dev, sgt_buf, sgt_buf_size, DMA_TO_DEVICE);
+ addr = dma_map_single(dev, sgt_buf, sgt_buf_size, DMA_BIDIRECTIONAL);
if (unlikely(dma_mapping_error(dev, addr))) {
err = -ENOMEM;
goto dma_map_single_failed;
@@ -413,7 +418,7 @@ static int build_sg_fd(struct dpaa2_eth_priv *priv,
dma_map_single_failed:
kfree(sgt_buf);
sgt_buf_alloc_failed:
- dma_unmap_sg(dev, scl, num_sg, DMA_TO_DEVICE);
+ dma_unmap_sg(dev, scl, num_sg, DMA_BIDIRECTIONAL);
dma_map_sg_failed:
kfree(scl);
return err;
@@ -426,7 +431,7 @@ static int build_single_fd(struct dpaa2_eth_priv *priv,
{
struct device *dev = priv->net_dev->dev.parent;
u8 *buffer_start;
- void *hwa;
+ struct dpaa2_fas *fas;
struct sk_buff **skbh;
dma_addr_t addr;
@@ -439,8 +444,8 @@ static int build_single_fd(struct dpaa2_eth_priv *priv,
* on TX confirmation. We are clearing FAS (Frame Annotation Status)
* field from the hardware annotation area
*/
- hwa = buffer_start + priv->buf_layout.private_data_size;
- memset(hwa + DPAA2_FAS_OFFSET, 0, DPAA2_FAS_SIZE);
+ fas = dpaa2_get_fas(buffer_start);
+ memset(fas, 0, DPAA2_FAS_SIZE);
/* Store a backpointer to the skb at the beginning of the buffer
* (in the private data area) such that we can release it
@@ -451,7 +456,7 @@ static int build_single_fd(struct dpaa2_eth_priv *priv,
addr = dma_map_single(dev, buffer_start,
skb_tail_pointer(skb) - buffer_start,
- DMA_TO_DEVICE);
+ DMA_BIDIRECTIONAL);
if (unlikely(dma_mapping_error(dev, addr)))
return -ENOMEM;
@@ -490,7 +495,8 @@ static void free_tx_fd(const struct dpaa2_eth_priv *priv,
struct dpaa2_fas *fas;
fd_addr = dpaa2_fd_get_addr(fd);
- skbh = phys_to_virt(fd_addr);
+ skbh = dpaa2_iova_to_virt(priv->iommu_domain, fd_addr);
+ fas = dpaa2_get_fas(skbh);
if (fd_format == dpaa2_fd_single) {
skb = *skbh;
@@ -500,7 +506,7 @@ static void free_tx_fd(const struct dpaa2_eth_priv *priv,
*/
dma_unmap_single(dev, fd_addr,
skb_tail_pointer(skb) - buffer_start,
- DMA_TO_DEVICE);
+ DMA_BIDIRECTIONAL);
} else if (fd_format == dpaa2_fd_sg) {
swa = (struct dpaa2_eth_swa *)skbh;
skb = swa->skb;
@@ -509,13 +515,13 @@ static void free_tx_fd(const struct dpaa2_eth_priv *priv,
num_dma_bufs = swa->num_dma_bufs;
/* Unmap the scatterlist */
- dma_unmap_sg(dev, scl, num_sg, DMA_TO_DEVICE);
+ dma_unmap_sg(dev, scl, num_sg, DMA_BIDIRECTIONAL);
kfree(scl);
/* Unmap the SGT buffer */
unmap_size = priv->tx_data_offset +
sizeof(struct dpaa2_sg_entry) * (1 + num_dma_bufs);
- dma_unmap_single(dev, fd_addr, unmap_size, DMA_TO_DEVICE);
+ dma_unmap_single(dev, fd_addr, unmap_size, DMA_BIDIRECTIONAL);
} else {
/* Unsupported format, mark it as errored and give up */
if (status)
@@ -527,11 +533,8 @@ static void free_tx_fd(const struct dpaa2_eth_priv *priv,
* buffer but before we free it. The caller function is responsible
* for checking the status value.
*/
- if (status && (dpaa2_fd_get_frc(fd) & DPAA2_FD_FRC_FASV)) {
- fas = (struct dpaa2_fas *)
- ((void *)skbh + priv->buf_layout.private_data_size);
+ if (status)
*status = le32_to_cpu(fas->status);
- }
/* Free SGT buffer kmalloc'ed on tx */
if (fd_format != dpaa2_fd_single)
@@ -541,7 +544,7 @@ static void free_tx_fd(const struct dpaa2_eth_priv *priv,
dev_kfree_skb(skb);
}
-static int dpaa2_eth_tx(struct sk_buff *skb, struct net_device *net_dev)
+static netdev_tx_t dpaa2_eth_tx(struct sk_buff *skb, struct net_device *net_dev)
{
struct dpaa2_eth_priv *priv = netdev_priv(net_dev);
struct dpaa2_fd fd;
@@ -634,6 +637,8 @@ static void dpaa2_eth_tx_conf(struct dpaa2_eth_priv *priv,
struct rtnl_link_stats64 *percpu_stats;
struct dpaa2_eth_drv_stats *percpu_extras;
u32 status = 0;
+ u32 fd_errors;
+ bool has_fas_errors = false;
/* Tracing point */
trace_dpaa2_tx_conf_fd(priv->net_dev, fd);
@@ -642,13 +647,31 @@ static void dpaa2_eth_tx_conf(struct dpaa2_eth_priv *priv,
percpu_extras->tx_conf_frames++;
percpu_extras->tx_conf_bytes += dpaa2_fd_get_len(fd);
- free_tx_fd(priv, fd, &status);
-
- if (unlikely(status & DPAA2_ETH_TXCONF_ERR_MASK)) {
- percpu_stats = this_cpu_ptr(priv->percpu_stats);
- /* Tx-conf logically pertains to the egress path. */
- percpu_stats->tx_errors++;
+ /* Check frame errors in the FD field */
+ fd_errors = dpaa2_fd_get_ctrl(fd) & DPAA2_FD_TX_ERR_MASK;
+ if (unlikely(fd_errors)) {
+ /* We only check error bits in the FAS field if corresponding
+ * FAERR bit is set in FD and the FAS field is marked as valid
+ */
+ has_fas_errors = (fd_errors & DPAA2_FD_CTRL_FAERR) &&
+ !!(dpaa2_fd_get_frc(fd) & DPAA2_FD_FRC_FASV);
+ if (net_ratelimit())
+ netdev_dbg(priv->net_dev, "TX frame FD error: %x08\n",
+ fd_errors);
}
+
+ free_tx_fd(priv, fd, has_fas_errors ? &status : NULL);
+
+ if (likely(!fd_errors))
+ return;
+
+ percpu_stats = this_cpu_ptr(priv->percpu_stats);
+ /* Tx-conf logically pertains to the egress path. */
+ percpu_stats->tx_errors++;
+
+ if (has_fas_errors && net_ratelimit())
+ netdev_dbg(priv->net_dev, "TX frame FAS error: %x08\n",
+ status & DPAA2_FAS_TX_ERR_MASK);
}
static int set_rx_csum(struct dpaa2_eth_priv *priv, bool enable)
@@ -794,7 +817,7 @@ static void drain_bufs(struct dpaa2_eth_priv *priv, int count)
int ret, i;
do {
- ret = dpaa2_io_service_acquire(NULL, priv->dpbp_attrs.bpid,
+ ret = dpaa2_io_service_acquire(NULL, priv->bpid,
buf_array, count);
if (ret < 0) {
netdev_err(priv->net_dev, "dpaa2_io_service_acquire() failed\n");
@@ -802,10 +825,11 @@ static void drain_bufs(struct dpaa2_eth_priv *priv, int count)
}
for (i = 0; i < ret; i++) {
/* Same logic as on regular Rx path */
+ vaddr = dpaa2_iova_to_virt(priv->iommu_domain,
+ buf_array[i]);
dma_unmap_single(dev, buf_array[i],
DPAA2_ETH_RX_BUF_SIZE,
DMA_FROM_DEVICE);
- vaddr = phys_to_virt(buf_array[i]);
skb_free_frag(vaddr);
}
} while (ret);
@@ -890,7 +914,7 @@ static int dpaa2_eth_poll(struct napi_struct *napi, int budget)
break;
/* Refill pool if appropriate */
- refill_pool(priv, ch, priv->dpbp_attrs.bpid);
+ refill_pool(priv, ch, priv->bpid);
store_cleaned = consume_frames(ch);
cleaned += store_cleaned;
@@ -964,7 +988,7 @@ static int link_state_update(struct dpaa2_eth_priv *priv)
netif_carrier_off(priv->net_dev);
}
- netdev_info(priv->net_dev, "Link Event: state %s",
+ netdev_info(priv->net_dev, "Link Event: state %s\n",
state.up ? "up" : "down");
return 0;
@@ -975,14 +999,14 @@ static int dpaa2_eth_open(struct net_device *net_dev)
struct dpaa2_eth_priv *priv = netdev_priv(net_dev);
int err;
- err = seed_pool(priv, priv->dpbp_attrs.bpid);
+ err = seed_pool(priv, priv->bpid);
if (err) {
/* Not much to do; the buffer pool, though not filled up,
* may still contain some buffers which would enable us
* to limp on.
*/
netdev_err(net_dev, "Buffer seeding failed for DPBP %d (bpid=%d)\n",
- priv->dpbp_dev->obj_desc.id, priv->dpbp_attrs.bpid);
+ priv->dpbp_dev->obj_desc.id, priv->bpid);
}
/* We'll only start the txqs when the link is actually ready; make sure
@@ -1151,8 +1175,8 @@ static int dpaa2_eth_set_addr(struct net_device *net_dev, void *addr)
/** Fill in counters maintained by the GPP driver. These may be different from
* the hardware counters obtained by ethtool.
*/
-void dpaa2_eth_get_stats(struct net_device *net_dev,
- struct rtnl_link_stats64 *stats)
+static void dpaa2_eth_get_stats(struct net_device *net_dev,
+ struct rtnl_link_stats64 *stats)
{
struct dpaa2_eth_priv *priv = netdev_priv(net_dev);
struct rtnl_link_stats64 *percpu_stats;
@@ -1502,6 +1526,7 @@ static int setup_dpio(struct dpaa2_eth_priv *priv)
if (!channel) {
dev_info(dev,
"No affine channel for cpu %d and above\n", i);
+ err = -ENODEV;
goto err_alloc_ch;
}
@@ -1516,10 +1541,13 @@ static int setup_dpio(struct dpaa2_eth_priv *priv)
/* Register the new context */
err = dpaa2_io_service_register(NULL, nctx);
if (err) {
- dev_info(dev, "No affine DPIO for cpu %d\n", i);
+ dev_dbg(dev, "No affine DPIO for cpu %d\n", i);
/* If no affine DPIO for this core, there's probably
- * none available for next cores either.
+ * none available for next cores either. Signal we want
+ * to retry later, in case the DPIO devices weren't
+ * probed yet.
*/
+ err = -EPROBE_DEFER;
goto err_service_reg;
}
@@ -1557,7 +1585,7 @@ err_service_reg:
err_alloc_ch:
if (cpumask_empty(&priv->dpio_cpumask)) {
dev_err(dev, "No cpu with an affine DPIO/DPCON\n");
- return -ENODEV;
+ return err;
}
dev_info(dev, "Cores %*pbl available for processing ingress traffic\n",
@@ -1662,6 +1690,7 @@ static int setup_dpbp(struct dpaa2_eth_priv *priv)
int err;
struct fsl_mc_device *dpbp_dev;
struct device *dev = priv->net_dev->dev.parent;
+ struct dpbp_attr dpbp_attrs;
err = fsl_mc_object_allocate(to_fsl_mc_device(dev), FSL_MC_POOL_DPBP,
&dpbp_dev);
@@ -1679,6 +1708,12 @@ static int setup_dpbp(struct dpaa2_eth_priv *priv)
goto err_open;
}
+ err = dpbp_reset(priv->mc_io, 0, dpbp_dev->mc_handle);
+ if (err) {
+ dev_err(dev, "dpbp_reset() failed\n");
+ goto err_reset;
+ }
+
err = dpbp_enable(priv->mc_io, 0, dpbp_dev->mc_handle);
if (err) {
dev_err(dev, "dpbp_enable() failed\n");
@@ -1686,17 +1721,19 @@ static int setup_dpbp(struct dpaa2_eth_priv *priv)
}
err = dpbp_get_attributes(priv->mc_io, 0, dpbp_dev->mc_handle,
- &priv->dpbp_attrs);
+ &dpbp_attrs);
if (err) {
dev_err(dev, "dpbp_get_attributes() failed\n");
goto err_get_attr;
}
+ priv->bpid = dpbp_attrs.bpid;
return 0;
err_get_attr:
dpbp_disable(priv->mc_io, 0, dpbp_dev->mc_handle);
err_enable:
+err_reset:
dpbp_close(priv->mc_io, 0, dpbp_dev->mc_handle);
err_open:
fsl_mc_object_free(dpbp_dev);
@@ -1718,15 +1755,14 @@ static int setup_dpni(struct fsl_mc_device *ls_dev)
struct device *dev = &ls_dev->dev;
struct dpaa2_eth_priv *priv;
struct net_device *net_dev;
+ struct dpni_buffer_layout buf_layout = {0};
int err;
net_dev = dev_get_drvdata(dev);
priv = netdev_priv(net_dev);
- priv->dpni_id = ls_dev->obj_desc.id;
-
/* get a handle for the DPNI object */
- err = dpni_open(priv->mc_io, 0, priv->dpni_id, &priv->mc_token);
+ err = dpni_open(priv->mc_io, 0, ls_dev->obj_desc.id, &priv->mc_token);
if (err) {
dev_err(dev, "dpni_open() failed\n");
goto err_open;
@@ -1750,35 +1786,35 @@ static int setup_dpni(struct fsl_mc_device *ls_dev)
/* Configure buffer layouts */
/* rx buffer */
- priv->buf_layout.pass_parser_result = true;
- priv->buf_layout.pass_frame_status = true;
- priv->buf_layout.private_data_size = DPAA2_ETH_SWA_SIZE;
- priv->buf_layout.data_align = DPAA2_ETH_RX_BUF_ALIGN;
- priv->buf_layout.options = DPNI_BUF_LAYOUT_OPT_PARSER_RESULT |
- DPNI_BUF_LAYOUT_OPT_FRAME_STATUS |
- DPNI_BUF_LAYOUT_OPT_PRIVATE_DATA_SIZE |
- DPNI_BUF_LAYOUT_OPT_DATA_ALIGN;
+ buf_layout.pass_parser_result = true;
+ buf_layout.pass_frame_status = true;
+ buf_layout.private_data_size = DPAA2_ETH_SWA_SIZE;
+ buf_layout.data_align = DPAA2_ETH_RX_BUF_ALIGN;
+ buf_layout.options = DPNI_BUF_LAYOUT_OPT_PARSER_RESULT |
+ DPNI_BUF_LAYOUT_OPT_FRAME_STATUS |
+ DPNI_BUF_LAYOUT_OPT_PRIVATE_DATA_SIZE |
+ DPNI_BUF_LAYOUT_OPT_DATA_ALIGN;
err = dpni_set_buffer_layout(priv->mc_io, 0, priv->mc_token,
- DPNI_QUEUE_RX, &priv->buf_layout);
+ DPNI_QUEUE_RX, &buf_layout);
if (err) {
dev_err(dev, "dpni_set_buffer_layout(RX) failed\n");
goto err_buf_layout;
}
/* tx buffer */
- priv->buf_layout.options = DPNI_BUF_LAYOUT_OPT_FRAME_STATUS |
- DPNI_BUF_LAYOUT_OPT_PRIVATE_DATA_SIZE;
+ buf_layout.options = DPNI_BUF_LAYOUT_OPT_FRAME_STATUS |
+ DPNI_BUF_LAYOUT_OPT_PRIVATE_DATA_SIZE;
err = dpni_set_buffer_layout(priv->mc_io, 0, priv->mc_token,
- DPNI_QUEUE_TX, &priv->buf_layout);
+ DPNI_QUEUE_TX, &buf_layout);
if (err) {
dev_err(dev, "dpni_set_buffer_layout(TX) failed\n");
goto err_buf_layout;
}
/* tx-confirm buffer */
- priv->buf_layout.options = DPNI_BUF_LAYOUT_OPT_FRAME_STATUS;
+ buf_layout.options = DPNI_BUF_LAYOUT_OPT_FRAME_STATUS;
err = dpni_set_buffer_layout(priv->mc_io, 0, priv->mc_token,
- DPNI_QUEUE_TX_CONFIRM, &priv->buf_layout);
+ DPNI_QUEUE_TX_CONFIRM, &buf_layout);
if (err) {
dev_err(dev, "dpni_set_buffer_layout(TX_CONF) failed\n");
goto err_buf_layout;
@@ -1795,7 +1831,7 @@ static int setup_dpni(struct fsl_mc_device *ls_dev)
}
if ((priv->tx_data_offset % 64) != 0)
- dev_warn(dev, "Tx data offset (%d) not a multiple of 64B",
+ dev_warn(dev, "Tx data offset (%d) not a multiple of 64B\n",
priv->tx_data_offset);
/* Accommodate software annotation space (SWA) */
@@ -1947,7 +1983,7 @@ static const struct dpaa2_eth_hash_fields hash_fields[] = {
/* Set RX hash options
* flags is a combination of RXH_ bits
*/
-int dpaa2_eth_set_hash(struct net_device *net_dev, u64 flags)
+static int dpaa2_eth_set_hash(struct net_device *net_dev, u64 flags)
{
struct device *dev = net_dev->dev.parent;
struct dpaa2_eth_priv *priv = netdev_priv(net_dev);
@@ -1958,8 +1994,8 @@ int dpaa2_eth_set_hash(struct net_device *net_dev, u64 flags)
int err = 0;
if (!dpaa2_eth_hash_enabled(priv)) {
- dev_err(dev, "Hashing support is not enabled\n");
- return -EOPNOTSUPP;
+ dev_dbg(dev, "Hashing support is not enabled\n");
+ return 0;
}
memset(&cls_cfg, 0, sizeof(cls_cfg));
@@ -1985,23 +2021,23 @@ int dpaa2_eth_set_hash(struct net_device *net_dev, u64 flags)
priv->rx_hash_fields |= hash_fields[i].rxnfc_field;
}
- dma_mem = kzalloc(DPAA2_CLASSIFIER_DMA_SIZE, GFP_DMA | GFP_KERNEL);
+ dma_mem = kzalloc(DPAA2_CLASSIFIER_DMA_SIZE, GFP_KERNEL);
if (!dma_mem)
return -ENOMEM;
err = dpni_prepare_key_cfg(&cls_cfg, dma_mem);
if (err) {
- dev_err(dev, "dpni_prepare_key_cfg error %d", err);
+ dev_err(dev, "dpni_prepare_key_cfg error %d\n", err);
goto err_prep_key;
}
memset(&dist_cfg, 0, sizeof(dist_cfg));
/* Prepare for setting the rx dist */
- dist_cfg.key_cfg_iova = dma_map_single(net_dev->dev.parent, dma_mem,
+ dist_cfg.key_cfg_iova = dma_map_single(dev, dma_mem,
DPAA2_CLASSIFIER_DMA_SIZE,
DMA_TO_DEVICE);
- if (dma_mapping_error(net_dev->dev.parent, dist_cfg.key_cfg_iova)) {
+ if (dma_mapping_error(dev, dist_cfg.key_cfg_iova)) {
dev_err(dev, "DMA mapping failed\n");
err = -ENOMEM;
goto err_dma_map;
@@ -2011,7 +2047,7 @@ int dpaa2_eth_set_hash(struct net_device *net_dev, u64 flags)
dist_cfg.dist_mode = DPNI_DIST_MODE_HASH;
err = dpni_set_rx_tc_dist(priv->mc_io, 0, priv->mc_token, 0, &dist_cfg);
- dma_unmap_single(net_dev->dev.parent, dist_cfg.key_cfg_iova,
+ dma_unmap_single(dev, dist_cfg.key_cfg_iova,
DPAA2_CLASSIFIER_DMA_SIZE, DMA_TO_DEVICE);
if (err)
dev_err(dev, "dpni_set_rx_tc_dist() error %d\n", err);
@@ -2052,7 +2088,7 @@ static int bind_dpni(struct dpaa2_eth_priv *priv)
netdev_err(net_dev, "Failed to configure hashing\n");
/* Configure handling of error frames */
- err_cfg.errors = DPAA2_ETH_RX_ERR_MASK;
+ err_cfg.errors = DPAA2_FAS_RX_ERR_MASK;
err_cfg.set_frame_annotation = 1;
err_cfg.error_action = DPNI_ERROR_ACTION_DISCARD;
err = dpni_set_errors_behavior(priv->mc_io, 0, priv->mc_token,
@@ -2125,15 +2161,12 @@ static void free_rings(struct dpaa2_eth_priv *priv)
dpaa2_io_store_destroy(priv->channel[i]->store);
}
-static int netdev_init(struct net_device *net_dev)
+static int set_mac_addr(struct dpaa2_eth_priv *priv)
{
- int err;
+ struct net_device *net_dev = priv->net_dev;
struct device *dev = net_dev->dev.parent;
- struct dpaa2_eth_priv *priv = netdev_priv(net_dev);
u8 mac_addr[ETH_ALEN], dpni_mac_addr[ETH_ALEN];
- u8 bcast_addr[ETH_ALEN];
-
- net_dev->netdev_ops = &dpaa2_eth_ops;
+ int err;
/* Get firmware address, if any */
err = dpni_get_port_mac_addr(priv->mc_io, 0, priv->mc_token, mac_addr);
@@ -2146,7 +2179,7 @@ static int netdev_init(struct net_device *net_dev)
err = dpni_get_primary_mac_addr(priv->mc_io, 0, priv->mc_token,
dpni_mac_addr);
if (err) {
- dev_err(dev, "dpni_get_primary_mac_addr() failed (%d)\n", err);
+ dev_err(dev, "dpni_get_primary_mac_addr() failed\n");
return err;
}
@@ -2164,18 +2197,19 @@ static int netdev_init(struct net_device *net_dev)
}
memcpy(net_dev->dev_addr, mac_addr, net_dev->addr_len);
} else if (is_zero_ether_addr(dpni_mac_addr)) {
- /* Fills in net_dev->dev_addr, as required by
- * register_netdevice()
+ /* No MAC address configured, fill in net_dev->dev_addr
+ * with a random one
*/
eth_hw_addr_random(net_dev);
- /* Make the user aware, without cluttering the boot log */
- dev_dbg_once(dev, " device(s) have all-zero hwaddr, replaced with random\n");
+ dev_dbg_once(dev, "device(s) have all-zero hwaddr, replaced with random\n");
+
err = dpni_set_primary_mac_addr(priv->mc_io, 0, priv->mc_token,
net_dev->dev_addr);
if (err) {
- dev_err(dev, "dpni_set_primary_mac_addr(): %d\n", err);
+ dev_err(dev, "dpni_set_primary_mac_addr() failed\n");
return err;
}
+
/* Override NET_ADDR_RANDOM set by eth_hw_addr_random(); for all
* practical purposes, this will be our "permanent" mac address,
* at least until the next reboot. This move will also permit
@@ -2189,14 +2223,29 @@ static int netdev_init(struct net_device *net_dev)
memcpy(net_dev->dev_addr, dpni_mac_addr, net_dev->addr_len);
}
- /* Explicitly add the broadcast address to the MAC filtering table;
- * the MC won't do that for us.
- */
+ return 0;
+}
+
+static int netdev_init(struct net_device *net_dev)
+{
+ struct device *dev = net_dev->dev.parent;
+ struct dpaa2_eth_priv *priv = netdev_priv(net_dev);
+ u8 bcast_addr[ETH_ALEN];
+ u8 num_queues;
+ int err;
+
+ net_dev->netdev_ops = &dpaa2_eth_ops;
+
+ err = set_mac_addr(priv);
+ if (err)
+ return err;
+
+ /* Explicitly add the broadcast address to the MAC filtering table */
eth_broadcast_addr(bcast_addr);
err = dpni_add_mac_addr(priv->mc_io, 0, priv->mc_token, bcast_addr);
if (err) {
- dev_warn(dev, "dpni_add_mac_addr() failed (%d)\n", err);
- /* Won't return an error; at least, we'd have egress traffic */
+ dev_err(dev, "dpni_add_mac_addr() failed\n");
+ return err;
}
/* Reserve enough space to align buffer as per hardware requirement;
@@ -2208,6 +2257,19 @@ static int netdev_init(struct net_device *net_dev)
net_dev->min_mtu = 68;
net_dev->max_mtu = DPAA2_ETH_MAX_MTU;
+ /* Set actual number of queues in the net device */
+ num_queues = dpaa2_eth_queue_count(priv);
+ err = netif_set_real_num_tx_queues(net_dev, num_queues);
+ if (err) {
+ dev_err(dev, "netif_set_real_num_tx_queues() failed\n");
+ return err;
+ }
+ err = netif_set_real_num_rx_queues(net_dev, num_queues);
+ if (err) {
+ dev_err(dev, "netif_set_real_num_rx_queues() failed\n");
+ return err;
+ }
+
/* Our .ndo_init will be called herein */
err = register_netdev(net_dev);
if (err < 0) {
@@ -2241,7 +2303,7 @@ static irqreturn_t dpni_irq0_handler(int irq_num, void *arg)
static irqreturn_t dpni_irq0_handler_thread(int irq_num, void *arg)
{
- u32 status, clear = 0;
+ u32 status = 0, clear = 0;
struct device *dev = (struct device *)arg;
struct fsl_mc_device *dpni_dev = to_fsl_mc_device(dev);
struct net_device *net_dev = dev_get_drvdata(dev);
@@ -2250,7 +2312,7 @@ static irqreturn_t dpni_irq0_handler_thread(int irq_num, void *arg)
err = dpni_get_irq_status(dpni_dev->mc_io, 0, dpni_dev->mc_handle,
DPNI_IRQ_INDEX, &status);
if (unlikely(err)) {
- netdev_err(net_dev, "Can't get irq status (err %d)", err);
+ netdev_err(net_dev, "Can't get irq status (err %d)\n", err);
clear = 0xffffffff;
goto out;
}
@@ -2284,21 +2346,21 @@ static int setup_irqs(struct fsl_mc_device *ls_dev)
IRQF_NO_SUSPEND | IRQF_ONESHOT,
dev_name(&ls_dev->dev), &ls_dev->dev);
if (err < 0) {
- dev_err(&ls_dev->dev, "devm_request_threaded_irq(): %d", err);
+ dev_err(&ls_dev->dev, "devm_request_threaded_irq(): %d\n", err);
goto free_mc_irq;
}
err = dpni_set_irq_mask(ls_dev->mc_io, 0, ls_dev->mc_handle,
DPNI_IRQ_INDEX, DPNI_IRQ_EVENT_LINK_CHANGED);
if (err < 0) {
- dev_err(&ls_dev->dev, "dpni_set_irq_mask(): %d", err);
+ dev_err(&ls_dev->dev, "dpni_set_irq_mask(): %d\n", err);
goto free_irq;
}
err = dpni_set_irq_enable(ls_dev->mc_io, 0, ls_dev->mc_handle,
DPNI_IRQ_INDEX, 1);
if (err < 0) {
- dev_err(&ls_dev->dev, "dpni_set_irq_enable(): %d", err);
+ dev_err(&ls_dev->dev, "dpni_set_irq_enable(): %d\n", err);
goto free_irq;
}
@@ -2358,6 +2420,8 @@ static int dpaa2_eth_probe(struct fsl_mc_device *dpni_dev)
priv = netdev_priv(net_dev);
priv->net_dev = net_dev;
+ priv->iommu_domain = iommu_get_domain_for_dev(dev);
+
/* Obtain a MC portal */
err = fsl_mc_portal_allocate(dpni_dev, FSL_MC_IO_ATOMIC_CONTEXT_PORTAL,
&priv->mc_io);
diff --git a/drivers/staging/fsl-dpaa2/ethernet/dpaa2-eth.h b/drivers/staging/fsl-dpaa2/ethernet/dpaa2-eth.h
index c67cced55b72..e6d28a249fc1 100644
--- a/drivers/staging/fsl-dpaa2/ethernet/dpaa2-eth.h
+++ b/drivers/staging/fsl-dpaa2/ethernet/dpaa2-eth.h
@@ -120,6 +120,19 @@ struct dpaa2_eth_swa {
#define DPAA2_FD_FRC_FASWOV 0x0800
#define DPAA2_FD_FRC_FAICFDV 0x0400
+/* Error bits in FD CTRL */
+#define DPAA2_FD_CTRL_UFD 0x00000004
+#define DPAA2_FD_CTRL_SBE 0x00000008
+#define DPAA2_FD_CTRL_FSE 0x00000010
+#define DPAA2_FD_CTRL_FAERR 0x00000020
+
+#define DPAA2_FD_RX_ERR_MASK (DPAA2_FD_CTRL_SBE | \
+ DPAA2_FD_CTRL_FAERR)
+#define DPAA2_FD_TX_ERR_MASK (DPAA2_FD_CTRL_UFD | \
+ DPAA2_FD_CTRL_SBE | \
+ DPAA2_FD_CTRL_FSE | \
+ DPAA2_FD_CTRL_FAERR)
+
/* Annotation bits in FD CTRL */
#define DPAA2_FD_CTRL_ASAL 0x00020000 /* ASAL = 128 */
#define DPAA2_FD_CTRL_PTA 0x00800000
@@ -139,6 +152,12 @@ struct dpaa2_fas {
#define DPAA2_FAS_OFFSET 0
#define DPAA2_FAS_SIZE (sizeof(struct dpaa2_fas))
+/* Accessors for the hardware annotation fields that we use */
+#define dpaa2_get_hwa(buf_addr) \
+ ((void *)(buf_addr) + DPAA2_ETH_SWA_SIZE)
+#define dpaa2_get_fas(buf_addr) \
+ (struct dpaa2_fas *)(dpaa2_get_hwa(buf_addr) + DPAA2_FAS_OFFSET)
+
/* Error and status bits in the frame annotation status word */
/* Debug frame, otherwise supposed to be discarded */
#define DPAA2_FAS_DISC 0x80000000
@@ -171,7 +190,7 @@ struct dpaa2_fas {
/* L4 csum error */
#define DPAA2_FAS_L4CE 0x00000001
/* Possible errors on the ingress path */
-#define DPAA2_ETH_RX_ERR_MASK (DPAA2_FAS_KSE | \
+#define DPAA2_FAS_RX_ERR_MASK (DPAA2_FAS_KSE | \
DPAA2_FAS_EOFHE | \
DPAA2_FAS_MNLE | \
DPAA2_FAS_TIDE | \
@@ -185,7 +204,7 @@ struct dpaa2_fas {
DPAA2_FAS_L3CE | \
DPAA2_FAS_L4CE)
/* Tx errors */
-#define DPAA2_ETH_TXCONF_ERR_MASK (DPAA2_FAS_KSE | \
+#define DPAA2_FAS_TX_ERR_MASK (DPAA2_FAS_KSE | \
DPAA2_FAS_EOFHE | \
DPAA2_FAS_MNLE | \
DPAA2_FAS_TIDE)
@@ -291,16 +310,12 @@ struct dpaa2_eth_priv {
u8 num_channels;
struct dpaa2_eth_channel *channel[DPAA2_ETH_MAX_DPCONS];
- int dpni_id;
struct dpni_attr dpni_attrs;
- /* Insofar as the MC is concerned, we're using one layout on all 3 types
- * of buffers (Rx, Tx, Tx-Conf).
- */
- struct dpni_buffer_layout buf_layout;
u16 tx_data_offset;
struct fsl_mc_device *dpbp_dev;
- struct dpbp_attr dpbp_attrs;
+ u16 bpid;
+ struct iommu_domain *iommu_domain;
u16 tx_qdid;
struct fsl_mc_io *mc_io;
@@ -338,8 +353,6 @@ struct dpaa2_eth_priv {
extern const struct ethtool_ops dpaa2_ethtool_ops;
extern const char dpaa2_eth_drv_version[];
-int dpaa2_eth_set_hash(struct net_device *net_dev, u64 flags);
-
static int dpaa2_eth_queue_count(struct dpaa2_eth_priv *priv)
{
return priv->dpni_attrs.num_queues;
diff --git a/drivers/staging/fsl-dpaa2/ethernet/dpaa2-ethtool.c b/drivers/staging/fsl-dpaa2/ethernet/dpaa2-ethtool.c
index dd0cffa908ef..5312edc26f01 100644
--- a/drivers/staging/fsl-dpaa2/ethernet/dpaa2-ethtool.c
+++ b/drivers/staging/fsl-dpaa2/ethernet/dpaa2-ethtool.c
@@ -34,41 +34,41 @@
#include "dpaa2-eth.h"
/* To be kept in sync with DPNI statistics */
-char dpaa2_ethtool_stats[][ETH_GSTRING_LEN] = {
- "rx frames",
- "rx bytes",
- "rx mcast frames",
- "rx mcast bytes",
- "rx bcast frames",
- "rx bcast bytes",
- "tx frames",
- "tx bytes",
- "tx mcast frames",
- "tx mcast bytes",
- "tx bcast frames",
- "tx bcast bytes",
- "rx filtered frames",
- "rx discarded frames",
- "rx nobuffer discards",
- "tx discarded frames",
- "tx confirmed frames",
+static char dpaa2_ethtool_stats[][ETH_GSTRING_LEN] = {
+ "[hw] rx frames",
+ "[hw] rx bytes",
+ "[hw] rx mcast frames",
+ "[hw] rx mcast bytes",
+ "[hw] rx bcast frames",
+ "[hw] rx bcast bytes",
+ "[hw] tx frames",
+ "[hw] tx bytes",
+ "[hw] tx mcast frames",
+ "[hw] tx mcast bytes",
+ "[hw] tx bcast frames",
+ "[hw] tx bcast bytes",
+ "[hw] rx filtered frames",
+ "[hw] rx discarded frames",
+ "[hw] rx nobuffer discards",
+ "[hw] tx discarded frames",
+ "[hw] tx confirmed frames",
};
#define DPAA2_ETH_NUM_STATS ARRAY_SIZE(dpaa2_ethtool_stats)
-char dpaa2_ethtool_extras[][ETH_GSTRING_LEN] = {
+static char dpaa2_ethtool_extras[][ETH_GSTRING_LEN] = {
/* per-cpu stats */
- "tx conf frames",
- "tx conf bytes",
- "tx sg frames",
- "tx sg bytes",
- "rx sg frames",
- "rx sg bytes",
- "enqueue portal busy",
+ "[drv] tx conf frames",
+ "[drv] tx conf bytes",
+ "[drv] tx sg frames",
+ "[drv] tx sg bytes",
+ "[drv] rx sg frames",
+ "[drv] rx sg bytes",
+ "[drv] enqueue portal busy",
/* Channel stats */
- "dequeue portal busy",
- "channel pull errors",
- "cdan",
+ "[drv] dequeue portal busy",
+ "[drv] channel pull errors",
+ "[drv] cdan",
};
#define DPAA2_ETH_NUM_EXTRA_STATS ARRAY_SIZE(dpaa2_ethtool_extras)
@@ -94,7 +94,7 @@ dpaa2_eth_get_link_ksettings(struct net_device *net_dev,
err = dpni_get_link_state(priv->mc_io, 0, priv->mc_token, &state);
if (err) {
- netdev_err(net_dev, "ERROR %d getting link state", err);
+ netdev_err(net_dev, "ERROR %d getting link state\n", err);
goto out;
}
@@ -147,7 +147,7 @@ dpaa2_eth_set_link_ksettings(struct net_device *net_dev,
/* ethtool will be loud enough if we return an error; no point
* in putting our own error message on the console by default
*/
- netdev_dbg(net_dev, "ERROR %d setting link cfg", err);
+ netdev_dbg(net_dev, "ERROR %d setting link cfg\n", err);
return err;
}
@@ -206,7 +206,7 @@ static void dpaa2_eth_get_ethtool_stats(struct net_device *net_dev,
err = dpni_get_statistics(priv->mc_io, 0, priv->mc_token,
j, &dpni_stats);
if (err != 0)
- netdev_warn(net_dev, "dpni_get_stats(%d) failed", j);
+ netdev_warn(net_dev, "dpni_get_stats(%d) failed\n", j);
switch (j) {
case 0:
num_cnt = sizeof(dpni_stats.page_0) / sizeof(u64);
diff --git a/drivers/staging/fsl-dpaa2/ethernet/dpni.c b/drivers/staging/fsl-dpaa2/ethernet/dpni.c
index cea46edec6a2..5b9d4424e4fb 100644
--- a/drivers/staging/fsl-dpaa2/ethernet/dpni.c
+++ b/drivers/staging/fsl-dpaa2/ethernet/dpni.c
@@ -30,8 +30,9 @@
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
-#include "../../fsl-mc/include/mc-sys.h"
-#include "../../fsl-mc/include/mc-cmd.h"
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include "../../fsl-mc/include/mc.h"
#include "dpni.h"
#include "dpni-cmd.h"
diff --git a/drivers/staging/fsl-mc/README.txt b/drivers/staging/fsl-mc/README.txt
index 179536a9b7a1..524eda1de04f 100644
--- a/drivers/staging/fsl-mc/README.txt
+++ b/drivers/staging/fsl-mc/README.txt
@@ -131,9 +131,7 @@ in creating a network interfaces.
DPRCs can be defined statically and populated with objects
via a config file passed to the MC when firmware starts
- it. There is also a Linux user space tool called "restool"
- that can be used to create/destroy containers and objects
- dynamically.
+ it.
-DPAA2 Objects for an Ethernet Network Interface
@@ -322,6 +320,8 @@ A brief description of each driver is provided below.
-creates an MSI IRQ domain
-doing a 'device add' to expose the 'root' DPRC, in turn triggering
a bind of the root DPRC to the DPRC driver
+ The binding for the MC-bus device-tree node can be consulted here:
+ Documentation/devicetree/bindings/misc/fsl,qoriq-mc.txt
DPRC driver
-----------
diff --git a/drivers/staging/fsl-mc/bus/Makefile b/drivers/staging/fsl-mc/bus/Makefile
index 659eccf52a4f..6df407edfade 100644
--- a/drivers/staging/fsl-mc/bus/Makefile
+++ b/drivers/staging/fsl-mc/bus/Makefile
@@ -11,7 +11,6 @@ mc-bus-driver-objs := fsl-mc-bus.o \
mc-sys.o \
mc-io.o \
dprc.o \
- dpmng.o \
dprc-driver.o \
fsl-mc-allocator.o \
fsl-mc-msi.o \
diff --git a/drivers/staging/fsl-mc/bus/dpbp-cmd.h b/drivers/staging/fsl-mc/bus/dpbp-cmd.h
index 8aa65452c872..5904836fd741 100644
--- a/drivers/staging/fsl-mc/bus/dpbp-cmd.h
+++ b/drivers/staging/fsl-mc/bus/dpbp-cmd.h
@@ -40,7 +40,7 @@
#define DPBP_CMD_BASE_VERSION 1
#define DPBP_CMD_ID_OFFSET 4
-#define DPBP_CMD(id) ((id << DPBP_CMD_ID_OFFSET) | DPBP_CMD_BASE_VERSION)
+#define DPBP_CMD(id) (((id) << DPBP_CMD_ID_OFFSET) | DPBP_CMD_BASE_VERSION)
/* Command IDs */
#define DPBP_CMDID_CLOSE DPBP_CMD(0x800)
diff --git a/drivers/staging/fsl-mc/bus/dpbp.c b/drivers/staging/fsl-mc/bus/dpbp.c
index d9e450a6bad6..363730a80cbb 100644
--- a/drivers/staging/fsl-mc/bus/dpbp.c
+++ b/drivers/staging/fsl-mc/bus/dpbp.c
@@ -29,8 +29,8 @@
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
-#include "../include/mc-sys.h"
-#include "../include/mc-cmd.h"
+#include <linux/kernel.h>
+#include "../include/mc.h"
#include "../include/dpbp.h"
#include "dpbp-cmd.h"
diff --git a/drivers/staging/fsl-mc/bus/dpcon.c b/drivers/staging/fsl-mc/bus/dpcon.c
index eb713578b817..ca1da85c6dda 100644
--- a/drivers/staging/fsl-mc/bus/dpcon.c
+++ b/drivers/staging/fsl-mc/bus/dpcon.c
@@ -29,8 +29,8 @@
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
-#include "../include/mc-sys.h"
-#include "../include/mc-cmd.h"
+#include <linux/kernel.h>
+#include "../include/mc.h"
#include "../include/dpcon.h"
#include "dpcon-cmd.h"
diff --git a/drivers/staging/fsl-mc/bus/dpio/dpio-service.c b/drivers/staging/fsl-mc/bus/dpio/dpio-service.c
index e5d66749614c..f8096828f5b7 100644
--- a/drivers/staging/fsl-mc/bus/dpio/dpio-service.c
+++ b/drivers/staging/fsl-mc/bus/dpio/dpio-service.c
@@ -260,9 +260,9 @@ int dpaa2_io_service_register(struct dpaa2_io *d,
/* Enable the generation of CDAN notifications */
if (ctx->is_cdan)
- qbman_swp_CDAN_set_context_enable(d->swp,
- (u16)ctx->id,
- ctx->qman64);
+ return qbman_swp_CDAN_set_context_enable(d->swp,
+ (u16)ctx->id,
+ ctx->qman64);
return 0;
}
EXPORT_SYMBOL(dpaa2_io_service_register);
@@ -514,7 +514,7 @@ EXPORT_SYMBOL(dpaa2_io_service_acquire);
* The size of the storage is "max_frames*sizeof(struct dpaa2_dq)".
* The 'dpaa2_io_store' returned is a DPIO service managed object.
*
- * Return pointer to dpaa2_io_store struct for successfuly created storage
+ * Return pointer to dpaa2_io_store struct for successfully created storage
* memory, or NULL on error.
*/
struct dpaa2_io_store *dpaa2_io_store_create(unsigned int max_frames,
diff --git a/drivers/staging/fsl-mc/bus/dpio/dpio.c b/drivers/staging/fsl-mc/bus/dpio/dpio.c
index d81e0232f6c1..00eb22186f42 100644
--- a/drivers/staging/fsl-mc/bus/dpio/dpio.c
+++ b/drivers/staging/fsl-mc/bus/dpio/dpio.c
@@ -30,8 +30,8 @@
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
-#include "../../include/mc-sys.h"
-#include "../../include/mc-cmd.h"
+#include <linux/kernel.h>
+#include "../../include/mc.h"
#include "dpio.h"
#include "dpio-cmd.h"
diff --git a/drivers/staging/fsl-mc/bus/dpmcp-cmd.h b/drivers/staging/fsl-mc/bus/dpmcp-cmd.h
index 384a13d0b07f..861b2a708af8 100644
--- a/drivers/staging/fsl-mc/bus/dpmcp-cmd.h
+++ b/drivers/staging/fsl-mc/bus/dpmcp-cmd.h
@@ -40,7 +40,7 @@
#define DPMCP_CMD_BASE_VERSION 1
#define DPMCP_CMD_ID_OFFSET 4
-#define DPMCP_CMD(id) ((id << DPMCP_CMD_ID_OFFSET) | DPMCP_CMD_BASE_VERSION)
+#define DPMCP_CMD(id) (((id) << DPMCP_CMD_ID_OFFSET) | DPMCP_CMD_BASE_VERSION)
/* Command IDs */
#define DPMCP_CMDID_CLOSE DPMCP_CMD(0x800)
diff --git a/drivers/staging/fsl-mc/bus/dpmcp.c b/drivers/staging/fsl-mc/bus/dpmcp.c
index ad4c8b43f065..eea42f61af86 100644
--- a/drivers/staging/fsl-mc/bus/dpmcp.c
+++ b/drivers/staging/fsl-mc/bus/dpmcp.c
@@ -29,8 +29,8 @@
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
-#include "../include/mc-sys.h"
-#include "../include/mc-cmd.h"
+#include <linux/kernel.h>
+#include "../include/mc.h"
#include "dpmcp.h"
#include "dpmcp-cmd.h"
diff --git a/drivers/staging/fsl-mc/bus/dpmng-cmd.h b/drivers/staging/fsl-mc/bus/dpmng-cmd.h
index cdddfb80eecc..d1f04ac18b78 100644
--- a/drivers/staging/fsl-mc/bus/dpmng-cmd.h
+++ b/drivers/staging/fsl-mc/bus/dpmng-cmd.h
@@ -44,7 +44,7 @@
#define DPMNG_CMD_BASE_VERSION 1
#define DPMNG_CMD_ID_OFFSET 4
-#define DPMNG_CMD(id) ((id << DPMNG_CMD_ID_OFFSET) | DPMNG_CMD_BASE_VERSION)
+#define DPMNG_CMD(id) (((id) << DPMNG_CMD_ID_OFFSET) | DPMNG_CMD_BASE_VERSION)
/* Command IDs */
#define DPMNG_CMDID_GET_VERSION DPMNG_CMD(0x831)
diff --git a/drivers/staging/fsl-mc/bus/dpmng.c b/drivers/staging/fsl-mc/bus/dpmng.c
deleted file mode 100644
index ad5d5bbec529..000000000000
--- a/drivers/staging/fsl-mc/bus/dpmng.c
+++ /dev/null
@@ -1,74 +0,0 @@
-/*
- * Copyright 2013-2016 Freescale Semiconductor Inc.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * * Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * * Neither the name of the above-listed copyright holders nor the
- * names of any contributors may be used to endorse or promote products
- * derived from this software without specific prior written permission.
- *
- * ALTERNATIVELY, this software may be distributed under the terms of the
- * GNU General Public License ("GPL") as published by the Free Software
- * Foundation, either version 2 of that License or (at your option) any
- * later version.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- * POSSIBILITY OF SUCH DAMAGE.
- */
-#include "../include/mc-sys.h"
-#include "../include/mc-cmd.h"
-#include "../include/dpmng.h"
-
-#include "dpmng-cmd.h"
-
-/**
- * mc_get_version() - Retrieves the Management Complex firmware
- * version information
- * @mc_io: Pointer to opaque I/O object
- * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
- * @mc_ver_info: Returned version information structure
- *
- * Return: '0' on Success; Error code otherwise.
- */
-int mc_get_version(struct fsl_mc_io *mc_io,
- u32 cmd_flags,
- struct mc_version *mc_ver_info)
-{
- struct mc_command cmd = { 0 };
- struct dpmng_rsp_get_version *rsp_params;
- int err;
-
- /* prepare command */
- cmd.header = mc_encode_cmd_header(DPMNG_CMDID_GET_VERSION,
- cmd_flags,
- 0);
-
- /* send command to mc*/
- err = mc_send_command(mc_io, &cmd);
- if (err)
- return err;
-
- /* retrieve response parameters */
- rsp_params = (struct dpmng_rsp_get_version *)cmd.params;
- mc_ver_info->revision = le32_to_cpu(rsp_params->revision);
- mc_ver_info->major = le32_to_cpu(rsp_params->version_major);
- mc_ver_info->minor = le32_to_cpu(rsp_params->version_minor);
-
- return 0;
-}
-EXPORT_SYMBOL(mc_get_version);
-
diff --git a/drivers/staging/fsl-mc/bus/dprc-cmd.h b/drivers/staging/fsl-mc/bus/dprc-cmd.h
index e9fdca41f324..d9b2dcde468e 100644
--- a/drivers/staging/fsl-mc/bus/dprc-cmd.h
+++ b/drivers/staging/fsl-mc/bus/dprc-cmd.h
@@ -48,7 +48,7 @@
#define DPRC_CMD_BASE_VERSION 1
#define DPRC_CMD_ID_OFFSET 4
-#define DPRC_CMD(id) ((id << DPRC_CMD_ID_OFFSET) | DPRC_CMD_BASE_VERSION)
+#define DPRC_CMD(id) (((id) << DPRC_CMD_ID_OFFSET) | DPRC_CMD_BASE_VERSION)
/* Command IDs */
#define DPRC_CMDID_CLOSE DPRC_CMD(0x800)
diff --git a/drivers/staging/fsl-mc/bus/dprc-driver.c b/drivers/staging/fsl-mc/bus/dprc-driver.c
index e4b0341d42d7..4cdd190a338b 100644
--- a/drivers/staging/fsl-mc/bus/dprc-driver.c
+++ b/drivers/staging/fsl-mc/bus/dprc-driver.c
@@ -13,27 +13,30 @@
#include <linux/slab.h>
#include <linux/interrupt.h>
#include <linux/msi.h>
-#include "../include/mc-bus.h"
-#include "../include/mc-sys.h"
+#include "../include/mc.h"
#include "dprc-cmd.h"
#include "fsl-mc-private.h"
#define FSL_MC_DPRC_DRIVER_NAME "fsl_mc_dprc"
-#define FSL_MC_DEVICE_MATCH(_mc_dev, _obj_desc) \
- (strcmp((_mc_dev)->obj_desc.type, (_obj_desc)->type) == 0 && \
- (_mc_dev)->obj_desc.id == (_obj_desc)->id)
-
-struct dprc_child_objs {
+struct fsl_mc_child_objs {
int child_count;
- struct dprc_obj_desc *child_array;
+ struct fsl_mc_obj_desc *child_array;
};
+static bool fsl_mc_device_match(struct fsl_mc_device *mc_dev,
+ struct fsl_mc_obj_desc *obj_desc)
+{
+ return mc_dev->obj_desc.id == obj_desc->id &&
+ !strcmp(mc_dev->obj_desc.type, obj_desc->type);
+
+}
+
static int __fsl_mc_device_remove_if_not_in_mc(struct device *dev, void *data)
{
int i;
- struct dprc_child_objs *objs;
+ struct fsl_mc_child_objs *objs;
struct fsl_mc_device *mc_dev;
WARN_ON(!dev);
@@ -42,10 +45,10 @@ static int __fsl_mc_device_remove_if_not_in_mc(struct device *dev, void *data)
objs = data;
for (i = 0; i < objs->child_count; i++) {
- struct dprc_obj_desc *obj_desc = &objs->child_array[i];
+ struct fsl_mc_obj_desc *obj_desc = &objs->child_array[i];
if (strlen(obj_desc->type) != 0 &&
- FSL_MC_DEVICE_MATCH(mc_dev, obj_desc))
+ fsl_mc_device_match(mc_dev, obj_desc))
break;
}
@@ -76,7 +79,7 @@ static int __fsl_mc_device_remove(struct device *dev, void *data)
* been dynamically removed in the physical DPRC.
*/
static void dprc_remove_devices(struct fsl_mc_device *mc_bus_dev,
- struct dprc_obj_desc *obj_desc_array,
+ struct fsl_mc_obj_desc *obj_desc_array,
int num_child_objects_in_mc)
{
if (num_child_objects_in_mc != 0) {
@@ -84,7 +87,7 @@ static void dprc_remove_devices(struct fsl_mc_device *mc_bus_dev,
* Remove child objects that are in the DPRC in Linux,
* but not in the MC:
*/
- struct dprc_child_objs objs;
+ struct fsl_mc_child_objs objs;
objs.child_count = num_child_objects_in_mc;
objs.child_array = obj_desc_array;
@@ -102,13 +105,13 @@ static void dprc_remove_devices(struct fsl_mc_device *mc_bus_dev,
static int __fsl_mc_device_match(struct device *dev, void *data)
{
- struct dprc_obj_desc *obj_desc = data;
+ struct fsl_mc_obj_desc *obj_desc = data;
struct fsl_mc_device *mc_dev = to_fsl_mc_device(dev);
- return FSL_MC_DEVICE_MATCH(mc_dev, obj_desc);
+ return fsl_mc_device_match(mc_dev, obj_desc);
}
-static struct fsl_mc_device *fsl_mc_device_lookup(struct dprc_obj_desc
+static struct fsl_mc_device *fsl_mc_device_lookup(struct fsl_mc_obj_desc
*obj_desc,
struct fsl_mc_device
*mc_bus_dev)
@@ -133,16 +136,16 @@ static struct fsl_mc_device *fsl_mc_device_lookup(struct dprc_obj_desc
* device is unbound from the corresponding device driver.
*/
static void check_plugged_state_change(struct fsl_mc_device *mc_dev,
- struct dprc_obj_desc *obj_desc)
+ struct fsl_mc_obj_desc *obj_desc)
{
int error;
u32 plugged_flag_at_mc =
- obj_desc->state & DPRC_OBJ_STATE_PLUGGED;
+ obj_desc->state & FSL_MC_OBJ_STATE_PLUGGED;
if (plugged_flag_at_mc !=
- (mc_dev->obj_desc.state & DPRC_OBJ_STATE_PLUGGED)) {
+ (mc_dev->obj_desc.state & FSL_MC_OBJ_STATE_PLUGGED)) {
if (plugged_flag_at_mc) {
- mc_dev->obj_desc.state |= DPRC_OBJ_STATE_PLUGGED;
+ mc_dev->obj_desc.state |= FSL_MC_OBJ_STATE_PLUGGED;
error = device_attach(&mc_dev->dev);
if (error < 0) {
dev_err(&mc_dev->dev,
@@ -150,7 +153,7 @@ static void check_plugged_state_change(struct fsl_mc_device *mc_dev,
error);
}
} else {
- mc_dev->obj_desc.state &= ~DPRC_OBJ_STATE_PLUGGED;
+ mc_dev->obj_desc.state &= ~FSL_MC_OBJ_STATE_PLUGGED;
device_release_driver(&mc_dev->dev);
}
}
@@ -169,7 +172,7 @@ static void check_plugged_state_change(struct fsl_mc_device *mc_dev,
* in the physical DPRC.
*/
static void dprc_add_new_devices(struct fsl_mc_device *mc_bus_dev,
- struct dprc_obj_desc *obj_desc_array,
+ struct fsl_mc_obj_desc *obj_desc_array,
int num_child_objects_in_mc)
{
int error;
@@ -177,7 +180,7 @@ static void dprc_add_new_devices(struct fsl_mc_device *mc_bus_dev,
for (i = 0; i < num_child_objects_in_mc; i++) {
struct fsl_mc_device *child_dev;
- struct dprc_obj_desc *obj_desc = &obj_desc_array[i];
+ struct fsl_mc_obj_desc *obj_desc = &obj_desc_array[i];
if (strlen(obj_desc->type) == 0)
continue;
@@ -217,14 +220,14 @@ static void dprc_add_new_devices(struct fsl_mc_device *mc_bus_dev,
* populated before they can get allocation requests from probe callbacks
* of the device drivers for the non-allocatable devices.
*/
-int dprc_scan_objects(struct fsl_mc_device *mc_bus_dev,
- unsigned int *total_irq_count)
+static int dprc_scan_objects(struct fsl_mc_device *mc_bus_dev,
+ unsigned int *total_irq_count)
{
int num_child_objects;
int dprc_get_obj_failures;
int error;
unsigned int irq_count = mc_bus_dev->obj_desc.irq_count;
- struct dprc_obj_desc *child_obj_desc_array = NULL;
+ struct fsl_mc_obj_desc *child_obj_desc_array = NULL;
error = dprc_get_obj_count(mc_bus_dev->mc_io,
0,
@@ -251,7 +254,7 @@ int dprc_scan_objects(struct fsl_mc_device *mc_bus_dev,
*/
dprc_get_obj_failures = 0;
for (i = 0; i < num_child_objects; i++) {
- struct dprc_obj_desc *obj_desc =
+ struct fsl_mc_obj_desc *obj_desc =
&child_obj_desc_array[i];
error = dprc_get_obj(mc_bus_dev->mc_io,
@@ -279,7 +282,7 @@ int dprc_scan_objects(struct fsl_mc_device *mc_bus_dev,
if ((strcmp(obj_desc->type, "dpseci") == 0) &&
(obj_desc->ver_major < 4))
obj_desc->flags |=
- DPRC_OBJ_FLAG_NO_MEM_SHAREABILITY;
+ FSL_MC_OBJ_FLAG_NO_MEM_SHAREABILITY;
irq_count += obj_desc->irq_count;
dev_dbg(&mc_bus_dev->dev,
@@ -306,7 +309,6 @@ int dprc_scan_objects(struct fsl_mc_device *mc_bus_dev,
return 0;
}
-EXPORT_SYMBOL_GPL(dprc_scan_objects);
/**
* dprc_scan_container - Scans a physical DPRC and synchronizes Linux bus state
@@ -317,7 +319,7 @@ EXPORT_SYMBOL_GPL(dprc_scan_objects);
* bus driver with the actual state of the MC by adding and removing
* devices as appropriate.
*/
-int dprc_scan_container(struct fsl_mc_device *mc_bus_dev)
+static int dprc_scan_container(struct fsl_mc_device *mc_bus_dev)
{
int error;
unsigned int irq_count;
@@ -353,7 +355,6 @@ error:
fsl_mc_cleanup_all_resource_pools(mc_bus_dev);
return error;
}
-EXPORT_SYMBOL_GPL(dprc_scan_container);
/**
* dprc_irq0_handler - Regular ISR for DPRC interrupt 0
@@ -681,8 +682,8 @@ static int dprc_probe(struct fsl_mc_device *mc_dev)
}
if (major_ver < DPRC_MIN_VER_MAJOR ||
- (major_ver == DPRC_MIN_VER_MAJOR &&
- minor_ver < DPRC_MIN_VER_MINOR)) {
+ (major_ver == DPRC_MIN_VER_MAJOR &&
+ minor_ver < DPRC_MIN_VER_MINOR)) {
dev_err(&mc_dev->dev,
"ERROR: DPRC version %d.%d not supported\n",
major_ver, minor_ver);
diff --git a/drivers/staging/fsl-mc/bus/dprc.c b/drivers/staging/fsl-mc/bus/dprc.c
index fcf7b4767dc0..6f6c65a42166 100644
--- a/drivers/staging/fsl-mc/bus/dprc.c
+++ b/drivers/staging/fsl-mc/bus/dprc.c
@@ -29,9 +29,9 @@
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
-#include "../include/mc-sys.h"
-#include "../include/mc-cmd.h"
-#include "../include/dprc.h"
+#include <linux/kernel.h>
+#include "../include/mc.h"
+#include "dprc.h"
#include "dprc-cmd.h"
@@ -496,7 +496,7 @@ int dprc_get_obj(struct fsl_mc_io *mc_io,
u32 cmd_flags,
u16 token,
int obj_index,
- struct dprc_obj_desc *obj_desc)
+ struct fsl_mc_obj_desc *obj_desc)
{
struct mc_command cmd = { 0 };
struct dprc_cmd_get_obj *cmd_params;
diff --git a/drivers/staging/fsl-mc/include/dprc.h b/drivers/staging/fsl-mc/bus/dprc.h
index dc985cc1246f..21295e4feb04 100644
--- a/drivers/staging/fsl-mc/include/dprc.h
+++ b/drivers/staging/fsl-mc/bus/dprc.h
@@ -33,14 +33,13 @@
#ifndef _FSL_DPRC_H
#define _FSL_DPRC_H
-#include "mc-cmd.h"
-
/*
* Data Path Resource Container API
* Contains DPRC API for managing and querying DPAA resources
*/
struct fsl_mc_io;
+struct fsl_mc_obj_desc;
int dprc_open(struct fsl_mc_io *mc_io,
u32 cmd_flags,
@@ -51,7 +50,6 @@ int dprc_close(struct fsl_mc_io *mc_io,
u32 cmd_flags,
u16 token);
-
/* IRQ */
/* IRQ index */
@@ -170,59 +168,18 @@ int dprc_get_obj_count(struct fsl_mc_io *mc_io,
u16 token,
int *obj_count);
-/* Objects Attributes Flags */
-
-/* Opened state - Indicates that an object is open by at least one owner */
-#define DPRC_OBJ_STATE_OPEN 0x00000001
-/* Plugged state - Indicates that the object is plugged */
-#define DPRC_OBJ_STATE_PLUGGED 0x00000002
-
-/**
- * Shareability flag - Object flag indicating no memory shareability.
- * the object generates memory accesses that are non coherent with other
- * masters;
- * user is responsible for proper memory handling through IOMMU configuration.
- */
-#define DPRC_OBJ_FLAG_NO_MEM_SHAREABILITY 0x0001
-
-/**
- * struct dprc_obj_desc - Object descriptor, returned from dprc_get_obj()
- * @type: Type of object: NULL terminated string
- * @id: ID of logical object resource
- * @vendor: Object vendor identifier
- * @ver_major: Major version number
- * @ver_minor: Minor version number
- * @irq_count: Number of interrupts supported by the object
- * @region_count: Number of mappable regions supported by the object
- * @state: Object state: combination of DPRC_OBJ_STATE_ states
- * @label: Object label
- * @flags: Object's flags
- */
-struct dprc_obj_desc {
- char type[16];
- int id;
- u16 vendor;
- u16 ver_major;
- u16 ver_minor;
- u8 irq_count;
- u8 region_count;
- u32 state;
- char label[16];
- u16 flags;
-};
-
int dprc_get_obj(struct fsl_mc_io *mc_io,
u32 cmd_flags,
u16 token,
int obj_index,
- struct dprc_obj_desc *obj_desc);
+ struct fsl_mc_obj_desc *obj_desc);
int dprc_get_obj_desc(struct fsl_mc_io *mc_io,
u32 cmd_flags,
u16 token,
char *obj_type,
int obj_id,
- struct dprc_obj_desc *obj_desc);
+ struct fsl_mc_obj_desc *obj_desc);
int dprc_set_obj_irq(struct fsl_mc_io *mc_io,
u32 cmd_flags,
diff --git a/drivers/staging/fsl-mc/bus/fsl-mc-allocator.c b/drivers/staging/fsl-mc/bus/fsl-mc-allocator.c
index ce07096c3b1f..b37a6f48225f 100644
--- a/drivers/staging/fsl-mc/bus/fsl-mc-allocator.c
+++ b/drivers/staging/fsl-mc/bus/fsl-mc-allocator.c
@@ -10,17 +10,16 @@
#include <linux/module.h>
#include <linux/msi.h>
-#include "../include/mc-bus.h"
-#include "../include/mc-sys.h"
+#include "../include/mc.h"
-#include "dpbp-cmd.h"
-#include "dpcon-cmd.h"
#include "fsl-mc-private.h"
-#define FSL_MC_IS_ALLOCATABLE(_obj_type) \
- (strcmp(_obj_type, "dpbp") == 0 || \
- strcmp(_obj_type, "dpmcp") == 0 || \
- strcmp(_obj_type, "dpcon") == 0)
+static bool __must_check fsl_mc_is_allocatable(const char *obj_type)
+{
+ return strcmp(obj_type, "dpbp") ||
+ strcmp(obj_type, "dpmcp") ||
+ strcmp(obj_type, "dpcon");
+}
/**
* fsl_mc_resource_pool_add_device - add allocatable object to a resource
@@ -44,7 +43,7 @@ static int __must_check fsl_mc_resource_pool_add_device(struct fsl_mc_bus
if (WARN_ON(pool_type < 0 || pool_type >= FSL_MC_NUM_POOL_TYPES))
goto out;
- if (WARN_ON(!FSL_MC_IS_ALLOCATABLE(mc_dev->obj_desc.type)))
+ if (WARN_ON(!fsl_mc_is_allocatable(mc_dev->obj_desc.type)))
goto out;
if (WARN_ON(mc_dev->resource))
goto out;
@@ -106,7 +105,7 @@ static int __must_check fsl_mc_resource_pool_remove_device(struct fsl_mc_device
struct fsl_mc_resource *resource;
int error = -EINVAL;
- if (WARN_ON(!FSL_MC_IS_ALLOCATABLE(mc_dev->obj_desc.type)))
+ if (WARN_ON(!fsl_mc_is_allocatable(mc_dev->obj_desc.type)))
goto out;
resource = mc_dev->resource;
@@ -586,7 +585,7 @@ static int fsl_mc_allocator_probe(struct fsl_mc_device *mc_dev)
struct fsl_mc_bus *mc_bus;
int error;
- if (WARN_ON(!FSL_MC_IS_ALLOCATABLE(mc_dev->obj_desc.type)))
+ if (WARN_ON(!fsl_mc_is_allocatable(mc_dev->obj_desc.type)))
return -EINVAL;
mc_bus_dev = to_fsl_mc_device(mc_dev->dev.parent);
@@ -615,7 +614,7 @@ static int fsl_mc_allocator_remove(struct fsl_mc_device *mc_dev)
{
int error;
- if (WARN_ON(!FSL_MC_IS_ALLOCATABLE(mc_dev->obj_desc.type)))
+ if (WARN_ON(!fsl_mc_is_allocatable(mc_dev->obj_desc.type)))
return -EINVAL;
if (mc_dev->resource) {
diff --git a/drivers/staging/fsl-mc/bus/fsl-mc-bus.c b/drivers/staging/fsl-mc/bus/fsl-mc-bus.c
index 3be5f25ff113..19606e8d25dd 100644
--- a/drivers/staging/fsl-mc/bus/fsl-mc-bus.c
+++ b/drivers/staging/fsl-mc/bus/fsl-mc-bus.c
@@ -20,12 +20,10 @@
#include <linux/bitops.h>
#include <linux/msi.h>
#include <linux/dma-mapping.h>
-#include "../include/mc-bus.h"
-#include "../include/dpmng.h"
-#include "../include/mc-sys.h"
#include "fsl-mc-private.h"
#include "dprc-cmd.h"
+#include "dpmng-cmd.h"
/**
* Default DMA mask for devices on a fsl-mc bus
@@ -61,6 +59,20 @@ struct fsl_mc_addr_translation_range {
};
/**
+ * struct mc_version
+ * @major: Major version number: incremented on API compatibility changes
+ * @minor: Minor version number: incremented on API additions (that are
+ * backward compatible); reset when major version is incremented
+ * @revision: Internal revision number: incremented on implementation changes
+ * and/or bug fixes that have no impact on API
+ */
+struct mc_version {
+ u32 major;
+ u32 minor;
+ u32 revision;
+};
+
+/**
* fsl_mc_bus_match - device to driver matching callback
* @dev: the fsl-mc device to match against
* @drv: the device driver to search for matching fsl-mc object type
@@ -82,7 +94,7 @@ static int fsl_mc_bus_match(struct device *dev, struct device_driver *drv)
* If the object is not 'plugged' don't match.
* Only exception is the root DPRC, which is a special case.
*/
- if ((mc_dev->obj_desc.state & DPRC_OBJ_STATE_PLUGGED) == 0 &&
+ if ((mc_dev->obj_desc.state & FSL_MC_OBJ_STATE_PLUGGED) == 0 &&
!fsl_mc_is_root_dprc(&mc_dev->dev))
goto out;
@@ -239,10 +251,46 @@ void fsl_mc_driver_unregister(struct fsl_mc_driver *mc_driver)
EXPORT_SYMBOL_GPL(fsl_mc_driver_unregister);
/**
+ * mc_get_version() - Retrieves the Management Complex firmware
+ * version information
+ * @mc_io: Pointer to opaque I/O object
+ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
+ * @mc_ver_info: Returned version information structure
+ *
+ * Return: '0' on Success; Error code otherwise.
+ */
+static int mc_get_version(struct fsl_mc_io *mc_io,
+ u32 cmd_flags,
+ struct mc_version *mc_ver_info)
+{
+ struct mc_command cmd = { 0 };
+ struct dpmng_rsp_get_version *rsp_params;
+ int err;
+
+ /* prepare command */
+ cmd.header = mc_encode_cmd_header(DPMNG_CMDID_GET_VERSION,
+ cmd_flags,
+ 0);
+
+ /* send command to mc*/
+ err = mc_send_command(mc_io, &cmd);
+ if (err)
+ return err;
+
+ /* retrieve response parameters */
+ rsp_params = (struct dpmng_rsp_get_version *)cmd.params;
+ mc_ver_info->revision = le32_to_cpu(rsp_params->revision);
+ mc_ver_info->major = le32_to_cpu(rsp_params->version_major);
+ mc_ver_info->minor = le32_to_cpu(rsp_params->version_minor);
+
+ return 0;
+}
+
+/**
* fsl_mc_get_root_dprc - function to traverse to the root dprc
*/
-void fsl_mc_get_root_dprc(struct device *dev,
- struct device **root_dprc_dev)
+static void fsl_mc_get_root_dprc(struct device *dev,
+ struct device **root_dprc_dev)
{
if (WARN_ON(!dev)) {
*root_dprc_dev = NULL;
@@ -254,7 +302,6 @@ void fsl_mc_get_root_dprc(struct device *dev,
*root_dprc_dev = (*root_dprc_dev)->parent;
}
}
-EXPORT_SYMBOL_GPL(fsl_mc_get_root_dprc);
static int get_dprc_attr(struct fsl_mc_io *mc_io,
int container_id, struct dprc_attributes *attr)
@@ -339,7 +386,7 @@ static int fsl_mc_device_get_mmio_regions(struct fsl_mc_device *mc_dev,
int i;
int error;
struct resource *regions;
- struct dprc_obj_desc *obj_desc = &mc_dev->obj_desc;
+ struct fsl_mc_obj_desc *obj_desc = &mc_dev->obj_desc;
struct device *parent_dev = mc_dev->dev.parent;
enum dprc_region_type mc_region_type;
@@ -420,15 +467,11 @@ bool fsl_mc_is_root_dprc(struct device *dev)
static void fsl_mc_device_release(struct device *dev)
{
struct fsl_mc_device *mc_dev = to_fsl_mc_device(dev);
- struct fsl_mc_bus *mc_bus = NULL;
kfree(mc_dev->regions);
if (strcmp(mc_dev->obj_desc.type, "dprc") == 0)
- mc_bus = to_fsl_mc_bus(mc_dev);
-
- if (mc_bus)
- kfree(mc_bus);
+ kfree(to_fsl_mc_bus(mc_dev));
else
kfree(mc_dev);
}
@@ -436,7 +479,7 @@ static void fsl_mc_device_release(struct device *dev)
/**
* Add a newly discovered fsl-mc device to be visible in Linux
*/
-int fsl_mc_device_add(struct dprc_obj_desc *obj_desc,
+int fsl_mc_device_add(struct fsl_mc_obj_desc *obj_desc,
struct fsl_mc_io *mc_io,
struct device *parent_dev,
struct fsl_mc_device **new_mc_dev)
@@ -538,7 +581,7 @@ int fsl_mc_device_add(struct dprc_obj_desc *obj_desc,
}
/* Objects are coherent, unless 'no shareability' flag set. */
- if (!(obj_desc->flags & DPRC_OBJ_FLAG_NO_MEM_SHAREABILITY))
+ if (!(obj_desc->flags & FSL_MC_OBJ_FLAG_NO_MEM_SHAREABILITY))
arch_setup_dma_ops(&mc_dev->dev, 0, 0, NULL, true);
/*
@@ -559,10 +602,8 @@ int fsl_mc_device_add(struct dprc_obj_desc *obj_desc,
error_cleanup_dev:
kfree(mc_dev->regions);
- if (mc_bus)
- kfree(mc_bus);
- else
- kfree(mc_dev);
+ kfree(mc_bus);
+ kfree(mc_dev);
return error;
}
@@ -644,10 +685,10 @@ static int get_mc_addr_translation_ranges(struct device *dev,
const __be32 *cell;
ret = parse_mc_ranges(dev,
- &paddr_cells,
- &mc_addr_cells,
- &mc_size_cells,
- &ranges_start);
+ &paddr_cells,
+ &mc_addr_cells,
+ &mc_size_cells,
+ &ranges_start);
if (ret < 0)
return ret;
@@ -693,7 +734,7 @@ static int get_mc_addr_translation_ranges(struct device *dev,
*/
static int fsl_mc_bus_probe(struct platform_device *pdev)
{
- struct dprc_obj_desc obj_desc;
+ struct fsl_mc_obj_desc obj_desc;
int error;
struct fsl_mc *mc;
struct fsl_mc_device *mc_bus_dev = NULL;
@@ -752,7 +793,7 @@ static int fsl_mc_bus_probe(struct platform_device *pdev)
goto error_cleanup_mc_io;
}
- memset(&obj_desc, 0, sizeof(struct dprc_obj_desc));
+ memset(&obj_desc, 0, sizeof(struct fsl_mc_obj_desc));
error = dprc_get_api_version(mc_io, 0,
&obj_desc.ver_major,
&obj_desc.ver_minor);
diff --git a/drivers/staging/fsl-mc/bus/fsl-mc-msi.c b/drivers/staging/fsl-mc/bus/fsl-mc-msi.c
index b8b2c86e63d4..c04a2f2b3409 100644
--- a/drivers/staging/fsl-mc/bus/fsl-mc-msi.c
+++ b/drivers/staging/fsl-mc/bus/fsl-mc-msi.c
@@ -16,7 +16,6 @@
#include <linux/irq.h>
#include <linux/irqdomain.h>
#include <linux/msi.h>
-#include "../include/mc-bus.h"
#include "fsl-mc-private.h"
/*
@@ -170,7 +169,7 @@ struct irq_domain *fsl_mc_msi_create_irq_domain(struct fwnode_handle *fwnode,
domain = msi_create_irq_domain(fwnode, info, parent);
if (domain)
- domain->bus_token = DOMAIN_BUS_FSL_MC_MSI;
+ irq_domain_update_bus_token(domain, DOMAIN_BUS_FSL_MC_MSI);
return domain;
}
diff --git a/drivers/staging/fsl-mc/bus/fsl-mc-private.h b/drivers/staging/fsl-mc/bus/fsl-mc-private.h
index 5c49c9d2df6a..62d398947605 100644
--- a/drivers/staging/fsl-mc/bus/fsl-mc-private.h
+++ b/drivers/staging/fsl-mc/bus/fsl-mc-private.h
@@ -11,9 +11,56 @@
#define _FSL_MC_PRIVATE_H_
#include "../include/mc.h"
-#include "../include/mc-bus.h"
+#include "dprc.h"
+#include <linux/mutex.h>
-int __must_check fsl_mc_device_add(struct dprc_obj_desc *obj_desc,
+/**
+ * Maximum number of total IRQs that can be pre-allocated for an MC bus'
+ * IRQ pool
+ */
+#define FSL_MC_IRQ_POOL_MAX_TOTAL_IRQS 256
+
+/**
+ * struct fsl_mc_resource_pool - Pool of MC resources of a given
+ * type
+ * @type: type of resources in the pool
+ * @max_count: maximum number of resources in the pool
+ * @free_count: number of free resources in the pool
+ * @mutex: mutex to serialize access to the pool's free list
+ * @free_list: anchor node of list of free resources in the pool
+ * @mc_bus: pointer to the MC bus that owns this resource pool
+ */
+struct fsl_mc_resource_pool {
+ enum fsl_mc_pool_type type;
+ int max_count;
+ int free_count;
+ struct mutex mutex; /* serializes access to free_list */
+ struct list_head free_list;
+ struct fsl_mc_bus *mc_bus;
+};
+
+/**
+ * struct fsl_mc_bus - logical bus that corresponds to a physical DPRC
+ * @mc_dev: fsl-mc device for the bus device itself.
+ * @resource_pools: array of resource pools (one pool per resource type)
+ * for this MC bus. These resources represent allocatable entities
+ * from the physical DPRC.
+ * @irq_resources: Pointer to array of IRQ objects for the IRQ pool
+ * @scan_mutex: Serializes bus scanning
+ * @dprc_attr: DPRC attributes
+ */
+struct fsl_mc_bus {
+ struct fsl_mc_device mc_dev;
+ struct fsl_mc_resource_pool resource_pools[FSL_MC_NUM_POOL_TYPES];
+ struct fsl_mc_device_irq *irq_resources;
+ struct mutex scan_mutex; /* serializes bus scanning */
+ struct dprc_attributes dprc_attr;
+};
+
+#define to_fsl_mc_bus(_mc_dev) \
+ container_of(_mc_dev, struct fsl_mc_bus, mc_dev)
+
+int __must_check fsl_mc_device_add(struct fsl_mc_obj_desc *obj_desc,
struct fsl_mc_io *mc_io,
struct device *parent_dev,
struct fsl_mc_device **new_mc_dev);
@@ -28,6 +75,10 @@ int __init fsl_mc_allocator_driver_init(void);
void fsl_mc_allocator_driver_exit(void);
+void fsl_mc_init_all_resource_pools(struct fsl_mc_device *mc_bus_dev);
+
+void fsl_mc_cleanup_all_resource_pools(struct fsl_mc_device *mc_bus_dev);
+
int __must_check fsl_mc_resource_allocate(struct fsl_mc_bus *mc_bus,
enum fsl_mc_pool_type pool_type,
struct fsl_mc_resource
@@ -44,6 +95,14 @@ int __init its_fsl_mc_msi_init(void);
void its_fsl_mc_msi_cleanup(void);
+int fsl_mc_find_msi_domain(struct device *mc_platform_dev,
+ struct irq_domain **mc_msi_domain);
+
+int fsl_mc_populate_irq_pool(struct fsl_mc_bus *mc_bus,
+ unsigned int irq_count);
+
+void fsl_mc_cleanup_irq_pool(struct fsl_mc_bus *mc_bus);
+
int __must_check fsl_create_mc_io(struct device *dev,
phys_addr_t mc_portal_phys_addr,
u32 mc_portal_size,
@@ -52,4 +111,6 @@ int __must_check fsl_create_mc_io(struct device *dev,
void fsl_destroy_mc_io(struct fsl_mc_io *mc_io);
+bool fsl_mc_is_root_dprc(struct device *dev);
+
#endif /* _FSL_MC_PRIVATE_H_ */
diff --git a/drivers/staging/fsl-mc/bus/irq-gic-v3-its-fsl-mc-msi.c b/drivers/staging/fsl-mc/bus/irq-gic-v3-its-fsl-mc-msi.c
index 49127acb85b2..865d38517508 100644
--- a/drivers/staging/fsl-mc/bus/irq-gic-v3-its-fsl-mc-msi.c
+++ b/drivers/staging/fsl-mc/bus/irq-gic-v3-its-fsl-mc-msi.c
@@ -16,7 +16,6 @@
#include <linux/msi.h>
#include <linux/of.h>
#include <linux/of_irq.h>
-#include "../include/mc-bus.h"
#include "fsl-mc-private.h"
static struct irq_chip its_msi_irq_chip = {
diff --git a/drivers/staging/fsl-mc/bus/mc-io.c b/drivers/staging/fsl-mc/bus/mc-io.c
index d66b87f0903b..35221a17858b 100644
--- a/drivers/staging/fsl-mc/bus/mc-io.c
+++ b/drivers/staging/fsl-mc/bus/mc-io.c
@@ -31,8 +31,7 @@
*/
#include <linux/io.h>
-#include "../include/mc-bus.h"
-#include "../include/mc-sys.h"
+#include "../include/mc.h"
#include "fsl-mc-private.h"
#include "dpmcp.h"
diff --git a/drivers/staging/fsl-mc/bus/mc-sys.c b/drivers/staging/fsl-mc/bus/mc-sys.c
index 4d82802b384d..a1704c3a6a78 100644
--- a/drivers/staging/fsl-mc/bus/mc-sys.c
+++ b/drivers/staging/fsl-mc/bus/mc-sys.c
@@ -37,8 +37,6 @@
#include <linux/ioport.h>
#include <linux/device.h>
#include <linux/io.h>
-#include "../include/mc-sys.h"
-#include "../include/mc-cmd.h"
#include "../include/mc.h"
#include "dpmcp.h"
diff --git a/drivers/staging/fsl-mc/include/dpmng.h b/drivers/staging/fsl-mc/include/dpmng.h
deleted file mode 100644
index 170c07dd376a..000000000000
--- a/drivers/staging/fsl-mc/include/dpmng.h
+++ /dev/null
@@ -1,67 +0,0 @@
-/*
- * Copyright 2013-2016 Freescale Semiconductor Inc.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * * Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * * Neither the name of the above-listed copyright holders nor the
- * names of any contributors may be used to endorse or promote products
- * derived from this software without specific prior written permission.
- *
- *
- * ALTERNATIVELY, this software may be distributed under the terms of the
- * GNU General Public License ("GPL") as published by the Free Software
- * Foundation, either version 2 of that License or (at your option) any
- * later version.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- * POSSIBILITY OF SUCH DAMAGE.
- */
-#ifndef __FSL_DPMNG_H
-#define __FSL_DPMNG_H
-
-/*
- * Management Complex General API
- * Contains general API for the Management Complex firmware
- */
-
-struct fsl_mc_io;
-
-/**
- * Management Complex firmware version information
- */
-#define MC_VER_MAJOR 8
-#define MC_VER_MINOR 0
-
-/**
- * struct mc_version
- * @major: Major version number: incremented on API compatibility changes
- * @minor: Minor version number: incremented on API additions (that are
- * backward compatible); reset when major version is incremented
- * @revision: Internal revision number: incremented on implementation changes
- * and/or bug fixes that have no impact on API
- */
-struct mc_version {
- u32 major;
- u32 minor;
- u32 revision;
-};
-
-int mc_get_version(struct fsl_mc_io *mc_io,
- u32 cmd_flags,
- struct mc_version *mc_ver_info);
-
-#endif /* __FSL_DPMNG_H */
diff --git a/drivers/staging/fsl-mc/include/mc-bus.h b/drivers/staging/fsl-mc/include/mc-bus.h
deleted file mode 100644
index 42700de94d59..000000000000
--- a/drivers/staging/fsl-mc/include/mc-bus.h
+++ /dev/null
@@ -1,111 +0,0 @@
-/*
- * Freescale Management Complex (MC) bus declarations
- *
- * Copyright (C) 2014-2016 Freescale Semiconductor, Inc.
- * Author: German Rivera <German.Rivera@freescale.com>
- *
- * This file is licensed under the terms of the GNU General Public
- * License version 2. This program is licensed "as is" without any
- * warranty of any kind, whether express or implied.
- */
-#ifndef _FSL_MC_MCBUS_H_
-#define _FSL_MC_MCBUS_H_
-
-#include "../include/mc.h"
-#include <linux/mutex.h>
-
-struct irq_domain;
-struct msi_domain_info;
-
-/**
- * Maximum number of total IRQs that can be pre-allocated for an MC bus'
- * IRQ pool
- */
-#define FSL_MC_IRQ_POOL_MAX_TOTAL_IRQS 256
-
-#ifdef CONFIG_FSL_MC_BUS
-#define dev_is_fsl_mc(_dev) ((_dev)->bus == &fsl_mc_bus_type)
-#else
-/* If fsl-mc bus is not present device cannot belong to fsl-mc bus */
-#define dev_is_fsl_mc(_dev) (0)
-#endif
-
-/**
- * struct fsl_mc_resource_pool - Pool of MC resources of a given
- * type
- * @type: type of resources in the pool
- * @max_count: maximum number of resources in the pool
- * @free_count: number of free resources in the pool
- * @mutex: mutex to serialize access to the pool's free list
- * @free_list: anchor node of list of free resources in the pool
- * @mc_bus: pointer to the MC bus that owns this resource pool
- */
-struct fsl_mc_resource_pool {
- enum fsl_mc_pool_type type;
- int max_count;
- int free_count;
- struct mutex mutex; /* serializes access to free_list */
- struct list_head free_list;
- struct fsl_mc_bus *mc_bus;
-};
-
-/**
- * struct fsl_mc_bus - logical bus that corresponds to a physical DPRC
- * @mc_dev: fsl-mc device for the bus device itself.
- * @resource_pools: array of resource pools (one pool per resource type)
- * for this MC bus. These resources represent allocatable entities
- * from the physical DPRC.
- * @irq_resources: Pointer to array of IRQ objects for the IRQ pool
- * @scan_mutex: Serializes bus scanning
- * @dprc_attr: DPRC attributes
- */
-struct fsl_mc_bus {
- struct fsl_mc_device mc_dev;
- struct fsl_mc_resource_pool resource_pools[FSL_MC_NUM_POOL_TYPES];
- struct fsl_mc_device_irq *irq_resources;
- struct mutex scan_mutex; /* serializes bus scanning */
- struct dprc_attributes dprc_attr;
-};
-
-#define to_fsl_mc_bus(_mc_dev) \
- container_of(_mc_dev, struct fsl_mc_bus, mc_dev)
-
-int dprc_scan_container(struct fsl_mc_device *mc_bus_dev);
-
-int dprc_scan_objects(struct fsl_mc_device *mc_bus_dev,
- unsigned int *total_irq_count);
-
-int __init dprc_driver_init(void);
-
-void dprc_driver_exit(void);
-
-int __init fsl_mc_allocator_driver_init(void);
-
-void fsl_mc_allocator_driver_exit(void);
-
-struct irq_domain *fsl_mc_msi_create_irq_domain(struct fwnode_handle *fwnode,
- struct msi_domain_info *info,
- struct irq_domain *parent);
-
-int fsl_mc_find_msi_domain(struct device *mc_platform_dev,
- struct irq_domain **mc_msi_domain);
-
-int fsl_mc_populate_irq_pool(struct fsl_mc_bus *mc_bus,
- unsigned int irq_count);
-
-void fsl_mc_cleanup_irq_pool(struct fsl_mc_bus *mc_bus);
-
-void fsl_mc_init_all_resource_pools(struct fsl_mc_device *mc_bus_dev);
-
-void fsl_mc_cleanup_all_resource_pools(struct fsl_mc_device *mc_bus_dev);
-
-bool fsl_mc_bus_exists(void);
-
-void fsl_mc_get_root_dprc(struct device *dev,
- struct device **root_dprc_dev);
-
-bool fsl_mc_is_root_dprc(struct device *dev);
-
-extern struct bus_type fsl_mc_bus_type;
-
-#endif /* _FSL_MC_MCBUS_H_ */
diff --git a/drivers/staging/fsl-mc/include/mc-cmd.h b/drivers/staging/fsl-mc/include/mc-cmd.h
deleted file mode 100644
index 2e08aa31b084..000000000000
--- a/drivers/staging/fsl-mc/include/mc-cmd.h
+++ /dev/null
@@ -1,130 +0,0 @@
-/*
- * Copyright 2013-2016 Freescale Semiconductor Inc.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * * Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * * Neither the name of the above-listed copyright holders nor the
- * names of any contributors may be used to endorse or promote products
- * derived from this software without specific prior written permission.
- *
- *
- * ALTERNATIVELY, this software may be distributed under the terms of the
- * GNU General Public License ("GPL") as published by the Free Software
- * Foundation, either version 2 of that License or (at your option) any
- * later version.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- * POSSIBILITY OF SUCH DAMAGE.
- */
-#ifndef __FSL_MC_CMD_H
-#define __FSL_MC_CMD_H
-
-#define MC_CMD_NUM_OF_PARAMS 7
-
-struct mc_cmd_header {
- u8 src_id;
- u8 flags_hw;
- u8 status;
- u8 flags_sw;
- __le16 token;
- __le16 cmd_id;
-};
-
-struct mc_command {
- u64 header;
- u64 params[MC_CMD_NUM_OF_PARAMS];
-};
-
-struct mc_rsp_create {
- __le32 object_id;
-};
-
-struct mc_rsp_api_ver {
- __le16 major_ver;
- __le16 minor_ver;
-};
-
-enum mc_cmd_status {
- MC_CMD_STATUS_OK = 0x0, /* Completed successfully */
- MC_CMD_STATUS_READY = 0x1, /* Ready to be processed */
- MC_CMD_STATUS_AUTH_ERR = 0x3, /* Authentication error */
- MC_CMD_STATUS_NO_PRIVILEGE = 0x4, /* No privilege */
- MC_CMD_STATUS_DMA_ERR = 0x5, /* DMA or I/O error */
- MC_CMD_STATUS_CONFIG_ERR = 0x6, /* Configuration error */
- MC_CMD_STATUS_TIMEOUT = 0x7, /* Operation timed out */
- MC_CMD_STATUS_NO_RESOURCE = 0x8, /* No resources */
- MC_CMD_STATUS_NO_MEMORY = 0x9, /* No memory available */
- MC_CMD_STATUS_BUSY = 0xA, /* Device is busy */
- MC_CMD_STATUS_UNSUPPORTED_OP = 0xB, /* Unsupported operation */
- MC_CMD_STATUS_INVALID_STATE = 0xC /* Invalid state */
-};
-
-/*
- * MC command flags
- */
-
-/* High priority flag */
-#define MC_CMD_FLAG_PRI 0x80
-/* Command completion flag */
-#define MC_CMD_FLAG_INTR_DIS 0x01
-
-static inline u64 mc_encode_cmd_header(u16 cmd_id,
- u32 cmd_flags,
- u16 token)
-{
- u64 header = 0;
- struct mc_cmd_header *hdr = (struct mc_cmd_header *)&header;
-
- hdr->cmd_id = cpu_to_le16(cmd_id);
- hdr->token = cpu_to_le16(token);
- hdr->status = MC_CMD_STATUS_READY;
- if (cmd_flags & MC_CMD_FLAG_PRI)
- hdr->flags_hw = MC_CMD_FLAG_PRI;
- if (cmd_flags & MC_CMD_FLAG_INTR_DIS)
- hdr->flags_sw = MC_CMD_FLAG_INTR_DIS;
-
- return header;
-}
-
-static inline u16 mc_cmd_hdr_read_token(struct mc_command *cmd)
-{
- struct mc_cmd_header *hdr = (struct mc_cmd_header *)&cmd->header;
- u16 token = le16_to_cpu(hdr->token);
-
- return token;
-}
-
-static inline u32 mc_cmd_read_object_id(struct mc_command *cmd)
-{
- struct mc_rsp_create *rsp_params;
-
- rsp_params = (struct mc_rsp_create *)cmd->params;
- return le32_to_cpu(rsp_params->object_id);
-}
-
-static inline void mc_cmd_read_api_version(struct mc_command *cmd,
- u16 *major_ver,
- u16 *minor_ver)
-{
- struct mc_rsp_api_ver *rsp_params;
-
- rsp_params = (struct mc_rsp_api_ver *)cmd->params;
- *major_ver = le16_to_cpu(rsp_params->major_ver);
- *minor_ver = le16_to_cpu(rsp_params->minor_ver);
-}
-
-#endif /* __FSL_MC_CMD_H */
diff --git a/drivers/staging/fsl-mc/include/mc-sys.h b/drivers/staging/fsl-mc/include/mc-sys.h
deleted file mode 100644
index dca7f9084e05..000000000000
--- a/drivers/staging/fsl-mc/include/mc-sys.h
+++ /dev/null
@@ -1,99 +0,0 @@
-/*
- * Copyright 2013-2016 Freescale Semiconductor Inc.
- *
- * Interface of the I/O services to send MC commands to the MC hardware
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * * Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * * Neither the name of the above-listed copyright holders nor the
- * names of any contributors may be used to endorse or promote products
- * derived from this software without specific prior written permission.
- *
- *
- * ALTERNATIVELY, this software may be distributed under the terms of the
- * GNU General Public License ("GPL") as published by the Free Software
- * Foundation, either version 2 of that License or (at your option) any
- * later version.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- * POSSIBILITY OF SUCH DAMAGE.
- */
-
-#ifndef _FSL_MC_SYS_H
-#define _FSL_MC_SYS_H
-
-#include <linux/types.h>
-#include <linux/errno.h>
-#include <linux/mutex.h>
-#include <linux/spinlock.h>
-
-/**
- * Bit masks for a MC I/O object (struct fsl_mc_io) flags
- */
-#define FSL_MC_IO_ATOMIC_CONTEXT_PORTAL 0x0001
-
-struct fsl_mc_resource;
-struct mc_command;
-
-/**
- * struct fsl_mc_io - MC I/O object to be passed-in to mc_send_command()
- * @dev: device associated with this Mc I/O object
- * @flags: flags for mc_send_command()
- * @portal_size: MC command portal size in bytes
- * @portal_phys_addr: MC command portal physical address
- * @portal_virt_addr: MC command portal virtual address
- * @dpmcp_dev: pointer to the DPMCP device associated with the MC portal.
- *
- * Fields are only meaningful if the FSL_MC_IO_ATOMIC_CONTEXT_PORTAL flag is not
- * set:
- * @mutex: Mutex to serialize mc_send_command() calls that use the same MC
- * portal, if the fsl_mc_io object was created with the
- * FSL_MC_IO_ATOMIC_CONTEXT_PORTAL flag off. mc_send_command() calls for this
- * fsl_mc_io object must be made only from non-atomic context.
- *
- * Fields are only meaningful if the FSL_MC_IO_ATOMIC_CONTEXT_PORTAL flag is
- * set:
- * @spinlock: Spinlock to serialize mc_send_command() calls that use the same MC
- * portal, if the fsl_mc_io object was created with the
- * FSL_MC_IO_ATOMIC_CONTEXT_PORTAL flag on. mc_send_command() calls for this
- * fsl_mc_io object can be made from atomic or non-atomic context.
- */
-struct fsl_mc_io {
- struct device *dev;
- u16 flags;
- u16 portal_size;
- phys_addr_t portal_phys_addr;
- void __iomem *portal_virt_addr;
- struct fsl_mc_device *dpmcp_dev;
- union {
- /*
- * This field is only meaningful if the
- * FSL_MC_IO_ATOMIC_CONTEXT_PORTAL flag is not set
- */
- struct mutex mutex; /* serializes mc_send_command() */
-
- /*
- * This field is only meaningful if the
- * FSL_MC_IO_ATOMIC_CONTEXT_PORTAL flag is set
- */
- spinlock_t spinlock; /* serializes mc_send_command() */
- };
-};
-
-int mc_send_command(struct fsl_mc_io *mc_io, struct mc_command *cmd);
-
-#endif /* _FSL_MC_SYS_H */
diff --git a/drivers/staging/fsl-mc/include/mc.h b/drivers/staging/fsl-mc/include/mc.h
index 1c46c0c2a895..aafe63a21f49 100644
--- a/drivers/staging/fsl-mc/include/mc.h
+++ b/drivers/staging/fsl-mc/include/mc.h
@@ -14,10 +14,12 @@
#include <linux/device.h>
#include <linux/mod_devicetable.h>
#include <linux/interrupt.h>
-#include "../include/dprc.h"
#define FSL_MC_VENDOR_FREESCALE 0x1957
+struct irq_domain;
+struct msi_domain_info;
+
struct fsl_mc_device;
struct fsl_mc_io;
@@ -104,6 +106,45 @@ struct fsl_mc_device_irq {
#define to_fsl_mc_irq(_mc_resource) \
container_of(_mc_resource, struct fsl_mc_device_irq, resource)
+/* Opened state - Indicates that an object is open by at least one owner */
+#define FSL_MC_OBJ_STATE_OPEN 0x00000001
+/* Plugged state - Indicates that the object is plugged */
+#define FSL_MC_OBJ_STATE_PLUGGED 0x00000002
+
+/**
+ * Shareability flag - Object flag indicating no memory shareability.
+ * the object generates memory accesses that are non coherent with other
+ * masters;
+ * user is responsible for proper memory handling through IOMMU configuration.
+ */
+#define FSL_MC_OBJ_FLAG_NO_MEM_SHAREABILITY 0x0001
+
+/**
+ * struct fsl_mc_obj_desc - Object descriptor
+ * @type: Type of object: NULL terminated string
+ * @id: ID of logical object resource
+ * @vendor: Object vendor identifier
+ * @ver_major: Major version number
+ * @ver_minor: Minor version number
+ * @irq_count: Number of interrupts supported by the object
+ * @region_count: Number of mappable regions supported by the object
+ * @state: Object state: combination of FSL_MC_OBJ_STATE_ states
+ * @label: Object label: NULL terminated string
+ * @flags: Object's flags
+ */
+struct fsl_mc_obj_desc {
+ char type[16];
+ int id;
+ u16 vendor;
+ u16 ver_major;
+ u16 ver_minor;
+ u8 irq_count;
+ u8 region_count;
+ u32 state;
+ char label[16];
+ u16 flags;
+};
+
/**
* Bit masks for a MC object device (struct fsl_mc_device) flags
*/
@@ -150,7 +191,7 @@ struct fsl_mc_device {
u16 icid;
u16 mc_handle;
struct fsl_mc_io *mc_io;
- struct dprc_obj_desc obj_desc;
+ struct fsl_mc_obj_desc obj_desc;
struct resource *regions;
struct fsl_mc_device_irq **irqs;
struct fsl_mc_resource *resource;
@@ -159,6 +200,159 @@ struct fsl_mc_device {
#define to_fsl_mc_device(_dev) \
container_of(_dev, struct fsl_mc_device, dev)
+#define MC_CMD_NUM_OF_PARAMS 7
+
+struct mc_cmd_header {
+ u8 src_id;
+ u8 flags_hw;
+ u8 status;
+ u8 flags_sw;
+ __le16 token;
+ __le16 cmd_id;
+};
+
+struct mc_command {
+ u64 header;
+ u64 params[MC_CMD_NUM_OF_PARAMS];
+};
+
+enum mc_cmd_status {
+ MC_CMD_STATUS_OK = 0x0, /* Completed successfully */
+ MC_CMD_STATUS_READY = 0x1, /* Ready to be processed */
+ MC_CMD_STATUS_AUTH_ERR = 0x3, /* Authentication error */
+ MC_CMD_STATUS_NO_PRIVILEGE = 0x4, /* No privilege */
+ MC_CMD_STATUS_DMA_ERR = 0x5, /* DMA or I/O error */
+ MC_CMD_STATUS_CONFIG_ERR = 0x6, /* Configuration error */
+ MC_CMD_STATUS_TIMEOUT = 0x7, /* Operation timed out */
+ MC_CMD_STATUS_NO_RESOURCE = 0x8, /* No resources */
+ MC_CMD_STATUS_NO_MEMORY = 0x9, /* No memory available */
+ MC_CMD_STATUS_BUSY = 0xA, /* Device is busy */
+ MC_CMD_STATUS_UNSUPPORTED_OP = 0xB, /* Unsupported operation */
+ MC_CMD_STATUS_INVALID_STATE = 0xC /* Invalid state */
+};
+
+/*
+ * MC command flags
+ */
+
+/* High priority flag */
+#define MC_CMD_FLAG_PRI 0x80
+/* Command completion flag */
+#define MC_CMD_FLAG_INTR_DIS 0x01
+
+static inline u64 mc_encode_cmd_header(u16 cmd_id,
+ u32 cmd_flags,
+ u16 token)
+{
+ u64 header = 0;
+ struct mc_cmd_header *hdr = (struct mc_cmd_header *)&header;
+
+ hdr->cmd_id = cpu_to_le16(cmd_id);
+ hdr->token = cpu_to_le16(token);
+ hdr->status = MC_CMD_STATUS_READY;
+ if (cmd_flags & MC_CMD_FLAG_PRI)
+ hdr->flags_hw = MC_CMD_FLAG_PRI;
+ if (cmd_flags & MC_CMD_FLAG_INTR_DIS)
+ hdr->flags_sw = MC_CMD_FLAG_INTR_DIS;
+
+ return header;
+}
+
+static inline u16 mc_cmd_hdr_read_token(struct mc_command *cmd)
+{
+ struct mc_cmd_header *hdr = (struct mc_cmd_header *)&cmd->header;
+ u16 token = le16_to_cpu(hdr->token);
+
+ return token;
+}
+
+struct mc_rsp_create {
+ __le32 object_id;
+};
+
+struct mc_rsp_api_ver {
+ __le16 major_ver;
+ __le16 minor_ver;
+};
+
+static inline u32 mc_cmd_read_object_id(struct mc_command *cmd)
+{
+ struct mc_rsp_create *rsp_params;
+
+ rsp_params = (struct mc_rsp_create *)cmd->params;
+ return le32_to_cpu(rsp_params->object_id);
+}
+
+static inline void mc_cmd_read_api_version(struct mc_command *cmd,
+ u16 *major_ver,
+ u16 *minor_ver)
+{
+ struct mc_rsp_api_ver *rsp_params;
+
+ rsp_params = (struct mc_rsp_api_ver *)cmd->params;
+ *major_ver = le16_to_cpu(rsp_params->major_ver);
+ *minor_ver = le16_to_cpu(rsp_params->minor_ver);
+}
+
+/**
+ * Bit masks for a MC I/O object (struct fsl_mc_io) flags
+ */
+#define FSL_MC_IO_ATOMIC_CONTEXT_PORTAL 0x0001
+
+/**
+ * struct fsl_mc_io - MC I/O object to be passed-in to mc_send_command()
+ * @dev: device associated with this Mc I/O object
+ * @flags: flags for mc_send_command()
+ * @portal_size: MC command portal size in bytes
+ * @portal_phys_addr: MC command portal physical address
+ * @portal_virt_addr: MC command portal virtual address
+ * @dpmcp_dev: pointer to the DPMCP device associated with the MC portal.
+ *
+ * Fields are only meaningful if the FSL_MC_IO_ATOMIC_CONTEXT_PORTAL flag is not
+ * set:
+ * @mutex: Mutex to serialize mc_send_command() calls that use the same MC
+ * portal, if the fsl_mc_io object was created with the
+ * FSL_MC_IO_ATOMIC_CONTEXT_PORTAL flag off. mc_send_command() calls for this
+ * fsl_mc_io object must be made only from non-atomic context.
+ *
+ * Fields are only meaningful if the FSL_MC_IO_ATOMIC_CONTEXT_PORTAL flag is
+ * set:
+ * @spinlock: Spinlock to serialize mc_send_command() calls that use the same MC
+ * portal, if the fsl_mc_io object was created with the
+ * FSL_MC_IO_ATOMIC_CONTEXT_PORTAL flag on. mc_send_command() calls for this
+ * fsl_mc_io object can be made from atomic or non-atomic context.
+ */
+struct fsl_mc_io {
+ struct device *dev;
+ u16 flags;
+ u16 portal_size;
+ phys_addr_t portal_phys_addr;
+ void __iomem *portal_virt_addr;
+ struct fsl_mc_device *dpmcp_dev;
+ union {
+ /*
+ * This field is only meaningful if the
+ * FSL_MC_IO_ATOMIC_CONTEXT_PORTAL flag is not set
+ */
+ struct mutex mutex; /* serializes mc_send_command() */
+
+ /*
+ * This field is only meaningful if the
+ * FSL_MC_IO_ATOMIC_CONTEXT_PORTAL flag is set
+ */
+ spinlock_t spinlock; /* serializes mc_send_command() */
+ };
+};
+
+int mc_send_command(struct fsl_mc_io *mc_io, struct mc_command *cmd);
+
+#ifdef CONFIG_FSL_MC_BUS
+#define dev_is_fsl_mc(_dev) ((_dev)->bus == &fsl_mc_bus_type)
+#else
+/* If fsl-mc bus is not present device cannot belong to fsl-mc bus */
+#define dev_is_fsl_mc(_dev) (0)
+#endif
+
/*
* module_fsl_mc_driver() - Helper macro for drivers that don't do
* anything special in module init/exit. This eliminates a lot of
@@ -194,8 +388,14 @@ int __must_check fsl_mc_object_allocate(struct fsl_mc_device *mc_dev,
void fsl_mc_object_free(struct fsl_mc_device *mc_adev);
+struct irq_domain *fsl_mc_msi_create_irq_domain(struct fwnode_handle *fwnode,
+ struct msi_domain_info *info,
+ struct irq_domain *parent);
+
int __must_check fsl_mc_allocate_irqs(struct fsl_mc_device *mc_dev);
void fsl_mc_free_irqs(struct fsl_mc_device *mc_dev);
+extern struct bus_type fsl_mc_bus_type;
+
#endif /* _FSL_MC_H_ */
diff --git a/drivers/staging/gdm724x/gdm_usb.c b/drivers/staging/gdm724x/gdm_usb.c
index 15a7e81ec2d2..87cd1f827455 100644
--- a/drivers/staging/gdm724x/gdm_usb.c
+++ b/drivers/staging/gdm724x/gdm_usb.c
@@ -738,11 +738,11 @@ static int gdm_usb_sdu_send(void *priv_dev, void *data, int len,
sdu->cmd_evt = gdm_cpu_to_dev16(&udev->gdm_ed, LTE_TX_SDU);
if (nic_type == NIC_TYPE_ARP) {
send_len = len + SDU_PARAM_LEN;
- memcpy(sdu->data, data, len);
+ memcpy(sdu->data, data, len);
} else {
- send_len = len - ETH_HLEN;
- send_len += SDU_PARAM_LEN;
- memcpy(sdu->data, data + ETH_HLEN, len - ETH_HLEN);
+ send_len = len - ETH_HLEN;
+ send_len += SDU_PARAM_LEN;
+ memcpy(sdu->data, data + ETH_HLEN, len - ETH_HLEN);
}
sdu->len = gdm_cpu_to_dev16(&udev->gdm_ed, send_len);
diff --git a/drivers/staging/greybus/Kconfig b/drivers/staging/greybus/Kconfig
index 50de2d72dde0..ab096bcef98c 100644
--- a/drivers/staging/greybus/Kconfig
+++ b/drivers/staging/greybus/Kconfig
@@ -216,4 +216,14 @@ config GREYBUS_USB
will be called gb-usb.ko
endif # GREYBUS_BRIDGED_PHY
+
+config GREYBUS_ARCHE
+ tristate "Greybus Arche Platform driver"
+ depends on USB_HSIC_USB3613 || COMPILE_TEST
+ ---help---
+ Select this option if you have an Arche device.
+
+ To compile this code as a module, chose M here: the module
+ will be called gb-arche.ko
+
endif # GREYBUS
diff --git a/drivers/staging/greybus/Makefile b/drivers/staging/greybus/Makefile
index b26b9a35bdd5..23e1cb7bff8e 100644
--- a/drivers/staging/greybus/Makefile
+++ b/drivers/staging/greybus/Makefile
@@ -91,4 +91,4 @@ obj-$(CONFIG_GREYBUS_USB) += gb-usb.o
# Greybus Platform driver
gb-arche-y := arche-platform.o arche-apb-ctrl.o
-obj-$(CONFIG_USB_HSIC_USB3613) += gb-arche.o
+obj-$(CONFIG_GREYBUS_ARCHE) += gb-arche.o
diff --git a/drivers/staging/greybus/arche-apb-ctrl.c b/drivers/staging/greybus/arche-apb-ctrl.c
index 02243b4fd898..0412f3d06efb 100644
--- a/drivers/staging/greybus/arche-apb-ctrl.c
+++ b/drivers/staging/greybus/arche-apb-ctrl.c
@@ -22,6 +22,8 @@
#include "arche_platform.h"
+static void apb_bootret_deassert(struct device *dev);
+
struct arche_apb_ctrl_drvdata {
/* Control GPIO signals to and from AP <=> AP Bridges */
int resetn_gpio;
@@ -222,14 +224,7 @@ static void poweroff_seq(struct platform_device *pdev)
/* TODO: May have to send an event to SVC about this exit */
}
-void apb_bootret_assert(struct device *dev)
-{
- struct arche_apb_ctrl_drvdata *apb = dev_get_drvdata(dev);
-
- gpio_set_value(apb->boot_ret_gpio, 1);
-}
-
-void apb_bootret_deassert(struct device *dev)
+static void apb_bootret_deassert(struct device *dev)
{
struct arche_apb_ctrl_drvdata *apb = dev_get_drvdata(dev);
diff --git a/drivers/staging/greybus/arche-platform.c b/drivers/staging/greybus/arche-platform.c
index aac1145f1983..eced2d26467b 100644
--- a/drivers/staging/greybus/arche-platform.c
+++ b/drivers/staging/greybus/arche-platform.c
@@ -24,7 +24,14 @@
#include "arche_platform.h"
#include "greybus.h"
+#if IS_ENABLED(CONFIG_USB_HSIC_USB3613)
#include <linux/usb/usb3613.h>
+#else
+static inline int usb3613_hub_mode_ctrl(bool unused)
+{
+ return 0;
+}
+#endif
#define WD_COLDBOOT_PULSE_WIDTH_MS 30
@@ -35,7 +42,6 @@ enum svc_wakedetect_state {
WD_STATE_STANDBYBOOT_TRIG, /* As of now not used ?? */
WD_STATE_COLDBOOT_START, /* Cold boot process started */
WD_STATE_STANDBYBOOT_START, /* Not used */
- WD_STATE_TIMESYNC,
};
struct arche_platform_drvdata {
@@ -59,26 +65,12 @@ struct arche_platform_drvdata {
int wake_detect_irq;
spinlock_t wake_lock; /* Protect wake_detect_state */
struct mutex platform_state_mutex; /* Protect state */
- wait_queue_head_t wq; /* WQ for arche_pdata->state */
unsigned long wake_detect_start;
struct notifier_block pm_notifier;
struct device *dev;
- struct gb_timesync_svc *timesync_svc_pdata;
};
-static int arche_apb_bootret_assert(struct device *dev, void *data)
-{
- apb_bootret_assert(dev);
- return 0;
-}
-
-static int arche_apb_bootret_deassert(struct device *dev, void *data)
-{
- apb_bootret_deassert(dev);
- return 0;
-}
-
/* Requires calling context to hold arche_pdata->platform_state_mutex */
static void arche_platform_set_state(struct arche_platform_drvdata *arche_pdata,
enum arche_platform_state state)
@@ -86,112 +78,6 @@ static void arche_platform_set_state(struct arche_platform_drvdata *arche_pdata,
arche_pdata->state = state;
}
-/*
- * arche_platform_change_state: Change the operational state
- *
- * This exported function allows external drivers to change the state
- * of the arche-platform driver.
- * Note that this function only supports transitions between two states
- * with limited functionality.
- *
- * - ARCHE_PLATFORM_STATE_TIME_SYNC:
- * Once set, allows timesync operations between SVC <=> AP and makes
- * sure that arche-platform driver ignores any subsequent events/pulses
- * from SVC over wake/detect.
- *
- * - ARCHE_PLATFORM_STATE_ACTIVE:
- * Puts back driver to active state, where any pulse from SVC on wake/detect
- * line would trigger either cold/standby boot.
- * Note: Transition request from this function does not trigger cold/standby
- * boot. It just puts back driver book keeping variable back to ACTIVE
- * state and restores the interrupt.
- *
- * Returns -ENODEV if device not found, -EAGAIN if the driver cannot currently
- * satisfy the requested state-transition or -EINVAL for all other
- * state-transition requests.
- */
-int arche_platform_change_state(enum arche_platform_state state,
- struct gb_timesync_svc *timesync_svc_pdata)
-{
- struct arche_platform_drvdata *arche_pdata;
- struct platform_device *pdev;
- struct device_node *np;
- int ret = -EAGAIN;
- unsigned long flags;
-
- np = of_find_compatible_node(NULL, NULL, "google,arche-platform");
- if (!np) {
- pr_err("google,arche-platform device node not found\n");
- return -ENODEV;
- }
-
- pdev = of_find_device_by_node(np);
- if (!pdev) {
- pr_err("arche-platform device not found\n");
- of_node_put(np);
- return -ENODEV;
- }
-
- arche_pdata = platform_get_drvdata(pdev);
-
- mutex_lock(&arche_pdata->platform_state_mutex);
- spin_lock_irqsave(&arche_pdata->wake_lock, flags);
-
- if (arche_pdata->state == state) {
- ret = 0;
- goto exit;
- }
-
- switch (state) {
- case ARCHE_PLATFORM_STATE_TIME_SYNC:
- if (arche_pdata->state != ARCHE_PLATFORM_STATE_ACTIVE) {
- ret = -EINVAL;
- goto exit;
- }
- if (arche_pdata->wake_detect_state != WD_STATE_IDLE) {
- dev_err(arche_pdata->dev,
- "driver busy with wake/detect line ops\n");
- goto exit;
- }
- device_for_each_child(arche_pdata->dev, NULL,
- arche_apb_bootret_assert);
- arche_pdata->wake_detect_state = WD_STATE_TIMESYNC;
- break;
- case ARCHE_PLATFORM_STATE_ACTIVE:
- if (arche_pdata->state != ARCHE_PLATFORM_STATE_TIME_SYNC) {
- ret = -EINVAL;
- goto exit;
- }
- device_for_each_child(arche_pdata->dev, NULL,
- arche_apb_bootret_deassert);
- arche_pdata->wake_detect_state = WD_STATE_IDLE;
- break;
- case ARCHE_PLATFORM_STATE_OFF:
- case ARCHE_PLATFORM_STATE_STANDBY:
- case ARCHE_PLATFORM_STATE_FW_FLASHING:
- dev_err(arche_pdata->dev, "busy, request to retry later\n");
- goto exit;
- default:
- ret = -EINVAL;
- dev_err(arche_pdata->dev,
- "invalid state transition request\n");
- goto exit;
- }
- arche_pdata->timesync_svc_pdata = timesync_svc_pdata;
- arche_platform_set_state(arche_pdata, state);
- if (state == ARCHE_PLATFORM_STATE_ACTIVE)
- wake_up(&arche_pdata->wq);
-
- ret = 0;
-exit:
- spin_unlock_irqrestore(&arche_pdata->wake_lock, flags);
- mutex_unlock(&arche_pdata->platform_state_mutex);
- put_device(&pdev->dev);
- of_node_put(np);
- return ret;
-}
-EXPORT_SYMBOL_GPL(arche_platform_change_state);
-
/* Requires arche_pdata->wake_lock is held by calling context */
static void arche_platform_set_wake_detect_state(
struct arche_platform_drvdata *arche_pdata,
@@ -275,11 +161,6 @@ static irqreturn_t arche_platform_wd_irq(int irq, void *devid)
spin_lock_irqsave(&arche_pdata->wake_lock, flags);
- if (arche_pdata->wake_detect_state == WD_STATE_TIMESYNC) {
- gb_timesync_irq(arche_pdata->timesync_svc_pdata);
- goto exit;
- }
-
if (gpio_get_value(arche_pdata->wake_detect_gpio)) {
/* wake/detect rising */
@@ -323,7 +204,6 @@ static irqreturn_t arche_platform_wd_irq(int irq, void *devid)
}
}
-exit:
spin_unlock_irqrestore(&arche_pdata->wake_lock, flags);
return IRQ_HANDLED;
@@ -436,17 +316,7 @@ static ssize_t state_store(struct device *dev,
struct arche_platform_drvdata *arche_pdata = platform_get_drvdata(pdev);
int ret = 0;
-retry:
mutex_lock(&arche_pdata->platform_state_mutex);
- if (arche_pdata->state == ARCHE_PLATFORM_STATE_TIME_SYNC) {
- mutex_unlock(&arche_pdata->platform_state_mutex);
- ret = wait_event_interruptible(
- arche_pdata->wq,
- arche_pdata->state != ARCHE_PLATFORM_STATE_TIME_SYNC);
- if (ret)
- return ret;
- goto retry;
- }
if (sysfs_streq(buf, "off")) {
if (arche_pdata->state == ARCHE_PLATFORM_STATE_OFF)
@@ -517,8 +387,6 @@ static ssize_t state_show(struct device *dev,
return sprintf(buf, "standby\n");
case ARCHE_PLATFORM_STATE_FW_FLASHING:
return sprintf(buf, "fw_flashing\n");
- case ARCHE_PLATFORM_STATE_TIME_SYNC:
- return sprintf(buf, "time_sync\n");
default:
return sprintf(buf, "unknown state\n");
}
@@ -665,7 +533,6 @@ static int arche_platform_probe(struct platform_device *pdev)
spin_lock_init(&arche_pdata->wake_lock);
mutex_init(&arche_pdata->platform_state_mutex);
- init_waitqueue_head(&arche_pdata->wq);
arche_pdata->wake_detect_irq =
gpio_to_irq(arche_pdata->wake_detect_gpio);
@@ -701,9 +568,6 @@ static int arche_platform_probe(struct platform_device *pdev)
goto err_device_remove;
}
- /* Register callback pointer */
- arche_platform_change_state_cb = arche_platform_change_state;
-
/* Explicitly power off if requested */
if (!of_property_read_bool(pdev->dev.of_node, "arche,init-off")) {
mutex_lock(&arche_pdata->platform_state_mutex);
@@ -751,7 +615,7 @@ static int arche_platform_remove(struct platform_device *pdev)
return 0;
}
-static int arche_platform_suspend(struct device *dev)
+static __maybe_unused int arche_platform_suspend(struct device *dev)
{
/*
* If timing profile premits, we may shutdown bridge
@@ -765,7 +629,7 @@ static int arche_platform_suspend(struct device *dev)
return 0;
}
-static int arche_platform_resume(struct device *dev)
+static __maybe_unused int arche_platform_resume(struct device *dev)
{
/*
* Atleast for ES2 we have to meet the delay requirement between
diff --git a/drivers/staging/greybus/arche_platform.h b/drivers/staging/greybus/arche_platform.h
index c0591df9b9d6..bcffc69d0960 100644
--- a/drivers/staging/greybus/arche_platform.h
+++ b/drivers/staging/greybus/arche_platform.h
@@ -15,14 +15,8 @@ enum arche_platform_state {
ARCHE_PLATFORM_STATE_ACTIVE,
ARCHE_PLATFORM_STATE_STANDBY,
ARCHE_PLATFORM_STATE_FW_FLASHING,
- ARCHE_PLATFORM_STATE_TIME_SYNC,
};
-int arche_platform_change_state(enum arche_platform_state state,
- struct gb_timesync_svc *pdata);
-
-extern int (*arche_platform_change_state_cb)(enum arche_platform_state state,
- struct gb_timesync_svc *pdata);
int __init arche_apb_init(void);
void __exit arche_apb_exit(void);
@@ -31,7 +25,5 @@ int apb_ctrl_coldboot(struct device *dev);
int apb_ctrl_fw_flashing(struct device *dev);
int apb_ctrl_standby_boot(struct device *dev);
void apb_ctrl_poweroff(struct device *dev);
-void apb_bootret_assert(struct device *dev);
-void apb_bootret_deassert(struct device *dev);
#endif /* __ARCHE_PLATFORM_H */
diff --git a/drivers/staging/greybus/light.c b/drivers/staging/greybus/light.c
index 16813628eda1..861a249e6ef1 100644
--- a/drivers/staging/greybus/light.c
+++ b/drivers/staging/greybus/light.c
@@ -1030,7 +1030,7 @@ static int gb_lights_light_config(struct gb_lights *glights, u8 id)
light->channels_count = conf.channel_count;
light->name = kstrndup(conf.name, NAMES_MAX, GFP_KERNEL);
- light->channels = kzalloc(light->channels_count *
+ light->channels = kcalloc(light->channels_count,
sizeof(struct gb_channel), GFP_KERNEL);
if (!light->channels)
return -ENOMEM;
@@ -1167,7 +1167,7 @@ static int gb_lights_create_all(struct gb_lights *glights)
if (ret < 0)
goto out;
- glights->lights = kzalloc(glights->lights_count *
+ glights->lights = kcalloc(glights->lights_count,
sizeof(struct gb_light), GFP_KERNEL);
if (!glights->lights) {
ret = -ENOMEM;
diff --git a/drivers/staging/greybus/power_supply.c b/drivers/staging/greybus/power_supply.c
index e85c988b7034..20cac20518d7 100644
--- a/drivers/staging/greybus/power_supply.c
+++ b/drivers/staging/greybus/power_supply.c
@@ -944,7 +944,7 @@ static int gb_power_supplies_setup(struct gb_power_supplies *supplies)
if (ret < 0)
goto out;
- supplies->supply = kzalloc(supplies->supplies_count *
+ supplies->supply = kcalloc(supplies->supplies_count,
sizeof(struct gb_power_supply),
GFP_KERNEL);
diff --git a/drivers/staging/iio/cdc/ad7152.c b/drivers/staging/iio/cdc/ad7152.c
index dc6ecd824365..ff10d1f0a7e4 100644
--- a/drivers/staging/iio/cdc/ad7152.c
+++ b/drivers/staging/iio/cdc/ad7152.c
@@ -231,16 +231,12 @@ static int ad7152_write_raw_samp_freq(struct device *dev, int val)
if (i >= ARRAY_SIZE(ad7152_filter_rate_table))
i = ARRAY_SIZE(ad7152_filter_rate_table) - 1;
- mutex_lock(&chip->state_lock);
ret = i2c_smbus_write_byte_data(chip->client,
AD7152_REG_CFG2, AD7152_CFG2_OSR(i));
- if (ret < 0) {
- mutex_unlock(&chip->state_lock);
+ if (ret < 0)
return ret;
- }
chip->filter_rate_setup = i;
- mutex_unlock(&chip->state_lock);
return ret;
}
diff --git a/drivers/staging/iio/frequency/ad9834.c b/drivers/staging/iio/frequency/ad9834.c
index af108e96b3ec..995acdd7c942 100644
--- a/drivers/staging/iio/frequency/ad9834.c
+++ b/drivers/staging/iio/frequency/ad9834.c
@@ -292,7 +292,7 @@ ssize_t ad9834_show_out0_wavetype_available(struct device *dev,
return sprintf(buf, "%s\n", str);
}
-static IIO_DEVICE_ATTR(out_altvoltage0_out0_wavetype_available, S_IRUGO,
+static IIO_DEVICE_ATTR(out_altvoltage0_out0_wavetype_available, 0444,
ad9834_show_out0_wavetype_available, NULL, 0);
static
@@ -312,27 +312,27 @@ ssize_t ad9834_show_out1_wavetype_available(struct device *dev,
return sprintf(buf, "%s\n", str);
}
-static IIO_DEVICE_ATTR(out_altvoltage0_out1_wavetype_available, S_IRUGO,
+static IIO_DEVICE_ATTR(out_altvoltage0_out1_wavetype_available, 0444,
ad9834_show_out1_wavetype_available, NULL, 0);
/**
* see dds.h for further information
*/
-static IIO_DEV_ATTR_FREQ(0, 0, S_IWUSR, NULL, ad9834_write, AD9834_REG_FREQ0);
-static IIO_DEV_ATTR_FREQ(0, 1, S_IWUSR, NULL, ad9834_write, AD9834_REG_FREQ1);
-static IIO_DEV_ATTR_FREQSYMBOL(0, S_IWUSR, NULL, ad9834_write, AD9834_FSEL);
+static IIO_DEV_ATTR_FREQ(0, 0, 0200, NULL, ad9834_write, AD9834_REG_FREQ0);
+static IIO_DEV_ATTR_FREQ(0, 1, 0200, NULL, ad9834_write, AD9834_REG_FREQ1);
+static IIO_DEV_ATTR_FREQSYMBOL(0, 0200, NULL, ad9834_write, AD9834_FSEL);
static IIO_CONST_ATTR_FREQ_SCALE(0, "1"); /* 1Hz */
-static IIO_DEV_ATTR_PHASE(0, 0, S_IWUSR, NULL, ad9834_write, AD9834_REG_PHASE0);
-static IIO_DEV_ATTR_PHASE(0, 1, S_IWUSR, NULL, ad9834_write, AD9834_REG_PHASE1);
-static IIO_DEV_ATTR_PHASESYMBOL(0, S_IWUSR, NULL, ad9834_write, AD9834_PSEL);
+static IIO_DEV_ATTR_PHASE(0, 0, 0200, NULL, ad9834_write, AD9834_REG_PHASE0);
+static IIO_DEV_ATTR_PHASE(0, 1, 0200, NULL, ad9834_write, AD9834_REG_PHASE1);
+static IIO_DEV_ATTR_PHASESYMBOL(0, 0200, NULL, ad9834_write, AD9834_PSEL);
static IIO_CONST_ATTR_PHASE_SCALE(0, "0.0015339808"); /* 2PI/2^12 rad*/
-static IIO_DEV_ATTR_PINCONTROL_EN(0, S_IWUSR, NULL,
+static IIO_DEV_ATTR_PINCONTROL_EN(0, 0200, NULL,
ad9834_write, AD9834_PIN_SW);
-static IIO_DEV_ATTR_OUT_ENABLE(0, S_IWUSR, NULL, ad9834_write, AD9834_RESET);
-static IIO_DEV_ATTR_OUTY_ENABLE(0, 1, S_IWUSR, NULL,
+static IIO_DEV_ATTR_OUT_ENABLE(0, 0200, NULL, ad9834_write, AD9834_RESET);
+static IIO_DEV_ATTR_OUTY_ENABLE(0, 1, 0200, NULL,
ad9834_write, AD9834_OPBITEN);
static IIO_DEV_ATTR_OUT_WAVETYPE(0, 0, ad9834_store_wavetype, 0);
static IIO_DEV_ATTR_OUT_WAVETYPE(0, 1, ad9834_store_wavetype, 1);
diff --git a/drivers/staging/iio/frequency/dds.h b/drivers/staging/iio/frequency/dds.h
index fe53e7324c94..d6ccd99c14d7 100644
--- a/drivers/staging/iio/frequency/dds.h
+++ b/drivers/staging/iio/frequency/dds.h
@@ -101,7 +101,7 @@
#define IIO_DEV_ATTR_OUT_WAVETYPE(_channel, _output, _store, _addr) \
IIO_DEVICE_ATTR(out_altvoltage##_channel##_out##_output##_wavetype,\
- S_IWUSR, NULL, _store, _addr)
+ 0200, NULL, _store, _addr)
/**
* /sys/bus/iio/devices/.../out_altvoltageX_outY_wavetype_available
diff --git a/drivers/staging/iio/light/Kconfig b/drivers/staging/iio/light/Kconfig
index 4fbf6298c0f3..aacb0ae58c0e 100644
--- a/drivers/staging/iio/light/Kconfig
+++ b/drivers/staging/iio/light/Kconfig
@@ -3,16 +3,6 @@
#
menu "Light sensors"
-config SENSORS_ISL29028
- tristate "Intersil ISL29028 Concurrent Light and Proximity Sensor"
- depends on I2C
- select REGMAP_I2C
- help
- Provides driver for the Intersil's ISL29028 device.
- This driver supports the sysfs interface to get the ALS, IR intensity,
- Proximity value via iio. The ISL29028 provides the concurrent sensing
- of ambient light and proximity.
-
config TSL2x7x
tristate "TAOS TSL/TMD2x71 and TSL/TMD2x72 Family of light and proximity sensors"
depends on I2C
diff --git a/drivers/staging/iio/light/Makefile b/drivers/staging/iio/light/Makefile
index f8693e9fdc94..ab8dc3a3d10b 100644
--- a/drivers/staging/iio/light/Makefile
+++ b/drivers/staging/iio/light/Makefile
@@ -2,5 +2,4 @@
# Makefile for industrial I/O Light sensors
#
-obj-$(CONFIG_SENSORS_ISL29028) += isl29028.o
-obj-$(CONFIG_TSL2x7x) += tsl2x7x_core.o
+obj-$(CONFIG_TSL2x7x) += tsl2x7x.o
diff --git a/drivers/staging/iio/light/tsl2x7x_core.c b/drivers/staging/iio/light/tsl2x7x.c
index af3910bc1b4f..146719928fb3 100644
--- a/drivers/staging/iio/light/tsl2x7x_core.c
+++ b/drivers/staging/iio/light/tsl2x7x.c
@@ -13,10 +13,6 @@
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#include <linux/kernel.h>
@@ -919,7 +915,7 @@ static void tsl2x7x_prox_cal(struct iio_dev *indio_dev)
tsl2x7x_chip_on(indio_dev);
}
-static ssize_t tsl2x7x_power_state_show(struct device *dev,
+static ssize_t power_state_show(struct device *dev,
struct device_attribute *attr,
char *buf)
{
@@ -928,7 +924,7 @@ static ssize_t tsl2x7x_power_state_show(struct device *dev,
return snprintf(buf, PAGE_SIZE, "%d\n", chip->tsl2x7x_chip_status);
}
-static ssize_t tsl2x7x_power_state_store(struct device *dev,
+static ssize_t power_state_store(struct device *dev,
struct device_attribute *attr,
const char *buf, size_t len)
{
@@ -946,7 +942,7 @@ static ssize_t tsl2x7x_power_state_store(struct device *dev,
return len;
}
-static ssize_t tsl2x7x_gain_available_show(struct device *dev,
+static ssize_t in_illuminance0_calibscale_available_show(struct device *dev,
struct device_attribute *attr,
char *buf)
{
@@ -964,14 +960,14 @@ static ssize_t tsl2x7x_gain_available_show(struct device *dev,
return snprintf(buf, PAGE_SIZE, "%s\n", "1 8 16 120");
}
-static ssize_t tsl2x7x_prox_gain_available_show(struct device *dev,
+static ssize_t in_proximity0_calibscale_available_show(struct device *dev,
struct device_attribute *attr,
char *buf)
{
return snprintf(buf, PAGE_SIZE, "%s\n", "1 2 4 8");
}
-static ssize_t tsl2x7x_als_time_show(struct device *dev,
+static ssize_t in_illuminance0_integration_time_show(struct device *dev,
struct device_attribute *attr,
char *buf)
{
@@ -986,7 +982,7 @@ static ssize_t tsl2x7x_als_time_show(struct device *dev,
return snprintf(buf, PAGE_SIZE, "%d.%03d\n", y, z);
}
-static ssize_t tsl2x7x_als_time_store(struct device *dev,
+static ssize_t in_illuminance0_integration_time_store(struct device *dev,
struct device_attribute *attr,
const char *buf, size_t len)
{
@@ -1014,7 +1010,7 @@ static ssize_t tsl2x7x_als_time_store(struct device *dev,
static IIO_CONST_ATTR(in_illuminance0_integration_time_available,
".00272 - .696");
-static ssize_t tsl2x7x_als_cal_target_show(struct device *dev,
+static ssize_t in_illuminance0_target_input_show(struct device *dev,
struct device_attribute *attr,
char *buf)
{
@@ -1024,7 +1020,7 @@ static ssize_t tsl2x7x_als_cal_target_show(struct device *dev,
chip->tsl2x7x_settings.als_cal_target);
}
-static ssize_t tsl2x7x_als_cal_target_store(struct device *dev,
+static ssize_t in_illuminance0_target_input_store(struct device *dev,
struct device_attribute *attr,
const char *buf, size_t len)
{
@@ -1044,7 +1040,7 @@ static ssize_t tsl2x7x_als_cal_target_store(struct device *dev,
}
/* persistence settings */
-static ssize_t tsl2x7x_als_persistence_show(struct device *dev,
+static ssize_t in_intensity0_thresh_period_show(struct device *dev,
struct device_attribute *attr,
char *buf)
{
@@ -1061,7 +1057,7 @@ static ssize_t tsl2x7x_als_persistence_show(struct device *dev,
return snprintf(buf, PAGE_SIZE, "%d.%03d\n", y, z);
}
-static ssize_t tsl2x7x_als_persistence_store(struct device *dev,
+static ssize_t in_intensity0_thresh_period_store(struct device *dev,
struct device_attribute *attr,
const char *buf, size_t len)
{
@@ -1092,7 +1088,7 @@ static ssize_t tsl2x7x_als_persistence_store(struct device *dev,
return IIO_VAL_INT_PLUS_MICRO;
}
-static ssize_t tsl2x7x_prox_persistence_show(struct device *dev,
+static ssize_t in_proximity0_thresh_period_show(struct device *dev,
struct device_attribute *attr,
char *buf)
{
@@ -1109,7 +1105,7 @@ static ssize_t tsl2x7x_prox_persistence_show(struct device *dev,
return snprintf(buf, PAGE_SIZE, "%d.%03d\n", y, z);
}
-static ssize_t tsl2x7x_prox_persistence_store(struct device *dev,
+static ssize_t in_proximity0_thresh_period_store(struct device *dev,
struct device_attribute *attr,
const char *buf, size_t len)
{
@@ -1140,7 +1136,7 @@ static ssize_t tsl2x7x_prox_persistence_store(struct device *dev,
return IIO_VAL_INT_PLUS_MICRO;
}
-static ssize_t tsl2x7x_do_calibrate(struct device *dev,
+static ssize_t in_illuminance0_calibrate_store(struct device *dev,
struct device_attribute *attr,
const char *buf, size_t len)
{
@@ -1158,7 +1154,7 @@ static ssize_t tsl2x7x_do_calibrate(struct device *dev,
return len;
}
-static ssize_t tsl2x7x_luxtable_show(struct device *dev,
+static ssize_t in_illuminance0_lux_table_show(struct device *dev,
struct device_attribute *attr,
char *buf)
{
@@ -1186,7 +1182,7 @@ static ssize_t tsl2x7x_luxtable_show(struct device *dev,
return offset;
}
-static ssize_t tsl2x7x_luxtable_store(struct device *dev,
+static ssize_t in_illuminance0_lux_table_store(struct device *dev,
struct device_attribute *attr,
const char *buf, size_t len)
{
@@ -1226,7 +1222,7 @@ static ssize_t tsl2x7x_luxtable_store(struct device *dev,
return len;
}
-static ssize_t tsl2x7x_do_prox_calibrate(struct device *dev,
+static ssize_t in_proximity0_calibrate_store(struct device *dev,
struct device_attribute *attr,
const char *buf, size_t len)
{
@@ -1498,35 +1494,25 @@ static int tsl2x7x_write_raw(struct iio_dev *indio_dev,
return 0;
}
-static DEVICE_ATTR(power_state, S_IRUGO | S_IWUSR,
- tsl2x7x_power_state_show, tsl2x7x_power_state_store);
+static DEVICE_ATTR_RW(power_state);
-static DEVICE_ATTR(in_proximity0_calibscale_available, S_IRUGO,
- tsl2x7x_prox_gain_available_show, NULL);
+static DEVICE_ATTR_RO(in_proximity0_calibscale_available);
-static DEVICE_ATTR(in_illuminance0_calibscale_available, S_IRUGO,
- tsl2x7x_gain_available_show, NULL);
+static DEVICE_ATTR_RO(in_illuminance0_calibscale_available);
-static DEVICE_ATTR(in_illuminance0_integration_time, S_IRUGO | S_IWUSR,
- tsl2x7x_als_time_show, tsl2x7x_als_time_store);
+static DEVICE_ATTR_RW(in_illuminance0_integration_time);
-static DEVICE_ATTR(in_illuminance0_target_input, S_IRUGO | S_IWUSR,
- tsl2x7x_als_cal_target_show, tsl2x7x_als_cal_target_store);
+static DEVICE_ATTR_RW(in_illuminance0_target_input);
-static DEVICE_ATTR(in_illuminance0_calibrate, S_IWUSR, NULL,
- tsl2x7x_do_calibrate);
+static DEVICE_ATTR_WO(in_illuminance0_calibrate);
-static DEVICE_ATTR(in_proximity0_calibrate, S_IWUSR, NULL,
- tsl2x7x_do_prox_calibrate);
+static DEVICE_ATTR_WO(in_proximity0_calibrate);
-static DEVICE_ATTR(in_illuminance0_lux_table, S_IRUGO | S_IWUSR,
- tsl2x7x_luxtable_show, tsl2x7x_luxtable_store);
+static DEVICE_ATTR_RW(in_illuminance0_lux_table);
-static DEVICE_ATTR(in_intensity0_thresh_period, S_IRUGO | S_IWUSR,
- tsl2x7x_als_persistence_show, tsl2x7x_als_persistence_store);
+static DEVICE_ATTR_RW(in_intensity0_thresh_period);
-static DEVICE_ATTR(in_proximity0_thresh_period, S_IRUGO | S_IWUSR,
- tsl2x7x_prox_persistence_show, tsl2x7x_prox_persistence_store);
+static DEVICE_ATTR_RW(in_proximity0_thresh_period);
/* Use the default register values to identify the Taos device */
static int tsl2x7x_device_id(unsigned char *id, int target)
diff --git a/drivers/staging/iio/meter/ade7753.c b/drivers/staging/iio/meter/ade7753.c
index b71fbd313778..ce26abdeab92 100644
--- a/drivers/staging/iio/meter/ade7753.c
+++ b/drivers/staging/iio/meter/ade7753.c
@@ -107,9 +107,8 @@ static int ade7753_spi_write_reg_8(struct device *dev,
return ret;
}
-static int ade7753_spi_write_reg_16(struct device *dev,
- u8 reg_address,
- u16 value)
+static int ade7753_spi_write_reg_16(struct device *dev, u8 reg_address,
+ u16 value)
{
int ret;
struct iio_dev *indio_dev = dev_to_iio_dev(dev);
@@ -126,8 +125,8 @@ static int ade7753_spi_write_reg_16(struct device *dev,
}
static int ade7753_spi_read_reg_8(struct device *dev,
- u8 reg_address,
- u8 *val)
+ u8 reg_address,
+ u8 *val)
{
struct iio_dev *indio_dev = dev_to_iio_dev(dev);
struct ade7753_state *st = iio_priv(indio_dev);
@@ -136,7 +135,7 @@ static int ade7753_spi_read_reg_8(struct device *dev,
ret = spi_w8r8(st->us, ADE7753_READ_REG(reg_address));
if (ret < 0) {
dev_err(&st->us->dev, "problem when reading 8 bit register 0x%02X",
- reg_address);
+ reg_address);
return ret;
}
*val = ret;
@@ -145,8 +144,8 @@ static int ade7753_spi_read_reg_8(struct device *dev,
}
static int ade7753_spi_read_reg_16(struct device *dev,
- u8 reg_address,
- u16 *val)
+ u8 reg_address,
+ u16 *val)
{
struct iio_dev *indio_dev = dev_to_iio_dev(dev);
struct ade7753_state *st = iio_priv(indio_dev);
@@ -165,8 +164,8 @@ static int ade7753_spi_read_reg_16(struct device *dev,
}
static int ade7753_spi_read_reg_24(struct device *dev,
- u8 reg_address,
- u32 *val)
+ u8 reg_address,
+ u32 *val)
{
struct iio_dev *indio_dev = dev_to_iio_dev(dev);
struct ade7753_state *st = iio_priv(indio_dev);
@@ -189,7 +188,7 @@ static int ade7753_spi_read_reg_24(struct device *dev,
ret = spi_sync_transfer(st->us, xfers, ARRAY_SIZE(xfers));
if (ret) {
dev_err(&st->us->dev, "problem when reading 24 bit register 0x%02X",
- reg_address);
+ reg_address);
goto error_ret;
}
*val = (st->rx[0] << 16) | (st->rx[1] << 8) | st->rx[2];
@@ -200,8 +199,8 @@ error_ret:
}
static ssize_t ade7753_read_8bit(struct device *dev,
- struct device_attribute *attr,
- char *buf)
+ struct device_attribute *attr,
+ char *buf)
{
int ret;
u8 val;
@@ -215,8 +214,8 @@ static ssize_t ade7753_read_8bit(struct device *dev,
}
static ssize_t ade7753_read_16bit(struct device *dev,
- struct device_attribute *attr,
- char *buf)
+ struct device_attribute *attr,
+ char *buf)
{
int ret;
u16 val;
@@ -230,8 +229,8 @@ static ssize_t ade7753_read_16bit(struct device *dev,
}
static ssize_t ade7753_read_24bit(struct device *dev,
- struct device_attribute *attr,
- char *buf)
+ struct device_attribute *attr,
+ char *buf)
{
int ret;
u32 val;
@@ -245,9 +244,9 @@ static ssize_t ade7753_read_24bit(struct device *dev,
}
static ssize_t ade7753_write_8bit(struct device *dev,
- struct device_attribute *attr,
- const char *buf,
- size_t len)
+ struct device_attribute *attr,
+ const char *buf,
+ size_t len)
{
struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
int ret;
@@ -263,9 +262,9 @@ error_ret:
}
static ssize_t ade7753_write_16bit(struct device *dev,
- struct device_attribute *attr,
- const char *buf,
- size_t len)
+ struct device_attribute *attr,
+ const char *buf,
+ size_t len)
{
struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
int ret;
@@ -298,92 +297,92 @@ static IIO_DEV_ATTR_AENERGY(ade7753_read_24bit, ADE7753_AENERGY);
static IIO_DEV_ATTR_LAENERGY(ade7753_read_24bit, ADE7753_LAENERGY);
static IIO_DEV_ATTR_VAENERGY(ade7753_read_24bit, ADE7753_VAENERGY);
static IIO_DEV_ATTR_LVAENERGY(ade7753_read_24bit, ADE7753_LVAENERGY);
-static IIO_DEV_ATTR_CFDEN(S_IWUSR | S_IRUGO,
+static IIO_DEV_ATTR_CFDEN(0644,
ade7753_read_16bit,
ade7753_write_16bit,
ADE7753_CFDEN);
-static IIO_DEV_ATTR_CFNUM(S_IWUSR | S_IRUGO,
+static IIO_DEV_ATTR_CFNUM(0644,
ade7753_read_8bit,
ade7753_write_8bit,
ADE7753_CFNUM);
static IIO_DEV_ATTR_CHKSUM(ade7753_read_8bit, ADE7753_CHKSUM);
-static IIO_DEV_ATTR_PHCAL(S_IWUSR | S_IRUGO,
+static IIO_DEV_ATTR_PHCAL(0644,
ade7753_read_16bit,
ade7753_write_16bit,
ADE7753_PHCAL);
-static IIO_DEV_ATTR_APOS(S_IWUSR | S_IRUGO,
+static IIO_DEV_ATTR_APOS(0644,
ade7753_read_16bit,
ade7753_write_16bit,
ADE7753_APOS);
-static IIO_DEV_ATTR_SAGCYC(S_IWUSR | S_IRUGO,
+static IIO_DEV_ATTR_SAGCYC(0644,
ade7753_read_8bit,
ade7753_write_8bit,
ADE7753_SAGCYC);
-static IIO_DEV_ATTR_SAGLVL(S_IWUSR | S_IRUGO,
+static IIO_DEV_ATTR_SAGLVL(0644,
ade7753_read_8bit,
ade7753_write_8bit,
ADE7753_SAGLVL);
-static IIO_DEV_ATTR_LINECYC(S_IWUSR | S_IRUGO,
+static IIO_DEV_ATTR_LINECYC(0644,
ade7753_read_8bit,
ade7753_write_8bit,
ADE7753_LINECYC);
-static IIO_DEV_ATTR_WDIV(S_IWUSR | S_IRUGO,
+static IIO_DEV_ATTR_WDIV(0644,
ade7753_read_8bit,
ade7753_write_8bit,
ADE7753_WDIV);
-static IIO_DEV_ATTR_IRMS(S_IWUSR | S_IRUGO,
+static IIO_DEV_ATTR_IRMS(0644,
ade7753_read_24bit,
NULL,
ADE7753_IRMS);
-static IIO_DEV_ATTR_VRMS(S_IRUGO,
+static IIO_DEV_ATTR_VRMS(0444,
ade7753_read_24bit,
NULL,
ADE7753_VRMS);
-static IIO_DEV_ATTR_IRMSOS(S_IWUSR | S_IRUGO,
+static IIO_DEV_ATTR_IRMSOS(0644,
ade7753_read_16bit,
ade7753_write_16bit,
ADE7753_IRMSOS);
-static IIO_DEV_ATTR_VRMSOS(S_IWUSR | S_IRUGO,
+static IIO_DEV_ATTR_VRMSOS(0644,
ade7753_read_16bit,
ade7753_write_16bit,
ADE7753_VRMSOS);
-static IIO_DEV_ATTR_WGAIN(S_IWUSR | S_IRUGO,
+static IIO_DEV_ATTR_WGAIN(0644,
ade7753_read_16bit,
ade7753_write_16bit,
ADE7753_WGAIN);
-static IIO_DEV_ATTR_VAGAIN(S_IWUSR | S_IRUGO,
+static IIO_DEV_ATTR_VAGAIN(0644,
ade7753_read_16bit,
ade7753_write_16bit,
ADE7753_VAGAIN);
-static IIO_DEV_ATTR_PGA_GAIN(S_IWUSR | S_IRUGO,
+static IIO_DEV_ATTR_PGA_GAIN(0644,
ade7753_read_16bit,
ade7753_write_16bit,
ADE7753_GAIN);
-static IIO_DEV_ATTR_IPKLVL(S_IWUSR | S_IRUGO,
+static IIO_DEV_ATTR_IPKLVL(0644,
ade7753_read_8bit,
ade7753_write_8bit,
ADE7753_IPKLVL);
-static IIO_DEV_ATTR_VPKLVL(S_IWUSR | S_IRUGO,
+static IIO_DEV_ATTR_VPKLVL(0644,
ade7753_read_8bit,
ade7753_write_8bit,
ADE7753_VPKLVL);
-static IIO_DEV_ATTR_IPEAK(S_IRUGO,
+static IIO_DEV_ATTR_IPEAK(0444,
ade7753_read_24bit,
NULL,
ADE7753_IPEAK);
-static IIO_DEV_ATTR_VPEAK(S_IRUGO,
+static IIO_DEV_ATTR_VPEAK(0444,
ade7753_read_24bit,
NULL,
ADE7753_VPEAK);
-static IIO_DEV_ATTR_VPERIOD(S_IRUGO,
+static IIO_DEV_ATTR_VPERIOD(0444,
ade7753_read_16bit,
NULL,
ADE7753_PERIOD);
-static IIO_DEV_ATTR_CH_OFF(1, S_IWUSR | S_IRUGO,
+static IIO_DEV_ATTR_CH_OFF(1, 0644,
ade7753_read_8bit,
ade7753_write_8bit,
ADE7753_CH1OS);
-static IIO_DEV_ATTR_CH_OFF(2, S_IWUSR | S_IRUGO,
+static IIO_DEV_ATTR_CH_OFF(2, 0644,
ade7753_read_8bit,
ade7753_write_8bit,
ADE7753_CH2OS);
@@ -450,8 +449,8 @@ err_ret:
}
static ssize_t ade7753_read_frequency(struct device *dev,
- struct device_attribute *attr,
- char *buf)
+ struct device_attribute *attr,
+ char *buf)
{
int ret;
u16 t;
@@ -468,9 +467,9 @@ static ssize_t ade7753_read_frequency(struct device *dev,
}
static ssize_t ade7753_write_frequency(struct device *dev,
- struct device_attribute *attr,
- const char *buf,
- size_t len)
+ struct device_attribute *attr,
+ const char *buf,
+ size_t len)
{
struct iio_dev *indio_dev = dev_to_iio_dev(dev);
struct ade7753_state *st = iio_priv(indio_dev);
@@ -514,7 +513,7 @@ static IIO_DEV_ATTR_TEMP_RAW(ade7753_read_8bit);
static IIO_CONST_ATTR(in_temp_offset, "-25 C");
static IIO_CONST_ATTR(in_temp_scale, "0.67 C");
-static IIO_DEV_ATTR_SAMP_FREQ(S_IWUSR | S_IRUGO,
+static IIO_DEV_ATTR_SAMP_FREQ(0644,
ade7753_read_frequency,
ade7753_write_frequency);
diff --git a/drivers/staging/iio/meter/ade7754.c b/drivers/staging/iio/meter/ade7754.c
index 32dc50341746..be0df3fe4230 100644
--- a/drivers/staging/iio/meter/ade7754.c
+++ b/drivers/staging/iio/meter/ade7754.c
@@ -316,111 +316,111 @@ static IIO_DEV_ATTR_AENERGY(ade7754_read_24bit, ADE7754_AENERGY);
static IIO_DEV_ATTR_LAENERGY(ade7754_read_24bit, ADE7754_LAENERGY);
static IIO_DEV_ATTR_VAENERGY(ade7754_read_24bit, ADE7754_VAENERGY);
static IIO_DEV_ATTR_LVAENERGY(ade7754_read_24bit, ADE7754_LVAENERGY);
-static IIO_DEV_ATTR_VPEAK(S_IWUSR | S_IRUGO,
+static IIO_DEV_ATTR_VPEAK(0644,
ade7754_read_8bit,
ade7754_write_8bit,
ADE7754_VPEAK);
-static IIO_DEV_ATTR_IPEAK(S_IWUSR | S_IRUGO,
+static IIO_DEV_ATTR_IPEAK(0644,
ade7754_read_8bit,
ade7754_write_8bit,
ADE7754_VPEAK);
-static IIO_DEV_ATTR_APHCAL(S_IWUSR | S_IRUGO,
+static IIO_DEV_ATTR_APHCAL(0644,
ade7754_read_8bit,
ade7754_write_8bit,
ADE7754_APHCAL);
-static IIO_DEV_ATTR_BPHCAL(S_IWUSR | S_IRUGO,
+static IIO_DEV_ATTR_BPHCAL(0644,
ade7754_read_8bit,
ade7754_write_8bit,
ADE7754_BPHCAL);
-static IIO_DEV_ATTR_CPHCAL(S_IWUSR | S_IRUGO,
+static IIO_DEV_ATTR_CPHCAL(0644,
ade7754_read_8bit,
ade7754_write_8bit,
ADE7754_CPHCAL);
-static IIO_DEV_ATTR_AAPOS(S_IWUSR | S_IRUGO,
+static IIO_DEV_ATTR_AAPOS(0644,
ade7754_read_16bit,
ade7754_write_16bit,
ADE7754_AAPOS);
-static IIO_DEV_ATTR_BAPOS(S_IWUSR | S_IRUGO,
+static IIO_DEV_ATTR_BAPOS(0644,
ade7754_read_16bit,
ade7754_write_16bit,
ADE7754_BAPOS);
-static IIO_DEV_ATTR_CAPOS(S_IWUSR | S_IRUGO,
+static IIO_DEV_ATTR_CAPOS(0644,
ade7754_read_16bit,
ade7754_write_16bit,
ADE7754_CAPOS);
-static IIO_DEV_ATTR_WDIV(S_IWUSR | S_IRUGO,
+static IIO_DEV_ATTR_WDIV(0644,
ade7754_read_8bit,
ade7754_write_8bit,
ADE7754_WDIV);
-static IIO_DEV_ATTR_VADIV(S_IWUSR | S_IRUGO,
+static IIO_DEV_ATTR_VADIV(0644,
ade7754_read_8bit,
ade7754_write_8bit,
ADE7754_VADIV);
-static IIO_DEV_ATTR_CFNUM(S_IWUSR | S_IRUGO,
+static IIO_DEV_ATTR_CFNUM(0644,
ade7754_read_16bit,
ade7754_write_16bit,
ADE7754_CFNUM);
-static IIO_DEV_ATTR_CFDEN(S_IWUSR | S_IRUGO,
+static IIO_DEV_ATTR_CFDEN(0644,
ade7754_read_16bit,
ade7754_write_16bit,
ADE7754_CFDEN);
-static IIO_DEV_ATTR_ACTIVE_POWER_A_GAIN(S_IWUSR | S_IRUGO,
+static IIO_DEV_ATTR_ACTIVE_POWER_A_GAIN(0644,
ade7754_read_16bit,
ade7754_write_16bit,
ADE7754_AAPGAIN);
-static IIO_DEV_ATTR_ACTIVE_POWER_B_GAIN(S_IWUSR | S_IRUGO,
+static IIO_DEV_ATTR_ACTIVE_POWER_B_GAIN(0644,
ade7754_read_16bit,
ade7754_write_16bit,
ADE7754_BAPGAIN);
-static IIO_DEV_ATTR_ACTIVE_POWER_C_GAIN(S_IWUSR | S_IRUGO,
+static IIO_DEV_ATTR_ACTIVE_POWER_C_GAIN(0644,
ade7754_read_16bit,
ade7754_write_16bit,
ADE7754_CAPGAIN);
-static IIO_DEV_ATTR_AIRMS(S_IRUGO,
+static IIO_DEV_ATTR_AIRMS(0444,
ade7754_read_24bit,
NULL,
ADE7754_AIRMS);
-static IIO_DEV_ATTR_BIRMS(S_IRUGO,
+static IIO_DEV_ATTR_BIRMS(0444,
ade7754_read_24bit,
NULL,
ADE7754_BIRMS);
-static IIO_DEV_ATTR_CIRMS(S_IRUGO,
+static IIO_DEV_ATTR_CIRMS(0444,
ade7754_read_24bit,
NULL,
ADE7754_CIRMS);
-static IIO_DEV_ATTR_AVRMS(S_IRUGO,
+static IIO_DEV_ATTR_AVRMS(0444,
ade7754_read_24bit,
NULL,
ADE7754_AVRMS);
-static IIO_DEV_ATTR_BVRMS(S_IRUGO,
+static IIO_DEV_ATTR_BVRMS(0444,
ade7754_read_24bit,
NULL,
ADE7754_BVRMS);
-static IIO_DEV_ATTR_CVRMS(S_IRUGO,
+static IIO_DEV_ATTR_CVRMS(0444,
ade7754_read_24bit,
NULL,
ADE7754_CVRMS);
-static IIO_DEV_ATTR_AIRMSOS(S_IRUGO,
+static IIO_DEV_ATTR_AIRMSOS(0444,
ade7754_read_16bit,
ade7754_write_16bit,
ADE7754_AIRMSOS);
-static IIO_DEV_ATTR_BIRMSOS(S_IRUGO,
+static IIO_DEV_ATTR_BIRMSOS(0444,
ade7754_read_16bit,
ade7754_write_16bit,
ADE7754_BIRMSOS);
-static IIO_DEV_ATTR_CIRMSOS(S_IRUGO,
+static IIO_DEV_ATTR_CIRMSOS(0444,
ade7754_read_16bit,
ade7754_write_16bit,
ADE7754_CIRMSOS);
-static IIO_DEV_ATTR_AVRMSOS(S_IRUGO,
+static IIO_DEV_ATTR_AVRMSOS(0444,
ade7754_read_16bit,
ade7754_write_16bit,
ADE7754_AVRMSOS);
-static IIO_DEV_ATTR_BVRMSOS(S_IRUGO,
+static IIO_DEV_ATTR_BVRMSOS(0444,
ade7754_read_16bit,
ade7754_write_16bit,
ADE7754_BVRMSOS);
-static IIO_DEV_ATTR_CVRMSOS(S_IRUGO,
+static IIO_DEV_ATTR_CVRMSOS(0444,
ade7754_read_16bit,
ade7754_write_16bit,
ADE7754_CVRMSOS);
@@ -549,7 +549,7 @@ static IIO_DEV_ATTR_TEMP_RAW(ade7754_read_8bit);
static IIO_CONST_ATTR(in_temp_offset, "129 C");
static IIO_CONST_ATTR(in_temp_scale, "4 C");
-static IIO_DEV_ATTR_SAMP_FREQ(S_IWUSR | S_IRUGO,
+static IIO_DEV_ATTR_SAMP_FREQ(0644,
ade7754_read_frequency,
ade7754_write_frequency);
diff --git a/drivers/staging/iio/meter/ade7758_core.c b/drivers/staging/iio/meter/ade7758_core.c
index 99c89e606c8d..40498af4dc46 100644
--- a/drivers/staging/iio/meter/ade7758_core.c
+++ b/drivers/staging/iio/meter/ade7758_core.c
@@ -301,103 +301,103 @@ static int ade7758_reset(struct device *dev)
return ret;
}
-static IIO_DEV_ATTR_VPEAK(S_IWUSR | S_IRUGO,
+static IIO_DEV_ATTR_VPEAK(0644,
ade7758_read_8bit,
ade7758_write_8bit,
ADE7758_VPEAK);
-static IIO_DEV_ATTR_IPEAK(S_IWUSR | S_IRUGO,
+static IIO_DEV_ATTR_IPEAK(0644,
ade7758_read_8bit,
ade7758_write_8bit,
ADE7758_VPEAK);
-static IIO_DEV_ATTR_APHCAL(S_IWUSR | S_IRUGO,
+static IIO_DEV_ATTR_APHCAL(0644,
ade7758_read_8bit,
ade7758_write_8bit,
ADE7758_APHCAL);
-static IIO_DEV_ATTR_BPHCAL(S_IWUSR | S_IRUGO,
+static IIO_DEV_ATTR_BPHCAL(0644,
ade7758_read_8bit,
ade7758_write_8bit,
ADE7758_BPHCAL);
-static IIO_DEV_ATTR_CPHCAL(S_IWUSR | S_IRUGO,
+static IIO_DEV_ATTR_CPHCAL(0644,
ade7758_read_8bit,
ade7758_write_8bit,
ADE7758_CPHCAL);
-static IIO_DEV_ATTR_WDIV(S_IWUSR | S_IRUGO,
+static IIO_DEV_ATTR_WDIV(0644,
ade7758_read_8bit,
ade7758_write_8bit,
ADE7758_WDIV);
-static IIO_DEV_ATTR_VADIV(S_IWUSR | S_IRUGO,
+static IIO_DEV_ATTR_VADIV(0644,
ade7758_read_8bit,
ade7758_write_8bit,
ADE7758_VADIV);
-static IIO_DEV_ATTR_AIRMS(S_IRUGO,
+static IIO_DEV_ATTR_AIRMS(0444,
ade7758_read_24bit,
NULL,
ADE7758_AIRMS);
-static IIO_DEV_ATTR_BIRMS(S_IRUGO,
+static IIO_DEV_ATTR_BIRMS(0444,
ade7758_read_24bit,
NULL,
ADE7758_BIRMS);
-static IIO_DEV_ATTR_CIRMS(S_IRUGO,
+static IIO_DEV_ATTR_CIRMS(0444,
ade7758_read_24bit,
NULL,
ADE7758_CIRMS);
-static IIO_DEV_ATTR_AVRMS(S_IRUGO,
+static IIO_DEV_ATTR_AVRMS(0444,
ade7758_read_24bit,
NULL,
ADE7758_AVRMS);
-static IIO_DEV_ATTR_BVRMS(S_IRUGO,
+static IIO_DEV_ATTR_BVRMS(0444,
ade7758_read_24bit,
NULL,
ADE7758_BVRMS);
-static IIO_DEV_ATTR_CVRMS(S_IRUGO,
+static IIO_DEV_ATTR_CVRMS(0444,
ade7758_read_24bit,
NULL,
ADE7758_CVRMS);
-static IIO_DEV_ATTR_AIRMSOS(S_IWUSR | S_IRUGO,
+static IIO_DEV_ATTR_AIRMSOS(0644,
ade7758_read_16bit,
ade7758_write_16bit,
ADE7758_AIRMSOS);
-static IIO_DEV_ATTR_BIRMSOS(S_IWUSR | S_IRUGO,
+static IIO_DEV_ATTR_BIRMSOS(0644,
ade7758_read_16bit,
ade7758_write_16bit,
ADE7758_BIRMSOS);
-static IIO_DEV_ATTR_CIRMSOS(S_IWUSR | S_IRUGO,
+static IIO_DEV_ATTR_CIRMSOS(0644,
ade7758_read_16bit,
ade7758_write_16bit,
ADE7758_CIRMSOS);
-static IIO_DEV_ATTR_AVRMSOS(S_IWUSR | S_IRUGO,
+static IIO_DEV_ATTR_AVRMSOS(0644,
ade7758_read_16bit,
ade7758_write_16bit,
ADE7758_AVRMSOS);
-static IIO_DEV_ATTR_BVRMSOS(S_IWUSR | S_IRUGO,
+static IIO_DEV_ATTR_BVRMSOS(0644,
ade7758_read_16bit,
ade7758_write_16bit,
ADE7758_BVRMSOS);
-static IIO_DEV_ATTR_CVRMSOS(S_IWUSR | S_IRUGO,
+static IIO_DEV_ATTR_CVRMSOS(0644,
ade7758_read_16bit,
ade7758_write_16bit,
ADE7758_CVRMSOS);
-static IIO_DEV_ATTR_AIGAIN(S_IWUSR | S_IRUGO,
+static IIO_DEV_ATTR_AIGAIN(0644,
ade7758_read_16bit,
ade7758_write_16bit,
ADE7758_AIGAIN);
-static IIO_DEV_ATTR_BIGAIN(S_IWUSR | S_IRUGO,
+static IIO_DEV_ATTR_BIGAIN(0644,
ade7758_read_16bit,
ade7758_write_16bit,
ADE7758_BIGAIN);
-static IIO_DEV_ATTR_CIGAIN(S_IWUSR | S_IRUGO,
+static IIO_DEV_ATTR_CIGAIN(0644,
ade7758_read_16bit,
ade7758_write_16bit,
ADE7758_CIGAIN);
-static IIO_DEV_ATTR_AVRMSGAIN(S_IWUSR | S_IRUGO,
+static IIO_DEV_ATTR_AVRMSGAIN(0644,
ade7758_read_16bit,
ade7758_write_16bit,
ADE7758_AVRMSGAIN);
-static IIO_DEV_ATTR_BVRMSGAIN(S_IWUSR | S_IRUGO,
+static IIO_DEV_ATTR_BVRMSGAIN(0644,
ade7758_read_16bit,
ade7758_write_16bit,
ADE7758_BVRMSGAIN);
-static IIO_DEV_ATTR_CVRMSGAIN(S_IWUSR | S_IRUGO,
+static IIO_DEV_ATTR_CVRMSGAIN(0644,
ade7758_read_16bit,
ade7758_write_16bit,
ADE7758_CVRMSGAIN);
diff --git a/drivers/staging/iio/meter/ade7854.c b/drivers/staging/iio/meter/ade7854.c
index c6cffc11b0ba..70612da64a8b 100644
--- a/drivers/staging/iio/meter/ade7854.c
+++ b/drivers/staging/iio/meter/ade7854.c
@@ -186,127 +186,127 @@ static int ade7854_reset(struct device *dev)
return st->write_reg_16(dev, ADE7854_CONFIG, val);
}
-static IIO_DEV_ATTR_AIGAIN(S_IWUSR | S_IRUGO,
+static IIO_DEV_ATTR_AIGAIN(0644,
ade7854_read_24bit,
ade7854_write_24bit,
ADE7854_AIGAIN);
-static IIO_DEV_ATTR_BIGAIN(S_IWUSR | S_IRUGO,
+static IIO_DEV_ATTR_BIGAIN(0644,
ade7854_read_24bit,
ade7854_write_24bit,
ADE7854_BIGAIN);
-static IIO_DEV_ATTR_CIGAIN(S_IWUSR | S_IRUGO,
+static IIO_DEV_ATTR_CIGAIN(0644,
ade7854_read_24bit,
ade7854_write_24bit,
ADE7854_CIGAIN);
-static IIO_DEV_ATTR_NIGAIN(S_IWUSR | S_IRUGO,
+static IIO_DEV_ATTR_NIGAIN(0644,
ade7854_read_24bit,
ade7854_write_24bit,
ADE7854_NIGAIN);
-static IIO_DEV_ATTR_AVGAIN(S_IWUSR | S_IRUGO,
+static IIO_DEV_ATTR_AVGAIN(0644,
ade7854_read_24bit,
ade7854_write_24bit,
ADE7854_AVGAIN);
-static IIO_DEV_ATTR_BVGAIN(S_IWUSR | S_IRUGO,
+static IIO_DEV_ATTR_BVGAIN(0644,
ade7854_read_24bit,
ade7854_write_24bit,
ADE7854_BVGAIN);
-static IIO_DEV_ATTR_CVGAIN(S_IWUSR | S_IRUGO,
+static IIO_DEV_ATTR_CVGAIN(0644,
ade7854_read_24bit,
ade7854_write_24bit,
ADE7854_CVGAIN);
-static IIO_DEV_ATTR_APPARENT_POWER_A_GAIN(S_IWUSR | S_IRUGO,
+static IIO_DEV_ATTR_APPARENT_POWER_A_GAIN(0644,
ade7854_read_24bit,
ade7854_write_24bit,
ADE7854_AVAGAIN);
-static IIO_DEV_ATTR_APPARENT_POWER_B_GAIN(S_IWUSR | S_IRUGO,
+static IIO_DEV_ATTR_APPARENT_POWER_B_GAIN(0644,
ade7854_read_24bit,
ade7854_write_24bit,
ADE7854_BVAGAIN);
-static IIO_DEV_ATTR_APPARENT_POWER_C_GAIN(S_IWUSR | S_IRUGO,
+static IIO_DEV_ATTR_APPARENT_POWER_C_GAIN(0644,
ade7854_read_24bit,
ade7854_write_24bit,
ADE7854_CVAGAIN);
-static IIO_DEV_ATTR_ACTIVE_POWER_A_OFFSET(S_IWUSR | S_IRUGO,
+static IIO_DEV_ATTR_ACTIVE_POWER_A_OFFSET(0644,
ade7854_read_24bit,
ade7854_write_24bit,
ADE7854_AWATTOS);
-static IIO_DEV_ATTR_ACTIVE_POWER_B_OFFSET(S_IWUSR | S_IRUGO,
+static IIO_DEV_ATTR_ACTIVE_POWER_B_OFFSET(0644,
ade7854_read_24bit,
ade7854_write_24bit,
ADE7854_BWATTOS);
-static IIO_DEV_ATTR_ACTIVE_POWER_C_OFFSET(S_IWUSR | S_IRUGO,
+static IIO_DEV_ATTR_ACTIVE_POWER_C_OFFSET(0644,
ade7854_read_24bit,
ade7854_write_24bit,
ADE7854_CWATTOS);
-static IIO_DEV_ATTR_REACTIVE_POWER_A_GAIN(S_IWUSR | S_IRUGO,
+static IIO_DEV_ATTR_REACTIVE_POWER_A_GAIN(0644,
ade7854_read_24bit,
ade7854_write_24bit,
ADE7854_AVARGAIN);
-static IIO_DEV_ATTR_REACTIVE_POWER_B_GAIN(S_IWUSR | S_IRUGO,
+static IIO_DEV_ATTR_REACTIVE_POWER_B_GAIN(0644,
ade7854_read_24bit,
ade7854_write_24bit,
ADE7854_BVARGAIN);
-static IIO_DEV_ATTR_REACTIVE_POWER_C_GAIN(S_IWUSR | S_IRUGO,
+static IIO_DEV_ATTR_REACTIVE_POWER_C_GAIN(0644,
ade7854_read_24bit,
ade7854_write_24bit,
ADE7854_CVARGAIN);
-static IIO_DEV_ATTR_REACTIVE_POWER_A_OFFSET(S_IWUSR | S_IRUGO,
+static IIO_DEV_ATTR_REACTIVE_POWER_A_OFFSET(0644,
ade7854_read_24bit,
ade7854_write_24bit,
ADE7854_AVAROS);
-static IIO_DEV_ATTR_REACTIVE_POWER_B_OFFSET(S_IWUSR | S_IRUGO,
+static IIO_DEV_ATTR_REACTIVE_POWER_B_OFFSET(0644,
ade7854_read_24bit,
ade7854_write_24bit,
ADE7854_BVAROS);
-static IIO_DEV_ATTR_REACTIVE_POWER_C_OFFSET(S_IWUSR | S_IRUGO,
+static IIO_DEV_ATTR_REACTIVE_POWER_C_OFFSET(0644,
ade7854_read_24bit,
ade7854_write_24bit,
ADE7854_CVAROS);
-static IIO_DEV_ATTR_VPEAK(S_IWUSR | S_IRUGO,
+static IIO_DEV_ATTR_VPEAK(0644,
ade7854_read_32bit,
ade7854_write_32bit,
ADE7854_VPEAK);
-static IIO_DEV_ATTR_IPEAK(S_IWUSR | S_IRUGO,
+static IIO_DEV_ATTR_IPEAK(0644,
ade7854_read_32bit,
ade7854_write_32bit,
ADE7854_VPEAK);
-static IIO_DEV_ATTR_APHCAL(S_IWUSR | S_IRUGO,
+static IIO_DEV_ATTR_APHCAL(0644,
ade7854_read_16bit,
ade7854_write_16bit,
ADE7854_APHCAL);
-static IIO_DEV_ATTR_BPHCAL(S_IWUSR | S_IRUGO,
+static IIO_DEV_ATTR_BPHCAL(0644,
ade7854_read_16bit,
ade7854_write_16bit,
ADE7854_BPHCAL);
-static IIO_DEV_ATTR_CPHCAL(S_IWUSR | S_IRUGO,
+static IIO_DEV_ATTR_CPHCAL(0644,
ade7854_read_16bit,
ade7854_write_16bit,
ADE7854_CPHCAL);
-static IIO_DEV_ATTR_CF1DEN(S_IWUSR | S_IRUGO,
+static IIO_DEV_ATTR_CF1DEN(0644,
ade7854_read_16bit,
ade7854_write_16bit,
ADE7854_CF1DEN);
-static IIO_DEV_ATTR_CF2DEN(S_IWUSR | S_IRUGO,
+static IIO_DEV_ATTR_CF2DEN(0644,
ade7854_read_16bit,
ade7854_write_16bit,
ADE7854_CF2DEN);
-static IIO_DEV_ATTR_CF3DEN(S_IWUSR | S_IRUGO,
+static IIO_DEV_ATTR_CF3DEN(0644,
ade7854_read_16bit,
ade7854_write_16bit,
ADE7854_CF3DEN);
-static IIO_DEV_ATTR_LINECYC(S_IWUSR | S_IRUGO,
+static IIO_DEV_ATTR_LINECYC(0644,
ade7854_read_16bit,
ade7854_write_16bit,
ADE7854_LINECYC);
-static IIO_DEV_ATTR_SAGCYC(S_IWUSR | S_IRUGO,
+static IIO_DEV_ATTR_SAGCYC(0644,
ade7854_read_8bit,
ade7854_write_8bit,
ADE7854_SAGCYC);
-static IIO_DEV_ATTR_CFCYC(S_IWUSR | S_IRUGO,
+static IIO_DEV_ATTR_CFCYC(0644,
ade7854_read_8bit,
ade7854_write_8bit,
ADE7854_CFCYC);
-static IIO_DEV_ATTR_PEAKCYC(S_IWUSR | S_IRUGO,
+static IIO_DEV_ATTR_PEAKCYC(0644,
ade7854_read_8bit,
ade7854_write_8bit,
ADE7854_PEAKCYC);
@@ -318,55 +318,55 @@ static IIO_DEV_ATTR_ANGLE1(ade7854_read_24bit,
ADE7854_ANGLE1);
static IIO_DEV_ATTR_ANGLE2(ade7854_read_24bit,
ADE7854_ANGLE2);
-static IIO_DEV_ATTR_AIRMS(S_IRUGO,
+static IIO_DEV_ATTR_AIRMS(0444,
ade7854_read_24bit,
NULL,
ADE7854_AIRMS);
-static IIO_DEV_ATTR_BIRMS(S_IRUGO,
+static IIO_DEV_ATTR_BIRMS(0444,
ade7854_read_24bit,
NULL,
ADE7854_BIRMS);
-static IIO_DEV_ATTR_CIRMS(S_IRUGO,
+static IIO_DEV_ATTR_CIRMS(0444,
ade7854_read_24bit,
NULL,
ADE7854_CIRMS);
-static IIO_DEV_ATTR_NIRMS(S_IRUGO,
+static IIO_DEV_ATTR_NIRMS(0444,
ade7854_read_24bit,
NULL,
ADE7854_NIRMS);
-static IIO_DEV_ATTR_AVRMS(S_IRUGO,
+static IIO_DEV_ATTR_AVRMS(0444,
ade7854_read_24bit,
NULL,
ADE7854_AVRMS);
-static IIO_DEV_ATTR_BVRMS(S_IRUGO,
+static IIO_DEV_ATTR_BVRMS(0444,
ade7854_read_24bit,
NULL,
ADE7854_BVRMS);
-static IIO_DEV_ATTR_CVRMS(S_IRUGO,
+static IIO_DEV_ATTR_CVRMS(0444,
ade7854_read_24bit,
NULL,
ADE7854_CVRMS);
-static IIO_DEV_ATTR_AIRMSOS(S_IRUGO,
+static IIO_DEV_ATTR_AIRMSOS(0444,
ade7854_read_16bit,
ade7854_write_16bit,
ADE7854_AIRMSOS);
-static IIO_DEV_ATTR_BIRMSOS(S_IRUGO,
+static IIO_DEV_ATTR_BIRMSOS(0444,
ade7854_read_16bit,
ade7854_write_16bit,
ADE7854_BIRMSOS);
-static IIO_DEV_ATTR_CIRMSOS(S_IRUGO,
+static IIO_DEV_ATTR_CIRMSOS(0444,
ade7854_read_16bit,
ade7854_write_16bit,
ADE7854_CIRMSOS);
-static IIO_DEV_ATTR_AVRMSOS(S_IRUGO,
+static IIO_DEV_ATTR_AVRMSOS(0444,
ade7854_read_16bit,
ade7854_write_16bit,
ADE7854_AVRMSOS);
-static IIO_DEV_ATTR_BVRMSOS(S_IRUGO,
+static IIO_DEV_ATTR_BVRMSOS(0444,
ade7854_read_16bit,
ade7854_write_16bit,
ADE7854_BVRMSOS);
-static IIO_DEV_ATTR_CVRMSOS(S_IRUGO,
+static IIO_DEV_ATTR_CVRMSOS(0444,
ade7854_read_16bit,
ade7854_write_16bit,
ADE7854_CVRMSOS);
diff --git a/drivers/staging/ks7010/eap_packet.h b/drivers/staging/ks7010/eap_packet.h
index b2d25ef1cd6b..ae03f7477324 100644
--- a/drivers/staging/ks7010/eap_packet.h
+++ b/drivers/staging/ks7010/eap_packet.h
@@ -18,7 +18,7 @@ struct ether_hdr {
unsigned char h_source_snap;
unsigned char h_command;
unsigned char h_vendor_id[3];
- unsigned short h_proto; /* packet type ID field */
+ __be16 h_proto; /* packet type ID field */
#define ETHER_PROTOCOL_TYPE_EAP 0x888e
#define ETHER_PROTOCOL_TYPE_IP 0x0800
#define ETHER_PROTOCOL_TYPE_ARP 0x0806
@@ -91,7 +91,7 @@ struct ieee802_1x_eapol_key {
struct wpa_eapol_key {
unsigned char type;
- unsigned short key_info;
+ __be16 key_info;
unsigned short key_length;
unsigned char replay_counter[WPA_REPLAY_COUNTER_LEN];
unsigned char key_nonce[WPA_NONCE_LEN];
diff --git a/drivers/staging/ks7010/ks7010_sdio.c b/drivers/staging/ks7010/ks7010_sdio.c
index c325f4846209..9b28ee1cfb1e 100644
--- a/drivers/staging/ks7010/ks7010_sdio.c
+++ b/drivers/staging/ks7010/ks7010_sdio.c
@@ -269,7 +269,8 @@ static int write_to_device(struct ks_wlan_private *priv, unsigned char *buffer,
hdr = (struct hostif_hdr *)buffer;
DPRINTK(4, "size=%d\n", hdr->size);
- if (hdr->event < HIF_DATA_REQ || HIF_REQ_MAX < hdr->event) {
+ if (le16_to_cpu(hdr->event) < HIF_DATA_REQ ||
+ le16_to_cpu(hdr->event) > HIF_REQ_MAX) {
DPRINTK(1, "unknown event=%04X\n", hdr->event);
return 0;
}
@@ -327,13 +328,14 @@ int ks_wlan_hw_tx(struct ks_wlan_private *priv, void *p, unsigned long size,
hdr = (struct hostif_hdr *)p;
- if (hdr->event < HIF_DATA_REQ || HIF_REQ_MAX < hdr->event) {
+ if (le16_to_cpu(hdr->event) < HIF_DATA_REQ ||
+ le16_to_cpu(hdr->event) > HIF_REQ_MAX) {
DPRINTK(1, "unknown event=%04X\n", hdr->event);
return 0;
}
/* add event to hostt buffer */
- priv->hostt.buff[priv->hostt.qtail] = hdr->event;
+ priv->hostt.buff[priv->hostt.qtail] = le16_to_cpu(hdr->event);
priv->hostt.qtail = (priv->hostt.qtail + 1) % SME_EVENT_BUFF_SIZE;
DPRINTK(4, "event=%04X\n", hdr->event);
@@ -403,7 +405,7 @@ static void ks_wlan_hw_rx(struct ks_wlan_private *priv, uint16_t size)
hdr = (struct hostif_hdr *)&rx_buffer->data[0];
rx_buffer->size = le16_to_cpu(hdr->size) + sizeof(hdr->size);
- event = hdr->event;
+ event = le16_to_cpu(hdr->event);
inc_rxqtail(priv);
ret = ks7010_sdio_writeb(priv, READ_STATUS, REG_STATUS_IDLE);
diff --git a/drivers/staging/ks7010/ks_hostif.c b/drivers/staging/ks7010/ks_hostif.c
index 49e95426ac30..db01a486a5a4 100644
--- a/drivers/staging/ks7010/ks_hostif.c
+++ b/drivers/staging/ks7010/ks_hostif.c
@@ -147,7 +147,7 @@ int get_current_ap(struct ks_wlan_private *priv, struct link_ap_info_t *ap_info)
/* noise */
ap->noise = ap_info->noise;
/* capability */
- ap->capability = ap_info->capability;
+ ap->capability = le16_to_cpu(ap_info->capability);
/* rsn */
if ((ap_info->rsn_mode & RSN_MODE_WPA2) &&
(priv->wpa.version == IW_AUTH_WPA_VERSION_WPA2)) {
@@ -233,12 +233,12 @@ int get_ap_information(struct ks_wlan_private *priv, struct ap_info_t *ap_info,
/* noise */
ap->noise = ap_info->noise;
/* capability */
- ap->capability = ap_info->capability;
+ ap->capability = le16_to_cpu(ap_info->capability);
/* channel */
ap->channel = ap_info->ch_info;
bp = ap_info->body;
- bsize = ap_info->body_size;
+ bsize = le16_to_cpu(ap_info->body_size);
offset = 0;
while (bsize > offset) {
@@ -567,9 +567,9 @@ void hostif_mib_get_confirm(struct ks_wlan_private *priv)
break;
case LOCAL_GAIN:
memcpy(&priv->gain, priv->rxp, sizeof(priv->gain));
- DPRINTK(3, "TxMode=%d, RxMode=%d, TxGain=%d, RxGain=%d\n",
- priv->gain.TxMode, priv->gain.RxMode, priv->gain.TxGain,
- priv->gain.RxGain);
+ DPRINTK(3, "tx_mode=%d, rx_mode=%d, tx_gain=%d, rx_gain=%d\n",
+ priv->gain.tx_mode, priv->gain.rx_mode,
+ priv->gain.tx_gain, priv->gain.rx_gain);
break;
case LOCAL_EEPROM_SUM:
memcpy(&priv->eeprom_sum, priv->rxp, sizeof(priv->eeprom_sum));
@@ -948,18 +948,18 @@ void hostif_associate_indication(struct ks_wlan_private *priv)
wrqu.data.length += sizeof(associnfo_leader0) - 1;
pbuf += sizeof(associnfo_leader0) - 1;
- for (i = 0; i < assoc_req->reqIEs_size; i++)
+ for (i = 0; i < le16_to_cpu(assoc_req->req_ies_size); i++)
pbuf += sprintf(pbuf, "%02x", *(pb + i));
- wrqu.data.length += (assoc_req->reqIEs_size) * 2;
+ wrqu.data.length += (le16_to_cpu(assoc_req->req_ies_size)) * 2;
memcpy(pbuf, associnfo_leader1, sizeof(associnfo_leader1) - 1);
wrqu.data.length += sizeof(associnfo_leader1) - 1;
pbuf += sizeof(associnfo_leader1) - 1;
- pb += assoc_req->reqIEs_size;
- for (i = 0; i < assoc_resp->respIEs_size; i++)
+ pb += le16_to_cpu(assoc_req->req_ies_size);
+ for (i = 0; i < le16_to_cpu(assoc_resp->resp_ies_size); i++)
pbuf += sprintf(pbuf, "%02x", *(pb + i));
- wrqu.data.length += (assoc_resp->respIEs_size) * 2;
+ wrqu.data.length += (le16_to_cpu(assoc_resp->resp_ies_size)) * 2;
pbuf += sprintf(pbuf, ")");
wrqu.data.length += 1;
@@ -994,22 +994,22 @@ void hostif_phy_information_confirm(struct ks_wlan_private *priv)
{
struct iw_statistics *wstats = &priv->wstats;
unsigned char rssi, signal, noise;
- unsigned char LinkSpeed;
- unsigned int TransmittedFrameCount, ReceivedFragmentCount;
- unsigned int FailedCount, FCSErrorCount;
+ unsigned char link_speed;
+ unsigned int transmitted_frame_count, received_fragment_count;
+ unsigned int failed_count, fcs_error_count;
DPRINTK(3, "\n");
rssi = get_BYTE(priv);
signal = get_BYTE(priv);
noise = get_BYTE(priv);
- LinkSpeed = get_BYTE(priv);
- TransmittedFrameCount = get_DWORD(priv);
- ReceivedFragmentCount = get_DWORD(priv);
- FailedCount = get_DWORD(priv);
- FCSErrorCount = get_DWORD(priv);
+ link_speed = get_BYTE(priv);
+ transmitted_frame_count = get_DWORD(priv);
+ received_fragment_count = get_DWORD(priv);
+ failed_count = get_DWORD(priv);
+ fcs_error_count = get_DWORD(priv);
DPRINTK(4, "phyinfo confirm rssi=%d signal=%d\n", rssi, signal);
- priv->current_rate = (LinkSpeed & RATE_MASK);
+ priv->current_rate = (link_speed & RATE_MASK);
wstats->qual.qual = signal;
wstats->qual.level = 256 - rssi;
wstats->qual.noise = 0; /* invalid noise value */
@@ -1017,14 +1017,13 @@ void hostif_phy_information_confirm(struct ks_wlan_private *priv)
DPRINTK(3, "\n rssi=%u\n"
" signal=%u\n"
- " LinkSpeed=%ux500Kbps\n"
- " TransmittedFrameCount=%u\n"
- " ReceivedFragmentCount=%u\n"
- " FailedCount=%u\n"
- " FCSErrorCount=%u\n",
- rssi, signal, LinkSpeed, TransmittedFrameCount,
- ReceivedFragmentCount, FailedCount, FCSErrorCount);
-
+ " link_speed=%ux500Kbps\n"
+ " transmitted_frame_count=%u\n"
+ " received_fragment_count=%u\n"
+ " failed_count=%u\n"
+ " fcs_error_count=%u\n",
+ rssi, signal, link_speed, transmitted_frame_count,
+ received_fragment_count, failed_count, fcs_error_count);
/* wake_up_interruptible_all(&priv->confirm_wait); */
complete(&priv->confirm_wait);
}
@@ -1660,13 +1659,13 @@ void hostif_phy_information_request(struct ks_wlan_private *priv)
static
void hostif_power_mgmt_request(struct ks_wlan_private *priv,
- unsigned long mode, unsigned long wake_up,
- unsigned long receiveDTIMs)
+ unsigned long mode, unsigned long wake_up,
+ unsigned long receive_dtims)
{
struct hostif_power_mgmt_request_t *pp;
- DPRINTK(3, "mode=%lu wake_up=%lu receiveDTIMs=%lu\n", mode, wake_up,
- receiveDTIMs);
+ DPRINTK(3, "mode=%lu wake_up=%lu receive_dtims=%lu\n", mode, wake_up,
+ receive_dtims);
pp = hostif_generic_request(sizeof(*pp), HIF_POWER_MGMT_REQ);
if (!pp)
@@ -1674,7 +1673,7 @@ void hostif_power_mgmt_request(struct ks_wlan_private *priv,
pp->mode = cpu_to_le32((uint32_t)mode);
pp->wake_up = cpu_to_le32((uint32_t)wake_up);
- pp->receiveDTIMs = cpu_to_le32((uint32_t)receiveDTIMs);
+ pp->receive_dtims = cpu_to_le32((uint32_t)receive_dtims);
/* send to device request */
ps_confirm_wait_inc(priv);
@@ -1822,7 +1821,7 @@ void hostif_receive(struct ks_wlan_private *priv, unsigned char *p,
static
void hostif_sme_set_wep(struct ks_wlan_private *priv, int type)
{
- u32 val;
+ __le32 val;
switch (type) {
case SME_WEP_INDEX_REQUEST:
@@ -1871,13 +1870,13 @@ void hostif_sme_set_wep(struct ks_wlan_private *priv, int type)
}
struct wpa_suite_t {
- unsigned short size;
+ __le16 size;
unsigned char suite[4][CIPHER_ID_LEN];
} __packed;
struct rsn_mode_t {
- u32 rsn_mode;
- u16 rsn_capability;
+ __le32 rsn_mode;
+ __le16 rsn_capability;
} __packed;
static
@@ -1885,7 +1884,7 @@ void hostif_sme_set_rsn(struct ks_wlan_private *priv, int type)
{
struct wpa_suite_t wpa_suite;
struct rsn_mode_t rsn_mode;
- u32 val;
+ __le32 val;
memset(&wpa_suite, 0, sizeof(wpa_suite));
@@ -1937,7 +1936,8 @@ void hostif_sme_set_rsn(struct ks_wlan_private *priv, int type)
hostif_mib_set_request(priv, DOT11_RSN_CONFIG_UNICAST_CIPHER,
sizeof(wpa_suite.size) +
- CIPHER_ID_LEN * wpa_suite.size,
+ CIPHER_ID_LEN *
+ le16_to_cpu(wpa_suite.size),
MIB_VALUE_TYPE_OSTRING, &wpa_suite);
break;
case SME_RSN_MCAST_REQUEST:
@@ -2029,7 +2029,8 @@ void hostif_sme_set_rsn(struct ks_wlan_private *priv, int type)
hostif_mib_set_request(priv, DOT11_RSN_CONFIG_AUTH_SUITE,
sizeof(wpa_suite.size) +
- KEY_MGMT_ID_LEN * wpa_suite.size,
+ KEY_MGMT_ID_LEN *
+ le16_to_cpu(wpa_suite.size),
MIB_VALUE_TYPE_OSTRING, &wpa_suite);
break;
case SME_RSN_ENABLED_REQUEST:
@@ -2166,7 +2167,7 @@ void hostif_sme_multicast_set(struct ks_wlan_private *priv)
int mc_count;
struct netdev_hw_addr *ha;
char set_address[NIC_MAX_MCAST_LIST * ETH_ALEN];
- unsigned long filter_type;
+ __le32 filter_type;
int i = 0;
DPRINTK(3, "\n");
@@ -2218,44 +2219,44 @@ spin_unlock:
static
void hostif_sme_power_mgmt_set(struct ks_wlan_private *priv)
{
- unsigned long mode, wake_up, receiveDTIMs;
+ unsigned long mode, wake_up, receive_dtims;
DPRINTK(3, "\n");
switch (priv->reg.power_mgmt) {
case POWER_MGMT_ACTIVE:
mode = POWER_ACTIVE;
wake_up = 0;
- receiveDTIMs = 0;
+ receive_dtims = 0;
break;
case POWER_MGMT_SAVE1:
if (priv->reg.operation_mode == MODE_INFRASTRUCTURE) {
mode = POWER_SAVE;
wake_up = 0;
- receiveDTIMs = 0;
+ receive_dtims = 0;
} else {
mode = POWER_ACTIVE;
wake_up = 0;
- receiveDTIMs = 0;
+ receive_dtims = 0;
}
break;
case POWER_MGMT_SAVE2:
if (priv->reg.operation_mode == MODE_INFRASTRUCTURE) {
mode = POWER_SAVE;
wake_up = 0;
- receiveDTIMs = 1;
+ receive_dtims = 1;
} else {
mode = POWER_ACTIVE;
wake_up = 0;
- receiveDTIMs = 0;
+ receive_dtims = 0;
}
break;
default:
mode = POWER_ACTIVE;
wake_up = 0;
- receiveDTIMs = 0;
+ receive_dtims = 0;
break;
}
- hostif_power_mgmt_request(priv, mode, wake_up, receiveDTIMs);
+ hostif_power_mgmt_request(priv, mode, wake_up, receive_dtims);
}
static
@@ -2277,7 +2278,7 @@ void hostif_sme_sleep_set(struct ks_wlan_private *priv)
static
void hostif_sme_set_key(struct ks_wlan_private *priv, int type)
{
- u32 val;
+ __le32 val;
switch (type) {
case SME_SET_FLAG:
@@ -2336,7 +2337,7 @@ static
void hostif_sme_set_pmksa(struct ks_wlan_private *priv)
{
struct pmk_cache_t {
- u16 size;
+ __le16 size;
struct {
u8 bssid[ETH_ALEN];
u8 pmkid[IW_PMKID_LEN];
@@ -2367,7 +2368,7 @@ void hostif_sme_set_pmksa(struct ks_wlan_private *priv)
static
void hostif_sme_execute(struct ks_wlan_private *priv, int event)
{
- u32 val;
+ __le32 val;
DPRINTK(3, "event=%d\n", event);
switch (event) {
diff --git a/drivers/staging/ks7010/ks_hostif.h b/drivers/staging/ks7010/ks_hostif.h
index d758076d419d..5bae8d468e23 100644
--- a/drivers/staging/ks7010/ks_hostif.h
+++ b/drivers/staging/ks7010/ks_hostif.h
@@ -62,27 +62,27 @@
*/
struct hostif_hdr {
- u16 size;
- u16 event;
+ __le16 size;
+ __le16 event;
} __packed;
struct hostif_data_request_t {
struct hostif_hdr header;
- u16 auth_type;
+ __le16 auth_type;
#define TYPE_DATA 0x0000
#define TYPE_AUTH 0x0001
- u16 reserved;
+ __le16 reserved;
u8 data[0];
} __packed;
struct hostif_data_indication_t {
struct hostif_hdr header;
- u16 auth_type;
+ __le16 auth_type;
/* #define TYPE_DATA 0x0000 */
#define TYPE_PMK1 0x0001
#define TYPE_GMK1 0x0002
#define TYPE_GMK2 0x0003
- u16 reserved;
+ __le16 reserved;
u8 data[0];
} __packed;
@@ -143,12 +143,12 @@ struct channel_list_t {
struct hostif_mib_get_request_t {
struct hostif_hdr header;
- u32 mib_attribute;
+ __le32 mib_attribute;
} __packed;
struct hostif_mib_value_t {
- u16 size;
- u16 type;
+ __le16 size;
+ __le16 type;
#define MIB_VALUE_TYPE_NULL 0
#define MIB_VALUE_TYPE_INT 1
#define MIB_VALUE_TYPE_BOOL 2
@@ -159,36 +159,36 @@ struct hostif_mib_value_t {
struct hostif_mib_get_confirm_t {
struct hostif_hdr header;
- u32 mib_status;
+ __le32 mib_status;
#define MIB_SUCCESS 0
#define MIB_INVALID 1
#define MIB_READ_ONLY 2
#define MIB_WRITE_ONLY 3
- u32 mib_attribute;
+ __le32 mib_attribute;
struct hostif_mib_value_t mib_value;
} __packed;
struct hostif_mib_set_request_t {
struct hostif_hdr header;
- u32 mib_attribute;
+ __le32 mib_attribute;
struct hostif_mib_value_t mib_value;
} __packed;
struct hostif_mib_set_confirm_t {
struct hostif_hdr header;
- u32 mib_status;
- u32 mib_attribute;
+ __le32 mib_status;
+ __le32 mib_attribute;
} __packed;
struct hostif_power_mgmt_request_t {
struct hostif_hdr header;
- u32 mode;
+ __le32 mode;
#define POWER_ACTIVE 1
#define POWER_SAVE 2
- u32 wake_up;
+ __le32 wake_up;
#define SLEEP_FALSE 0
#define SLEEP_TRUE 1 /* not used */
- u32 receiveDTIMs;
+ __le32 receive_dtims;
#define DTIM_FALSE 0
#define DTIM_TRUE 1
} __packed;
@@ -207,12 +207,12 @@ enum power_mgmt_mode_type {
struct hostif_power_mgmt_confirm_t {
struct hostif_hdr header;
- u16 result_code;
+ __le16 result_code;
} __packed;
struct hostif_start_request_t {
struct hostif_hdr header;
- u16 mode;
+ __le16 mode;
#define MODE_PSEUDO_ADHOC 0
#define MODE_INFRASTRUCTURE 1
#define MODE_AP 2 /* not used */
@@ -221,7 +221,7 @@ struct hostif_start_request_t {
struct hostif_start_confirm_t {
struct hostif_hdr header;
- u16 result_code;
+ __le16 result_code;
} __packed;
#define SSID_MAX_SIZE 32
@@ -238,26 +238,26 @@ struct rate_set8_t {
u8 rate_pad;
} __packed;
-struct FhParms_t {
- u16 dwellTime;
- u8 hopSet;
- u8 hopPattern;
- u8 hopIndex;
+struct fh_parms_t {
+ __le16 dwell_time;
+ u8 hop_set;
+ u8 hop_pattern;
+ u8 hop_index;
} __packed;
-struct DsParms_t {
+struct ds_parms_t {
u8 channel;
} __packed;
-struct CfParms_t {
+struct cf_parms_t {
u8 count;
u8 period;
- u16 maxDuration;
- u16 durRemaining;
+ __le16 max_duration;
+ __le16 dur_remaining;
} __packed;
-struct IbssParms_t {
- u16 atimWindow;
+struct ibss_parms_t {
+ __le16 atim_window;
} __packed;
struct rsn_t {
@@ -266,7 +266,7 @@ struct rsn_t {
u8 body[RSN_BODY_SIZE];
} __packed;
-struct ErpParams_t {
+struct erp_params_t {
u8 erp_info;
} __packed;
@@ -282,8 +282,8 @@ struct ap_info_t {
u8 sq; /* +07 */
u8 noise; /* +08 */
u8 pad0; /* +09 */
- u16 beacon_period; /* +10 */
- u16 capability; /* +12 */
+ __le16 beacon_period; /* +10 */
+ __le16 capability; /* +12 */
#define BSS_CAP_ESS BIT(0)
#define BSS_CAP_IBSS BIT(1)
#define BSS_CAP_CF_POLABLE BIT(2)
@@ -298,7 +298,7 @@ struct ap_info_t {
u8 ch_info; /* +15 */
#define FRAME_TYPE_BEACON 0x80
#define FRAME_TYPE_PROBE_RESP 0x50
- u16 body_size; /* +16 */
+ __le16 body_size; /* +16 */
u8 body[1024]; /* +18 */
/* +1032 */
} __packed;
@@ -309,14 +309,14 @@ struct link_ap_info_t {
u8 sq; /* +07 */
u8 noise; /* +08 */
u8 pad0; /* +09 */
- u16 beacon_period; /* +10 */
- u16 capability; /* +12 */
+ __le16 beacon_period; /* +10 */
+ __le16 capability; /* +12 */
struct rate_set8_t rate_set; /* +14 */
- struct FhParms_t fh_parameter; /* +24 */
- struct DsParms_t ds_parameter; /* +29 */
- struct CfParms_t cf_parameter; /* +30 */
- struct IbssParms_t ibss_parameter; /* +36 */
- struct ErpParams_t erp_parameter; /* +38 */
+ struct fh_parms_t fh_parameter; /* +24 */
+ struct ds_parms_t ds_parameter; /* +29 */
+ struct cf_parms_t cf_parameter; /* +30 */
+ struct ibss_parms_t ibss_parameter; /* +36 */
+ struct erp_params_t erp_parameter; /* +38 */
u8 pad1; /* +39 */
struct rate_set8_t ext_rate_set; /* +40 */
u8 DTIM_period; /* +50 */
@@ -332,7 +332,7 @@ struct link_ap_info_t {
struct hostif_connect_indication_t {
struct hostif_hdr header;
- u16 connect_code;
+ __le16 connect_code;
#define RESULT_CONNECT 0
#define RESULT_DISCONNECT 1
struct link_ap_info_t link_ap_info;
@@ -344,7 +344,7 @@ struct hostif_stop_request_t {
struct hostif_stop_confirm_t {
struct hostif_hdr header;
- u16 result_code;
+ __le16 result_code;
} __packed;
/**
@@ -356,23 +356,23 @@ struct hostif_stop_confirm_t {
*/
struct hostif_ps_adhoc_set_request_t {
struct hostif_hdr header;
- u16 phy_type;
+ __le16 phy_type;
#define D_11B_ONLY_MODE 0
#define D_11G_ONLY_MODE 1
#define D_11BG_COMPATIBLE_MODE 2
#define D_11A_ONLY_MODE 3
- u16 cts_mode;
+ __le16 cts_mode;
#define CTS_MODE_FALSE 0
#define CTS_MODE_TRUE 1
- u16 channel;
+ __le16 channel;
struct rate_set16_t rate_set;
- u16 capability;
- u16 scan_type;
+ __le16 capability;
+ __le16 scan_type;
} __packed;
struct hostif_ps_adhoc_set_confirm_t {
struct hostif_hdr header;
- u16 result_code;
+ __le16 result_code;
} __packed;
/**
@@ -384,17 +384,17 @@ struct hostif_ps_adhoc_set_confirm_t {
*/
struct hostif_infrastructure_set_request_t {
struct hostif_hdr header;
- u16 phy_type;
- u16 cts_mode;
+ __le16 phy_type;
+ __le16 cts_mode;
struct rate_set16_t rate_set;
struct ssid_t ssid;
- u16 capability;
- u16 beacon_lost_count;
- u16 auth_type;
+ __le16 capability;
+ __le16 beacon_lost_count;
+ __le16 auth_type;
#define AUTH_TYPE_OPEN_SYSTEM 0
#define AUTH_TYPE_SHARED_KEY 1
struct channel_list_t channel_list;
- u16 scan_type;
+ __le16 scan_type;
} __packed;
/**
@@ -406,23 +406,23 @@ struct hostif_infrastructure_set_request_t {
*/
struct hostif_infrastructure_set2_request_t {
struct hostif_hdr header;
- u16 phy_type;
- u16 cts_mode;
+ __le16 phy_type;
+ __le16 cts_mode;
struct rate_set16_t rate_set;
struct ssid_t ssid;
- u16 capability;
- u16 beacon_lost_count;
- u16 auth_type;
+ __le16 capability;
+ __le16 beacon_lost_count;
+ __le16 auth_type;
#define AUTH_TYPE_OPEN_SYSTEM 0
#define AUTH_TYPE_SHARED_KEY 1
struct channel_list_t channel_list;
- u16 scan_type;
+ __le16 scan_type;
u8 bssid[ETH_ALEN];
} __packed;
struct hostif_infrastructure_set_confirm_t {
struct hostif_hdr header;
- u16 result_code;
+ __le16 result_code;
} __packed;
/**
@@ -434,13 +434,13 @@ struct hostif_infrastructure_set_confirm_t {
*/
struct hostif_adhoc_set_request_t {
struct hostif_hdr header;
- u16 phy_type;
- u16 cts_mode;
- u16 channel;
+ __le16 phy_type;
+ __le16 cts_mode;
+ __le16 channel;
struct rate_set16_t rate_set;
struct ssid_t ssid;
- u16 capability;
- u16 scan_type;
+ __le16 capability;
+ __le16 scan_type;
} __packed;
/**
@@ -452,20 +452,20 @@ struct hostif_adhoc_set_request_t {
*/
struct hostif_adhoc_set2_request_t {
struct hostif_hdr header;
- u16 phy_type;
- u16 cts_mode;
- u16 reserved;
+ __le16 phy_type;
+ __le16 cts_mode;
+ __le16 reserved;
struct rate_set16_t rate_set;
struct ssid_t ssid;
- u16 capability;
- u16 scan_type;
+ __le16 capability;
+ __le16 scan_type;
struct channel_list_t channel_list;
u8 bssid[ETH_ALEN];
} __packed;
struct hostif_adhoc_set_confirm_t {
struct hostif_hdr header;
- u16 result_code;
+ __le16 result_code;
} __packed;
struct last_associate_t {
@@ -478,10 +478,10 @@ struct association_request_t {
#define FRAME_TYPE_ASSOC_REQ 0x00
#define FRAME_TYPE_REASSOC_REQ 0x20
u8 pad;
- u16 capability;
- u16 listen_interval;
+ __le16 capability;
+ __le16 listen_interval;
u8 ap_address[6];
- u16 reqIEs_size;
+ __le16 req_ies_size;
} __packed;
struct association_response_t {
@@ -489,17 +489,17 @@ struct association_response_t {
#define FRAME_TYPE_ASSOC_RESP 0x10
#define FRAME_TYPE_REASSOC_RESP 0x30
u8 pad;
- u16 capability;
- u16 status;
- u16 association_id;
- u16 respIEs_size;
+ __le16 capability;
+ __le16 status;
+ __le16 association_id;
+ __le16 resp_ies_size;
} __packed;
struct hostif_associate_indication_t {
struct hostif_hdr header;
struct association_request_t assoc_req;
struct association_response_t assoc_resp;
- /* followed by (reqIEs_size + respIEs_size) octets of data */
+ /* followed by (req_ies_size + resp_ies_size) octets of data */
/* reqIEs data *//* respIEs data */
} __packed;
@@ -509,24 +509,24 @@ struct hostif_bss_scan_request_t {
#define ACTIVE_SCAN 0
#define PASSIVE_SCAN 1
u8 pad[3];
- u32 ch_time_min;
- u32 ch_time_max;
+ __le32 ch_time_min;
+ __le32 ch_time_max;
struct channel_list_t channel_list;
struct ssid_t ssid;
} __packed;
struct hostif_bss_scan_confirm_t {
struct hostif_hdr header;
- u16 result_code;
- u16 reserved;
+ __le16 result_code;
+ __le16 reserved;
} __packed;
struct hostif_phy_information_request_t {
struct hostif_hdr header;
- u16 type;
+ __le16 type;
#define NORMAL_TYPE 0
#define TIME_TYPE 1
- u16 time; /* unit 100ms */
+ __le16 time; /* unit 100ms */
} __packed;
struct hostif_phy_information_confirm_t {
@@ -535,10 +535,10 @@ struct hostif_phy_information_confirm_t {
u8 sq;
u8 noise;
u8 link_speed;
- u32 tx_frame;
- u32 rx_frame;
- u32 tx_error;
- u32 rx_error;
+ __le32 tx_frame;
+ __le32 rx_frame;
+ __le32 tx_error;
+ __le32 rx_error;
} __packed;
enum sleep_mode_type {
@@ -552,18 +552,18 @@ struct hostif_sleep_request_t {
struct hostif_sleep_confirm_t {
struct hostif_hdr header;
- u16 result_code;
+ __le16 result_code;
} __packed;
struct hostif_mic_failure_request_t {
struct hostif_hdr header;
- u16 failure_count;
- u16 timer;
+ __le16 failure_count;
+ __le16 timer;
} __packed;
struct hostif_mic_failure_confirm_t {
struct hostif_hdr header;
- u16 result_code;
+ __le16 result_code;
} __packed;
#define BASIC_RATE 0x80
diff --git a/drivers/staging/ks7010/ks_wlan.h b/drivers/staging/ks7010/ks_wlan.h
index cd4f56ddbea8..3767079be00d 100644
--- a/drivers/staging/ks7010/ks_wlan.h
+++ b/drivers/staging/ks7010/ks_wlan.h
@@ -264,10 +264,10 @@ struct local_aplist_t {
};
struct local_gain_t {
- u8 TxMode;
- u8 RxMode;
- u8 TxGain;
- u8 RxGain;
+ u8 tx_mode;
+ u8 rx_mode;
+ u8 tx_gain;
+ u8 rx_gain;
};
struct local_eeprom_sum_t {
diff --git a/drivers/staging/ks7010/ks_wlan_net.c b/drivers/staging/ks7010/ks_wlan_net.c
index 5a43f193dcc8..8aa12e813bd7 100644
--- a/drivers/staging/ks7010/ks_wlan_net.c
+++ b/drivers/staging/ks7010/ks_wlan_net.c
@@ -2273,7 +2273,7 @@ static int ks_wlan_set_sleep_mode(struct net_device *dev,
netdev_info(dev, "SET_SLEEP_MODE %d\n", priv->sleep_mode);
hostif_sme_enqueue(priv, SME_SLEEP_REQUEST);
} else {
- netdev_err(dev, "SET_SLEEP_MODE %d errror\n", *uwrq);
+ netdev_err(dev, "SET_SLEEP_MODE %d error\n", *uwrq);
return -EINVAL;
}
@@ -2378,14 +2378,14 @@ static int ks_wlan_set_tx_gain(struct net_device *dev,
return -EPERM;
/* for SLEEP MODE */
if (*uwrq >= 0 && *uwrq <= 0xFF) /* 0-255 */
- priv->gain.TxGain = (uint8_t)*uwrq;
+ priv->gain.tx_gain = (uint8_t)*uwrq;
else
return -EINVAL;
- if (priv->gain.TxGain < 0xFF)
- priv->gain.TxMode = 1;
+ if (priv->gain.tx_gain < 0xFF)
+ priv->gain.tx_mode = 1;
else
- priv->gain.TxMode = 0;
+ priv->gain.tx_mode = 0;
hostif_sme_enqueue(priv, SME_SET_GAIN);
return 0;
@@ -2400,7 +2400,7 @@ static int ks_wlan_get_tx_gain(struct net_device *dev,
if (priv->sleep_mode == SLP_SLEEP)
return -EPERM;
/* for SLEEP MODE */
- *uwrq = priv->gain.TxGain;
+ *uwrq = priv->gain.tx_gain;
hostif_sme_enqueue(priv, SME_GET_GAIN);
return 0;
}
@@ -2415,14 +2415,14 @@ static int ks_wlan_set_rx_gain(struct net_device *dev,
return -EPERM;
/* for SLEEP MODE */
if (*uwrq >= 0 && *uwrq <= 0xFF) /* 0-255 */
- priv->gain.RxGain = (uint8_t)*uwrq;
+ priv->gain.rx_gain = (uint8_t)*uwrq;
else
return -EINVAL;
- if (priv->gain.RxGain < 0xFF)
- priv->gain.RxMode = 1;
+ if (priv->gain.rx_gain < 0xFF)
+ priv->gain.rx_mode = 1;
else
- priv->gain.RxMode = 0;
+ priv->gain.rx_mode = 0;
hostif_sme_enqueue(priv, SME_SET_GAIN);
return 0;
@@ -2437,7 +2437,7 @@ static int ks_wlan_get_rx_gain(struct net_device *dev,
if (priv->sleep_mode == SLP_SLEEP)
return -EPERM;
/* for SLEEP MODE */
- *uwrq = priv->gain.RxGain;
+ *uwrq = priv->gain.rx_gain;
hostif_sme_enqueue(priv, SME_GET_GAIN);
return 0;
}
diff --git a/drivers/staging/lustre/lnet/klnds/o2iblnd/o2iblnd.c b/drivers/staging/lustre/lnet/klnds/o2iblnd/o2iblnd.c
index 79321e4aaf30..0520f02f670d 100644
--- a/drivers/staging/lustre/lnet/klnds/o2iblnd/o2iblnd.c
+++ b/drivers/staging/lustre/lnet/klnds/o2iblnd/o2iblnd.c
@@ -2306,7 +2306,7 @@ static int kiblnd_dev_need_failover(struct kib_dev *dev)
memset(&srcaddr, 0, sizeof(srcaddr));
srcaddr.sin_family = AF_INET;
- srcaddr.sin_addr.s_addr = (__force u32)htonl(dev->ibd_ifip);
+ srcaddr.sin_addr.s_addr = htonl(dev->ibd_ifip);
memset(&dstaddr, 0, sizeof(dstaddr));
dstaddr.sin_family = AF_INET;
@@ -2378,7 +2378,7 @@ int kiblnd_dev_failover(struct kib_dev *dev)
memset(&addr, 0, sizeof(addr));
addr.sin_family = AF_INET;
- addr.sin_addr.s_addr = (__force u32)htonl(dev->ibd_ifip);
+ addr.sin_addr.s_addr = htonl(dev->ibd_ifip);
addr.sin_port = htons(*kiblnd_tunables.kib_service);
/* Bind to failover device or port */
diff --git a/drivers/staging/lustre/lnet/klnds/o2iblnd/o2iblnd_cb.c b/drivers/staging/lustre/lnet/klnds/o2iblnd/o2iblnd_cb.c
index 0db662d6abdd..85b242ec5f9b 100644
--- a/drivers/staging/lustre/lnet/klnds/o2iblnd/o2iblnd_cb.c
+++ b/drivers/staging/lustre/lnet/klnds/o2iblnd/o2iblnd_cb.c
@@ -3267,7 +3267,7 @@ int
kiblnd_connd(void *arg)
{
spinlock_t *lock = &kiblnd_data.kib_connd_lock;
- wait_queue_t wait;
+ wait_queue_entry_t wait;
unsigned long flags;
struct kib_conn *conn;
int timeout;
@@ -3521,7 +3521,7 @@ kiblnd_scheduler(void *arg)
long id = (long)arg;
struct kib_sched_info *sched;
struct kib_conn *conn;
- wait_queue_t wait;
+ wait_queue_entry_t wait;
unsigned long flags;
struct ib_wc wc;
int did_something;
@@ -3656,7 +3656,7 @@ kiblnd_failover_thread(void *arg)
{
rwlock_t *glock = &kiblnd_data.kib_global_lock;
struct kib_dev *dev;
- wait_queue_t wait;
+ wait_queue_entry_t wait;
unsigned long flags;
int rc;
diff --git a/drivers/staging/lustre/lnet/klnds/socklnd/socklnd_cb.c b/drivers/staging/lustre/lnet/klnds/socklnd/socklnd_cb.c
index 3ed3b08c122c..6b38d5a8fe92 100644
--- a/drivers/staging/lustre/lnet/klnds/socklnd/socklnd_cb.c
+++ b/drivers/staging/lustre/lnet/klnds/socklnd/socklnd_cb.c
@@ -2166,7 +2166,7 @@ ksocknal_connd(void *arg)
{
spinlock_t *connd_lock = &ksocknal_data.ksnd_connd_lock;
struct ksock_connreq *cr;
- wait_queue_t wait;
+ wait_queue_entry_t wait;
int nloops = 0;
int cons_retry = 0;
@@ -2554,7 +2554,7 @@ ksocknal_check_peer_timeouts(int idx)
int
ksocknal_reaper(void *arg)
{
- wait_queue_t wait;
+ wait_queue_entry_t wait;
struct ksock_conn *conn;
struct ksock_sched *sched;
struct list_head enomem_conns;
diff --git a/drivers/staging/lustre/lnet/libcfs/debug.c b/drivers/staging/lustre/lnet/libcfs/debug.c
index c56e9922cd5b..49deb448b044 100644
--- a/drivers/staging/lustre/lnet/libcfs/debug.c
+++ b/drivers/staging/lustre/lnet/libcfs/debug.c
@@ -361,7 +361,7 @@ static int libcfs_debug_dumplog_thread(void *arg)
void libcfs_debug_dumplog(void)
{
- wait_queue_t wait;
+ wait_queue_entry_t wait;
struct task_struct *dumper;
/* we're being careful to ensure that the kernel thread is
diff --git a/drivers/staging/lustre/lnet/libcfs/linux/linux-tracefile.c b/drivers/staging/lustre/lnet/libcfs/linux/linux-tracefile.c
index 75eb84e7f0f8..a5a94788f11f 100644
--- a/drivers/staging/lustre/lnet/libcfs/linux/linux-tracefile.c
+++ b/drivers/staging/lustre/lnet/libcfs/linux/linux-tracefile.c
@@ -57,8 +57,9 @@ int cfs_tracefile_init_arch(void)
memset(cfs_trace_data, 0, sizeof(cfs_trace_data));
for (i = 0; i < CFS_TCD_TYPE_MAX; i++) {
cfs_trace_data[i] =
- kmalloc(sizeof(union cfs_trace_data_union) *
- num_possible_cpus(), GFP_KERNEL);
+ kmalloc_array(num_possible_cpus(),
+ sizeof(union cfs_trace_data_union),
+ GFP_KERNEL);
if (!cfs_trace_data[i])
goto out;
}
diff --git a/drivers/staging/lustre/lnet/libcfs/tracefile.c b/drivers/staging/lustre/lnet/libcfs/tracefile.c
index 9599b7441feb..d1aa79bb2017 100644
--- a/drivers/staging/lustre/lnet/libcfs/tracefile.c
+++ b/drivers/staging/lustre/lnet/libcfs/tracefile.c
@@ -191,10 +191,9 @@ cfs_trace_get_tage_try(struct cfs_trace_cpu_data *tcd, unsigned long len)
} else {
tage = cfs_tage_alloc(GFP_ATOMIC);
if (unlikely(!tage)) {
- if ((!memory_pressure_get() ||
- in_interrupt()) && printk_ratelimit())
- pr_warn("cannot allocate a tage (%ld)\n",
- tcd->tcd_cur_pages);
+ if (!memory_pressure_get() || in_interrupt())
+ pr_warn_ratelimited("cannot allocate a tage (%ld)\n",
+ tcd->tcd_cur_pages);
return NULL;
}
}
@@ -229,9 +228,8 @@ static void cfs_tcd_shrink(struct cfs_trace_cpu_data *tcd)
* from here: this will lead to infinite recursion.
*/
- if (printk_ratelimit())
- pr_warn("debug daemon buffer overflowed; discarding 10%% of pages (%d of %ld)\n",
- pgcount + 1, tcd->tcd_cur_pages);
+ pr_warn_ratelimited("debug daemon buffer overflowed; discarding 10%% of pages (%d of %ld)\n",
+ pgcount + 1, tcd->tcd_cur_pages);
INIT_LIST_HEAD(&pc.pc_pages);
@@ -990,7 +988,7 @@ static int tracefiled(void *arg)
complete(&tctl->tctl_start);
while (1) {
- wait_queue_t __wait;
+ wait_queue_entry_t __wait;
pc.pc_want_daemon_pages = 0;
collect_pages(&pc);
diff --git a/drivers/staging/lustre/lnet/lnet/lib-eq.c b/drivers/staging/lustre/lnet/lnet/lib-eq.c
index ce4b83584e17..9ebba4ef5f90 100644
--- a/drivers/staging/lustre/lnet/lnet/lib-eq.c
+++ b/drivers/staging/lustre/lnet/lnet/lib-eq.c
@@ -312,7 +312,7 @@ __must_hold(&the_lnet.ln_eq_wait_lock)
{
int tms = *timeout_ms;
int wait;
- wait_queue_t wl;
+ wait_queue_entry_t wl;
unsigned long now;
if (!tms)
diff --git a/drivers/staging/lustre/lnet/lnet/lib-move.c b/drivers/staging/lustre/lnet/lnet/lib-move.c
index a99c5c0aa672..20ebe247071f 100644
--- a/drivers/staging/lustre/lnet/lnet/lib-move.c
+++ b/drivers/staging/lustre/lnet/lnet/lib-move.c
@@ -1274,9 +1274,9 @@ lnet_parse_put(struct lnet_ni *ni, struct lnet_msg *msg)
int rc;
/* Convert put fields to host byte order */
- hdr->msg.put.match_bits = le64_to_cpu(hdr->msg.put.match_bits);
- hdr->msg.put.ptl_index = le32_to_cpu(hdr->msg.put.ptl_index);
- hdr->msg.put.offset = le32_to_cpu(hdr->msg.put.offset);
+ le64_to_cpus(&hdr->msg.put.match_bits);
+ le32_to_cpus(&hdr->msg.put.ptl_index);
+ le32_to_cpus(&hdr->msg.put.offset);
info.mi_id.nid = hdr->src_nid;
info.mi_id.pid = hdr->src_pid;
@@ -1332,10 +1332,10 @@ lnet_parse_get(struct lnet_ni *ni, struct lnet_msg *msg, int rdma_get)
int rc;
/* Convert get fields to host byte order */
- hdr->msg.get.match_bits = le64_to_cpu(hdr->msg.get.match_bits);
- hdr->msg.get.ptl_index = le32_to_cpu(hdr->msg.get.ptl_index);
- hdr->msg.get.sink_length = le32_to_cpu(hdr->msg.get.sink_length);
- hdr->msg.get.src_offset = le32_to_cpu(hdr->msg.get.src_offset);
+ le64_to_cpus(&hdr->msg.get.match_bits);
+ le32_to_cpus(&hdr->msg.get.ptl_index);
+ le32_to_cpus(&hdr->msg.get.sink_length);
+ le32_to_cpus(&hdr->msg.get.src_offset);
info.mi_id.nid = hdr->src_nid;
info.mi_id.pid = hdr->src_pid;
@@ -1464,8 +1464,8 @@ lnet_parse_ack(struct lnet_ni *ni, struct lnet_msg *msg)
src.pid = hdr->src_pid;
/* Convert ack fields to host byte order */
- hdr->msg.ack.match_bits = le64_to_cpu(hdr->msg.ack.match_bits);
- hdr->msg.ack.mlength = le32_to_cpu(hdr->msg.ack.mlength);
+ le64_to_cpus(&hdr->msg.ack.match_bits);
+ le32_to_cpus(&hdr->msg.ack.mlength);
cpt = lnet_cpt_of_cookie(hdr->msg.ack.dst_wmd.wh_object_cookie);
lnet_res_lock(cpt);
@@ -1798,7 +1798,7 @@ lnet_parse(struct lnet_ni *ni, struct lnet_hdr *hdr, lnet_nid_t from_nid,
/* convert common msg->hdr fields to host byteorder */
msg->msg_hdr.type = type;
msg->msg_hdr.src_nid = src_nid;
- msg->msg_hdr.src_pid = le32_to_cpu(msg->msg_hdr.src_pid);
+ le32_to_cpus(&msg->msg_hdr.src_pid);
msg->msg_hdr.dest_nid = dest_nid;
msg->msg_hdr.dest_pid = dest_pid;
msg->msg_hdr.payload_length = payload_length;
diff --git a/drivers/staging/lustre/lnet/lnet/lib-socket.c b/drivers/staging/lustre/lnet/lnet/lib-socket.c
index 9fca8d225ee0..800f4f6c6593 100644
--- a/drivers/staging/lustre/lnet/lnet/lib-socket.c
+++ b/drivers/staging/lustre/lnet/lnet/lib-socket.c
@@ -89,7 +89,7 @@ lnet_ipif_query(char *name, int *up, __u32 *ip, __u32 *mask)
struct ifreq ifr;
int nob;
int rc;
- __u32 val;
+ __be32 val;
nob = strnlen(name, IFNAMSIZ);
if (nob == IFNAMSIZ) {
@@ -516,7 +516,7 @@ lnet_sock_listen(struct socket **sockp, __u32 local_ip, int local_port,
int
lnet_sock_accept(struct socket **newsockp, struct socket *sock)
{
- wait_queue_t wait;
+ wait_queue_entry_t wait;
struct socket *newsock;
int rc;
diff --git a/drivers/staging/lustre/lustre/fid/fid_request.c b/drivers/staging/lustre/lustre/fid/fid_request.c
index 999f250ceed0..19895faf7626 100644
--- a/drivers/staging/lustre/lustre/fid/fid_request.c
+++ b/drivers/staging/lustre/lustre/fid/fid_request.c
@@ -192,7 +192,7 @@ static int seq_client_alloc_seq(const struct lu_env *env,
}
static int seq_fid_alloc_prep(struct lu_client_seq *seq,
- wait_queue_t *link)
+ wait_queue_entry_t *link)
{
if (seq->lcs_update) {
add_wait_queue(&seq->lcs_waitq, link);
@@ -223,7 +223,7 @@ static void seq_fid_alloc_fini(struct lu_client_seq *seq)
int seq_client_alloc_fid(const struct lu_env *env,
struct lu_client_seq *seq, struct lu_fid *fid)
{
- wait_queue_t link;
+ wait_queue_entry_t link;
int rc;
LASSERT(seq);
@@ -259,7 +259,7 @@ int seq_client_alloc_fid(const struct lu_env *env,
return rc;
}
- CDEBUG(D_INFO, "%s: Switch to sequence [0x%16.16Lx]\n",
+ CDEBUG(D_INFO, "%s: Switch to sequence [0x%16.16llx]\n",
seq->lcs_name, seqnr);
seq->lcs_fid.f_oid = LUSTRE_FID_INIT_OID;
@@ -279,7 +279,7 @@ int seq_client_alloc_fid(const struct lu_env *env,
*fid = seq->lcs_fid;
mutex_unlock(&seq->lcs_mutex);
- CDEBUG(D_INFO, "%s: Allocated FID "DFID"\n", seq->lcs_name, PFID(fid));
+ CDEBUG(D_INFO, "%s: Allocated FID " DFID "\n", seq->lcs_name, PFID(fid));
return rc;
}
EXPORT_SYMBOL(seq_client_alloc_fid);
@@ -290,7 +290,7 @@ EXPORT_SYMBOL(seq_client_alloc_fid);
*/
void seq_client_flush(struct lu_client_seq *seq)
{
- wait_queue_t link;
+ wait_queue_entry_t link;
LASSERT(seq);
init_waitqueue_entry(&link, current);
diff --git a/drivers/staging/lustre/lustre/fld/fld_cache.c b/drivers/staging/lustre/lustre/fld/fld_cache.c
index 11f697496180..b852fed0b10f 100644
--- a/drivers/staging/lustre/lustre/fld/fld_cache.c
+++ b/drivers/staging/lustre/lustre/fld/fld_cache.c
@@ -151,7 +151,7 @@ restart_fixup:
continue;
LASSERTF(c_range->lsr_start <= n_range->lsr_start,
- "cur lsr_start "DRANGE" next lsr_start "DRANGE"\n",
+ "cur lsr_start " DRANGE " next lsr_start " DRANGE "\n",
PRANGE(c_range), PRANGE(n_range));
/* check merge possibility with next range */
@@ -349,7 +349,7 @@ static void fld_cache_overlap_handle(struct fld_cache *cache,
f_curr->fce_range.lsr_end = new_start;
fld_cache_entry_add(cache, f_new, &f_curr->fce_list);
} else
- CERROR("NEW range ="DRANGE" curr = "DRANGE"\n",
+ CERROR("NEW range =" DRANGE " curr = " DRANGE "\n",
PRANGE(range), PRANGE(&f_curr->fce_range));
}
@@ -415,7 +415,7 @@ static int fld_cache_insert_nolock(struct fld_cache *cache,
if (!prev)
prev = head;
- CDEBUG(D_INFO, "insert range "DRANGE"\n", PRANGE(&f_new->fce_range));
+ CDEBUG(D_INFO, "insert range " DRANGE "\n", PRANGE(&f_new->fce_range));
/* Add new entry to cache and lru list. */
fld_cache_entry_add(cache, f_new, prev);
out:
diff --git a/drivers/staging/lustre/lustre/fld/lproc_fld.c b/drivers/staging/lustre/lustre/fld/lproc_fld.c
index 61ac420798af..b83d7ebb2d18 100644
--- a/drivers/staging/lustre/lustre/fld/lproc_fld.c
+++ b/drivers/staging/lustre/lustre/fld/lproc_fld.c
@@ -136,7 +136,7 @@ fld_debugfs_cache_flush_release(struct inode *inode, struct file *file)
return 0;
}
-static struct file_operations fld_debugfs_cache_flush_fops = {
+static const struct file_operations fld_debugfs_cache_flush_fops = {
.owner = THIS_MODULE,
.open = simple_open,
.write = fld_debugfs_cache_flush_write,
diff --git a/drivers/staging/lustre/lustre/include/cl_object.h b/drivers/staging/lustre/lustre/include/cl_object.h
index 2bc3ee51b069..90a0c501e1ea 100644
--- a/drivers/staging/lustre/lustre/include/cl_object.h
+++ b/drivers/staging/lustre/lustre/include/cl_object.h
@@ -1287,7 +1287,7 @@ do { \
* @{
*/
struct cl_page_list {
- unsigned pl_nr;
+ unsigned int pl_nr;
struct list_head pl_pages;
struct task_struct *pl_owner;
};
@@ -1842,7 +1842,7 @@ struct cl_io {
/**
* Number of pages owned by this IO. For invariant checking.
*/
- unsigned ci_owned_nr;
+ unsigned int ci_owned_nr;
};
/** @} cl_io */
diff --git a/drivers/staging/lustre/lustre/include/lprocfs_status.h b/drivers/staging/lustre/lustre/include/lprocfs_status.h
index 242abb881766..915283c04094 100644
--- a/drivers/staging/lustre/lustre/include/lprocfs_status.h
+++ b/drivers/staging/lustre/lustre/include/lprocfs_status.h
@@ -49,7 +49,7 @@
struct lprocfs_vars {
const char *name;
- struct file_operations *fops;
+ const struct file_operations *fops;
void *data;
/**
* sysfs file mode.
@@ -449,7 +449,7 @@ int lprocfs_exp_cleanup(struct obd_export *exp);
struct dentry *ldebugfs_add_simple(struct dentry *root,
char *name,
void *data,
- struct file_operations *fops);
+ const struct file_operations *fops);
int ldebugfs_register_stats(struct dentry *parent,
const char *name,
@@ -523,8 +523,8 @@ unsigned long lprocfs_oh_sum(struct obd_histogram *oh);
void lprocfs_stats_collect(struct lprocfs_stats *stats, int idx,
struct lprocfs_counter *cnt);
-int lprocfs_single_release(struct inode *, struct file *);
-int lprocfs_seq_release(struct inode *, struct file *);
+int lprocfs_single_release(struct inode *inode, struct file *file);
+int lprocfs_seq_release(struct inode *inode, struct file *file);
/* write the name##_seq_show function, call LPROC_SEQ_FOPS_RO for read-only
* proc entries; otherwise, you will define name##_seq_write function also for
@@ -536,7 +536,7 @@ static int name##_single_open(struct inode *inode, struct file *file) \
{ \
return single_open(file, name##_seq_show, inode->i_private); \
} \
-static struct file_operations name##_fops = { \
+static const struct file_operations name##_fops = { \
.owner = THIS_MODULE, \
.open = name##_single_open, \
.read = seq_read, \
@@ -581,7 +581,7 @@ static struct file_operations name##_fops = { \
{ \
return single_open(file, NULL, inode->i_private); \
} \
- static struct file_operations name##_##type##_fops = { \
+ static const struct file_operations name##_##type##_fops = { \
.open = name##_##type##_open, \
.write = name##_##type##_write, \
.release = lprocfs_single_release, \
diff --git a/drivers/staging/lustre/lustre/include/lu_object.h b/drivers/staging/lustre/lustre/include/lu_object.h
index 73ecc232967b..2e70602dc2e2 100644
--- a/drivers/staging/lustre/lustre/include/lu_object.h
+++ b/drivers/staging/lustre/lustre/include/lu_object.h
@@ -968,11 +968,11 @@ struct lu_context {
* Version counter used to skip calls to lu_context_refill() when no
* keys were registered.
*/
- unsigned lc_version;
+ unsigned int lc_version;
/**
* Debugging cookie.
*/
- unsigned lc_cookie;
+ unsigned int lc_cookie;
};
/**
diff --git a/drivers/staging/lustre/lustre/include/lustre/lustre_idl.h b/drivers/staging/lustre/lustre/include/lustre/lustre_idl.h
index df48b8d6fe52..77995fa47691 100644
--- a/drivers/staging/lustre/lustre/include/lustre/lustre_idl.h
+++ b/drivers/staging/lustre/lustre/include/lustre/lustre_idl.h
@@ -546,7 +546,7 @@ static inline void ostid_set_id(struct ost_id *oi, __u64 oid)
static inline int fid_set_id(struct lu_fid *fid, __u64 oid)
{
if (unlikely(fid_seq_is_igif(fid->f_seq))) {
- CERROR("bad IGIF, "DFID"\n", PFID(fid));
+ CERROR("bad IGIF, " DFID "\n", PFID(fid));
return -EBADF;
}
@@ -585,7 +585,7 @@ static inline int ostid_to_fid(struct lu_fid *fid, struct ost_id *ostid,
__u64 seq = ostid_seq(ostid);
if (ost_idx > 0xffff) {
- CERROR("bad ost_idx, "DOSTID" ost_idx:%u\n", POSTID(ostid),
+ CERROR("bad ost_idx, " DOSTID " ost_idx:%u\n", POSTID(ostid),
ost_idx);
return -EBADF;
}
@@ -630,7 +630,7 @@ static inline int ostid_to_fid(struct lu_fid *fid, struct ost_id *ostid,
static inline int fid_to_ostid(const struct lu_fid *fid, struct ost_id *ostid)
{
if (unlikely(fid_seq_is_igif(fid->f_seq))) {
- CERROR("bad IGIF, "DFID"\n", PFID(fid));
+ CERROR("bad IGIF, " DFID "\n", PFID(fid));
return -EBADF;
}
diff --git a/drivers/staging/lustre/lustre/include/lustre/lustre_user.h b/drivers/staging/lustre/lustre/include/lustre/lustre_user.h
index 7d8628ce0d3b..edff8dc34430 100644
--- a/drivers/staging/lustre/lustre/include/lustre/lustre_user.h
+++ b/drivers/staging/lustre/lustre/include/lustre/lustre_user.h
@@ -532,7 +532,7 @@ static inline void obd_uuid2fsname(char *buf, char *uuid, int buflen)
#define FID_NOBRACE_LEN 40
#define FID_LEN (FID_NOBRACE_LEN + 2)
#define DFID_NOBRACE "%#llx:0x%x:0x%x"
-#define DFID "["DFID_NOBRACE"]"
+#define DFID "[" DFID_NOBRACE "]"
#define PFID(fid) (unsigned long long)(fid)->f_seq, (fid)->f_oid, (fid)->f_ver
/* scanf input parse format for fids in DFID_NOBRACE format
diff --git a/drivers/staging/lustre/lustre/include/lustre_fid.h b/drivers/staging/lustre/lustre/include/lustre_fid.h
index b5a1aadbcb93..6dc24a76ddb6 100644
--- a/drivers/staging/lustre/lustre/include/lustre_fid.h
+++ b/drivers/staging/lustre/lustre/include/lustre_fid.h
@@ -606,7 +606,7 @@ static inline __u32 fid_flatten32(const struct lu_fid *fid)
static inline int lu_fid_diff(const struct lu_fid *fid1,
const struct lu_fid *fid2)
{
- LASSERTF(fid_seq(fid1) == fid_seq(fid2), "fid1:"DFID", fid2:"DFID"\n",
+ LASSERTF(fid_seq(fid1) == fid_seq(fid2), "fid1:" DFID ", fid2:" DFID "\n",
PFID(fid1), PFID(fid2));
if (fid_is_idif(fid1) && fid_is_idif(fid2))
diff --git a/drivers/staging/lustre/lustre/include/lustre_lib.h b/drivers/staging/lustre/lustre/include/lustre_lib.h
index b04d613846ee..f24970da8323 100644
--- a/drivers/staging/lustre/lustre/include/lustre_lib.h
+++ b/drivers/staging/lustre/lustre/include/lustre_lib.h
@@ -201,7 +201,7 @@ struct l_wait_info {
sigmask(SIGALRM))
/**
- * wait_queue_t of Linux (version < 2.6.34) is a FIFO list for exclusively
+ * wait_queue_entry_t of Linux (version < 2.6.34) is a FIFO list for exclusively
* waiting threads, which is not always desirable because all threads will
* be waken up again and again, even user only needs a few of them to be
* active most time. This is not good for performance because cache can
@@ -228,7 +228,7 @@ struct l_wait_info {
*/
#define __l_wait_event(wq, condition, info, ret, l_add_wait) \
do { \
- wait_queue_t __wait; \
+ wait_queue_entry_t __wait; \
long __timeout = info->lwi_timeout; \
sigset_t __blocked; \
int __allow_intr = info->lwi_allow_intr; \
diff --git a/drivers/staging/lustre/lustre/ldlm/ldlm_internal.h b/drivers/staging/lustre/lustre/ldlm/ldlm_internal.h
index 5d24b4825796..ec3b23cd09ec 100644
--- a/drivers/staging/lustre/lustre/ldlm/ldlm_internal.h
+++ b/drivers/staging/lustre/lustre/ldlm/ldlm_internal.h
@@ -79,11 +79,11 @@ static inline int ldlm_ns_empty(struct ldlm_namespace *ns)
return atomic_read(&ns->ns_bref) == 0;
}
-void ldlm_namespace_move_to_active_locked(struct ldlm_namespace *,
- enum ldlm_side);
-void ldlm_namespace_move_to_inactive_locked(struct ldlm_namespace *,
- enum ldlm_side);
-struct ldlm_namespace *ldlm_namespace_first_locked(enum ldlm_side);
+void ldlm_namespace_move_to_active_locked(struct ldlm_namespace *ns,
+ enum ldlm_side client);
+void ldlm_namespace_move_to_inactive_locked(struct ldlm_namespace *ns,
+ enum ldlm_side client);
+struct ldlm_namespace *ldlm_namespace_first_locked(enum ldlm_side client);
/* ldlm_request.c */
/* Cancel lru flag, it indicates we cancel aged locks. */
@@ -130,16 +130,19 @@ void ldlm_grant_lock(struct ldlm_lock *lock, struct list_head *work_list);
int ldlm_fill_lvb(struct ldlm_lock *lock, struct req_capsule *pill,
enum req_location loc, void *data, int size);
struct ldlm_lock *
-ldlm_lock_create(struct ldlm_namespace *ns, const struct ldlm_res_id *,
+ldlm_lock_create(struct ldlm_namespace *ns, const struct ldlm_res_id *id,
enum ldlm_type type, enum ldlm_mode mode,
const struct ldlm_callback_suite *cbs,
void *data, __u32 lvb_len, enum lvb_type lvb_type);
-enum ldlm_error ldlm_lock_enqueue(struct ldlm_namespace *, struct ldlm_lock **,
- void *cookie, __u64 *flags);
-void ldlm_lock_addref_internal(struct ldlm_lock *, enum ldlm_mode mode);
-void ldlm_lock_addref_internal_nolock(struct ldlm_lock *, enum ldlm_mode mode);
-void ldlm_lock_decref_internal(struct ldlm_lock *, enum ldlm_mode mode);
-void ldlm_lock_decref_internal_nolock(struct ldlm_lock *, enum ldlm_mode mode);
+enum ldlm_error ldlm_lock_enqueue(struct ldlm_namespace *ns,
+ struct ldlm_lock **lock, void *cookie,
+ __u64 *flags);
+void ldlm_lock_addref_internal(struct ldlm_lock *lock, enum ldlm_mode mode);
+void ldlm_lock_addref_internal_nolock(struct ldlm_lock *lock,
+ enum ldlm_mode mode);
+void ldlm_lock_decref_internal(struct ldlm_lock *lock, enum ldlm_mode mode);
+void ldlm_lock_decref_internal_nolock(struct ldlm_lock *lock,
+ enum ldlm_mode mode);
int ldlm_run_ast_work(struct ldlm_namespace *ns, struct list_head *rpc_list,
enum ldlm_desc_ast_t ast_type);
int ldlm_lock_remove_from_lru_check(struct ldlm_lock *lock, time_t last_use);
diff --git a/drivers/staging/lustre/lustre/ldlm/ldlm_lib.c b/drivers/staging/lustre/lustre/ldlm/ldlm_lib.c
index 3663c5cdb051..4dc7baee1f28 100644
--- a/drivers/staging/lustre/lustre/ldlm/ldlm_lib.c
+++ b/drivers/staging/lustre/lustre/ldlm/ldlm_lib.c
@@ -363,17 +363,16 @@ int client_obd_setup(struct obd_device *obddev, struct lustre_cfg *lcfg)
*/
cli->cl_chunkbits = PAGE_SHIFT;
- if (!strcmp(name, LUSTRE_MDC_NAME)) {
+ if (!strcmp(name, LUSTRE_MDC_NAME))
cli->cl_max_rpcs_in_flight = OBD_MAX_RIF_DEFAULT;
- } else if (totalram_pages >> (20 - PAGE_SHIFT) <= 128 /* MB */) {
+ else if (totalram_pages >> (20 - PAGE_SHIFT) <= 128 /* MB */)
cli->cl_max_rpcs_in_flight = 2;
- } else if (totalram_pages >> (20 - PAGE_SHIFT) <= 256 /* MB */) {
+ else if (totalram_pages >> (20 - PAGE_SHIFT) <= 256 /* MB */)
cli->cl_max_rpcs_in_flight = 3;
- } else if (totalram_pages >> (20 - PAGE_SHIFT) <= 512 /* MB */) {
+ else if (totalram_pages >> (20 - PAGE_SHIFT) <= 512 /* MB */)
cli->cl_max_rpcs_in_flight = 4;
- } else {
+ else
cli->cl_max_rpcs_in_flight = OBD_MAX_RIF_DEFAULT;
- }
spin_lock_init(&cli->cl_mod_rpcs_lock);
spin_lock_init(&cli->cl_mod_rpcs_hist.oh_lock);
diff --git a/drivers/staging/lustre/lustre/ldlm/ldlm_request.c b/drivers/staging/lustre/lustre/ldlm/ldlm_request.c
index 84eeaa552113..4028e11249a2 100644
--- a/drivers/staging/lustre/lustre/ldlm/ldlm_request.c
+++ b/drivers/staging/lustre/lustre/ldlm/ldlm_request.c
@@ -445,8 +445,8 @@ int ldlm_cli_enqueue_fini(struct obd_export *exp, struct ptlrpc_request *req,
if (!ldlm_res_eq(&reply->lock_desc.l_resource.lr_name,
&lock->l_resource->lr_name)) {
- CDEBUG(D_INFO, "remote intent success, locking "DLDLMRES
- " instead of "DLDLMRES"\n",
+ CDEBUG(D_INFO, "remote intent success, locking " DLDLMRES
+ " instead of " DLDLMRES "\n",
PLDLMRES(&reply->lock_desc.l_resource),
PLDLMRES(lock->l_resource));
@@ -1677,7 +1677,7 @@ int ldlm_cli_cancel_unused_resource(struct ldlm_namespace *ns,
0, flags | LCF_BL_AST, opaque);
rc = ldlm_cli_cancel_list(&cancels, count, NULL, flags);
if (rc != ELDLM_OK)
- CERROR("canceling unused lock "DLDLMRES": rc = %d\n",
+ CERROR("canceling unused lock " DLDLMRES ": rc = %d\n",
PLDLMRES(res), rc);
LDLM_RESOURCE_DELREF(res);
diff --git a/drivers/staging/lustre/lustre/ldlm/ldlm_resource.c b/drivers/staging/lustre/lustre/ldlm/ldlm_resource.c
index 633f65b078eb..c9ef247d9be4 100644
--- a/drivers/staging/lustre/lustre/ldlm/ldlm_resource.c
+++ b/drivers/staging/lustre/lustre/ldlm/ldlm_resource.c
@@ -78,7 +78,25 @@ lprocfs_wr_dump_ns(struct file *file, const char __user *buffer,
LPROC_SEQ_FOPS_WR_ONLY(ldlm, dump_ns);
-LPROC_SEQ_FOPS_RW_TYPE(ldlm_rw, uint);
+static int ldlm_rw_uint_seq_show(struct seq_file *m, void *v)
+{
+ seq_printf(m, "%u\n", *(unsigned int *)m->private);
+ return 0;
+}
+
+static ssize_t
+ldlm_rw_uint_seq_write(struct file *file, const char __user *buffer,
+ size_t count, loff_t *off)
+{
+ struct seq_file *seq = file->private_data;
+
+ if (count == 0)
+ return 0;
+ return kstrtouint_from_user(buffer, count, 0,
+ (unsigned int *)seq->private);
+}
+
+LPROC_SEQ_FOPS(ldlm_rw_uint);
static struct lprocfs_vars ldlm_debugfs_list[] = {
{ "dump_namespaces", &ldlm_dump_ns_fops, NULL, 0222 },
@@ -831,7 +849,7 @@ static int ldlm_resource_complain(struct cfs_hash *hs, struct cfs_hash_bd *bd,
struct ldlm_resource *res = cfs_hash_object(hs, hnode);
lock_res(res);
- CERROR("%s: namespace resource "DLDLMRES
+ CERROR("%s: namespace resource " DLDLMRES
" (%p) refcount nonzero (%d) after lock cleanup; forcing cleanup.\n",
ldlm_ns_name(ldlm_res_to_ns(res)), PLDLMRES(res), res,
atomic_read(&res->lr_refcount) - 1);
@@ -1373,7 +1391,7 @@ void ldlm_resource_dump(int level, struct ldlm_resource *res)
if (!((libcfs_debug | D_ERROR) & level))
return;
- CDEBUG(level, "--- Resource: "DLDLMRES" (%p) refcount = %d\n",
+ CDEBUG(level, "--- Resource: " DLDLMRES " (%p) refcount = %d\n",
PLDLMRES(res), res, atomic_read(&res->lr_refcount));
if (!list_empty(&res->lr_granted)) {
diff --git a/drivers/staging/lustre/lustre/llite/dcache.c b/drivers/staging/lustre/lustre/llite/dcache.c
index 38f84662cf02..d20425fb8cbe 100644
--- a/drivers/staging/lustre/lustre/llite/dcache.c
+++ b/drivers/staging/lustre/lustre/llite/dcache.c
@@ -180,7 +180,7 @@ void ll_invalidate_aliases(struct inode *inode)
{
struct dentry *dentry;
- CDEBUG(D_INODE, "marking dentries for ino "DFID"(%p) invalid\n",
+ CDEBUG(D_INODE, "marking dentries for ino " DFID "(%p) invalid\n",
PFID(ll_inode2fid(inode)), inode);
spin_lock(&inode->i_lock);
@@ -216,7 +216,7 @@ void ll_lookup_finish_locks(struct lookup_intent *it, struct inode *inode)
if (it->it_lock_mode && inode) {
struct ll_sb_info *sbi = ll_i2sbi(inode);
- CDEBUG(D_DLMTRACE, "setting l_data to inode "DFID"(%p)\n",
+ CDEBUG(D_DLMTRACE, "setting l_data to inode " DFID "(%p)\n",
PFID(ll_inode2fid(inode)), inode);
ll_set_lock_data(sbi->ll_md_exp, inode, it, NULL);
}
diff --git a/drivers/staging/lustre/lustre/llite/dir.c b/drivers/staging/lustre/lustre/llite/dir.c
index 13b35922a4ca..03a72c07f57c 100644
--- a/drivers/staging/lustre/lustre/llite/dir.c
+++ b/drivers/staging/lustre/lustre/llite/dir.c
@@ -303,7 +303,7 @@ static int ll_readdir(struct file *filp, struct dir_context *ctx)
struct md_op_data *op_data;
int rc;
- CDEBUG(D_VFSTRACE, "VFS Op:inode="DFID"(%p) pos/size %lu/%llu 32bit_api %d\n",
+ CDEBUG(D_VFSTRACE, "VFS Op:inode=" DFID "(%p) pos/size %lu/%llu 32bit_api %d\n",
PFID(ll_inode2fid(inode)), inode, (unsigned long)pos,
i_size_read(inode), api32);
@@ -419,7 +419,7 @@ static int ll_dir_setdirstripe(struct inode *parent, struct lmv_user_md *lump,
if (unlikely(lump->lum_magic != LMV_USER_MAGIC))
return -EINVAL;
- CDEBUG(D_VFSTRACE, "VFS Op:inode="DFID"(%p) name %s stripe_offset %d, stripe_count: %u\n",
+ CDEBUG(D_VFSTRACE, "VFS Op:inode=" DFID "(%p) name %s stripe_offset %d, stripe_count: %u\n",
PFID(ll_inode2fid(parent)), parent, dirname,
(int)lump->lum_stripe_offset, lump->lum_stripe_count);
@@ -606,7 +606,7 @@ int ll_dir_getstripe(struct inode *inode, void **plmm, int *plmm_size,
rc = md_getattr(sbi->ll_md_exp, op_data, &req);
ll_finish_md_op_data(op_data);
if (rc < 0) {
- CDEBUG(D_INFO, "md_getattr failed on inode "DFID": rc %d\n",
+ CDEBUG(D_INFO, "md_getattr failed on inode " DFID ": rc %d\n",
PFID(ll_inode2fid(inode)), rc);
goto out;
}
@@ -733,7 +733,7 @@ static int ll_ioc_copy_start(struct super_block *sb, struct hsm_copy *copy)
iput(inode);
if (rc != 0) {
CDEBUG(D_HSM, "Could not read file data version of "
- DFID" (rc = %d). Archive request (%#llx) could not be done.\n",
+ DFID " (rc = %d). Archive request (%#llx) could not be done.\n",
PFID(&copy->hc_hai.hai_fid), rc,
copy->hc_hai.hai_cookie);
hpk.hpk_flags |= HP_FLAG_RETRY;
@@ -833,7 +833,7 @@ static int ll_ioc_copy_end(struct super_block *sb, struct hsm_copy *copy)
if ((copy->hc_hai.hai_action == HSMA_ARCHIVE) &&
(copy->hc_data_version != data_version)) {
CDEBUG(D_HSM, "File data version mismatched. File content was changed during archiving. "
- DFID", start:%#llx current:%#llx\n",
+ DFID ", start:%#llx current:%#llx\n",
PFID(&copy->hc_hai.hai_fid),
copy->hc_data_version, data_version);
/* File was changed, send error to cdt. Do not ask for
@@ -1037,7 +1037,7 @@ static long ll_dir_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
struct obd_ioctl_data *data;
int rc = 0;
- CDEBUG(D_VFSTRACE, "VFS Op:inode="DFID"(%p), cmd=%#x\n",
+ CDEBUG(D_VFSTRACE, "VFS Op:inode=" DFID "(%p), cmd=%#x\n",
PFID(ll_inode2fid(inode)), inode, cmd);
/* asm-ppc{,64} declares TCGETS, et. al. as type 't' not 'T' */
@@ -1141,7 +1141,7 @@ out_free:
}
#if OBD_OCD_VERSION(2, 9, 50, 0) > LUSTRE_VERSION_CODE
- mode = data->ioc_type != 0 ? data->ioc_type : S_IRWXUGO;
+ mode = data->ioc_type != 0 ? data->ioc_type : 0777;
#else
mode = data->ioc_type;
#endif
diff --git a/drivers/staging/lustre/lustre/llite/file.c b/drivers/staging/lustre/lustre/llite/file.c
index 67c4b9cc6e75..ab1c85c1ed38 100644
--- a/drivers/staging/lustre/lustre/llite/file.c
+++ b/drivers/staging/lustre/lustre/llite/file.c
@@ -316,7 +316,7 @@ int ll_file_release(struct inode *inode, struct file *file)
struct ll_inode_info *lli = ll_i2info(inode);
int rc;
- CDEBUG(D_VFSTRACE, "VFS Op:inode="DFID"(%p)\n",
+ CDEBUG(D_VFSTRACE, "VFS Op:inode=" DFID "(%p)\n",
PFID(ll_inode2fid(inode)), inode);
if (!is_root_inode(inode))
@@ -494,7 +494,7 @@ int ll_file_open(struct inode *inode, struct file *file)
struct ll_file_data *fd;
int rc = 0;
- CDEBUG(D_VFSTRACE, "VFS Op:inode="DFID"(%p), flags %o\n",
+ CDEBUG(D_VFSTRACE, "VFS Op:inode=" DFID "(%p), flags %o\n",
PFID(ll_inode2fid(inode)), inode, file->f_flags);
it = file->private_data; /* XXX: compat macro */
@@ -834,7 +834,7 @@ out_close:
}
rc2 = ll_close_inode_openhandle(inode, och, 0, NULL);
if (rc2 < 0)
- CERROR("%s: error closing file "DFID": %d\n",
+ CERROR("%s: error closing file " DFID ": %d\n",
ll_get_fsname(inode->i_sb, NULL, 0),
PFID(&ll_i2info(inode)->lli_fid), rc2);
och = NULL; /* och has been freed in ll_close_inode_openhandle() */
@@ -1665,7 +1665,7 @@ int ll_hsm_release(struct inode *inode)
int rc;
u16 refcheck;
- CDEBUG(D_INODE, "%s: Releasing file "DFID".\n",
+ CDEBUG(D_INODE, "%s: Releasing file " DFID ".\n",
ll_get_fsname(inode->i_sb, NULL, 0),
PFID(&ll_i2info(inode)->lli_fid));
@@ -1928,7 +1928,7 @@ ll_file_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
struct ll_file_data *fd = LUSTRE_FPRIVATE(file);
int flags, rc;
- CDEBUG(D_VFSTRACE, "VFS Op:inode="DFID"(%p),cmd=%x\n",
+ CDEBUG(D_VFSTRACE, "VFS Op:inode=" DFID "(%p),cmd=%x\n",
PFID(ll_inode2fid(inode)), inode, cmd);
ll_stats_ops_tally(ll_i2sbi(inode), LPROC_LL_IOCTL, 1);
@@ -2263,7 +2263,7 @@ static loff_t ll_file_seek(struct file *file, loff_t offset, int origin)
retval = offset + ((origin == SEEK_END) ? i_size_read(inode) :
(origin == SEEK_CUR) ? file->f_pos : 0);
- CDEBUG(D_VFSTRACE, "VFS Op:inode="DFID"(%p), to=%llu=%#llx(%d)\n",
+ CDEBUG(D_VFSTRACE, "VFS Op:inode=" DFID "(%p), to=%llu=%#llx(%d)\n",
PFID(ll_inode2fid(inode)), inode, retval, retval, origin);
ll_stats_ops_tally(ll_i2sbi(inode), LPROC_LL_LLSEEK, 1);
@@ -2360,7 +2360,7 @@ int ll_fsync(struct file *file, loff_t start, loff_t end, int datasync)
struct ptlrpc_request *req;
int rc, err;
- CDEBUG(D_VFSTRACE, "VFS Op:inode="DFID"(%p)\n",
+ CDEBUG(D_VFSTRACE, "VFS Op:inode=" DFID "(%p)\n",
PFID(ll_inode2fid(inode)), inode);
ll_stats_ops_tally(ll_i2sbi(inode), LPROC_LL_FSYNC, 1);
@@ -2422,7 +2422,7 @@ ll_file_flock(struct file *file, int cmd, struct file_lock *file_lock)
int rc;
int rc2 = 0;
- CDEBUG(D_VFSTRACE, "VFS Op:inode="DFID" file_lock=%p\n",
+ CDEBUG(D_VFSTRACE, "VFS Op:inode=" DFID " file_lock=%p\n",
PFID(ll_inode2fid(inode)), file_lock);
ll_stats_ops_tally(ll_i2sbi(inode), LPROC_LL_FLOCK, 1);
@@ -2507,7 +2507,7 @@ ll_file_flock(struct file *file, int cmd, struct file_lock *file_lock)
if (IS_ERR(op_data))
return PTR_ERR(op_data);
- CDEBUG(D_DLMTRACE, "inode="DFID", pid=%u, flags=%#llx, mode=%u, start=%llu, end=%llu\n",
+ CDEBUG(D_DLMTRACE, "inode=" DFID ", pid=%u, flags=%#llx, mode=%u, start=%llu, end=%llu\n",
PFID(ll_inode2fid(inode)), flock.l_flock.pid, flags,
einfo.ei_mode, flock.l_flock.start, flock.l_flock.end);
@@ -2582,7 +2582,7 @@ int ll_migrate(struct inode *parent, struct file *file, int mdtidx,
struct qstr qstr;
int rc;
- CDEBUG(D_VFSTRACE, "migrate %s under "DFID" to MDT%d\n",
+ CDEBUG(D_VFSTRACE, "migrate %s under " DFID " to MDT%d\n",
name, PFID(ll_inode2fid(parent)), mdtidx);
op_data = ll_prep_md_op_data(NULL, parent, NULL, name, namelen,
@@ -2617,7 +2617,7 @@ int ll_migrate(struct inode *parent, struct file *file, int mdtidx,
inode_lock(child_inode);
op_data->op_fid3 = *ll_inode2fid(child_inode);
if (!fid_is_sane(&op_data->op_fid3)) {
- CERROR("%s: migrate %s, but fid "DFID" is insane\n",
+ CERROR("%s: migrate %s, but fid " DFID " is insane\n",
ll_get_fsname(parent->i_sb, NULL, 0), name,
PFID(&op_data->op_fid3));
rc = -EINVAL;
@@ -2629,7 +2629,7 @@ int ll_migrate(struct inode *parent, struct file *file, int mdtidx,
goto out_unlock;
if (rc == mdtidx) {
- CDEBUG(D_INFO, "%s:"DFID" is already on MDT%d.\n", name,
+ CDEBUG(D_INFO, "%s: " DFID " is already on MDT%d.\n", name,
PFID(&op_data->op_fid3), mdtidx);
rc = 0;
goto out_unlock;
@@ -2733,7 +2733,7 @@ int ll_have_md_lock(struct inode *inode, __u64 *bits,
return 0;
fid = &ll_i2info(inode)->lli_fid;
- CDEBUG(D_INFO, "trying to match res "DFID" mode %s\n", PFID(fid),
+ CDEBUG(D_INFO, "trying to match res " DFID " mode %s\n", PFID(fid),
ldlm_lockname[mode]);
flags = LDLM_FL_BLOCK_GRANTED | LDLM_FL_CBPENDING | LDLM_FL_TEST_LOCK;
@@ -2767,7 +2767,7 @@ enum ldlm_mode ll_take_md_lock(struct inode *inode, __u64 bits,
struct lu_fid *fid;
fid = &ll_i2info(inode)->lli_fid;
- CDEBUG(D_INFO, "trying to match res "DFID"\n", PFID(fid));
+ CDEBUG(D_INFO, "trying to match res " DFID "\n", PFID(fid));
return md_lock_match(ll_i2mdexp(inode), flags | LDLM_FL_BLOCK_GRANTED,
fid, LDLM_IBITS, &policy, mode, lockh);
@@ -2792,7 +2792,7 @@ static int ll_inode_revalidate_fini(struct inode *inode, int rc)
return 0;
} else if (rc != 0) {
CDEBUG_LIMIT((rc == -EACCES || rc == -EIDRM) ? D_INFO : D_ERROR,
- "%s: revalidate FID "DFID" error: rc = %d\n",
+ "%s: revalidate FID " DFID " error: rc = %d\n",
ll_get_fsname(inode->i_sb, NULL, 0),
PFID(ll_inode2fid(inode)), rc);
}
@@ -2807,7 +2807,7 @@ static int __ll_inode_revalidate(struct dentry *dentry, __u64 ibits)
struct obd_export *exp;
int rc = 0;
- CDEBUG(D_VFSTRACE, "VFS Op:inode="DFID"(%p),name=%pd\n",
+ CDEBUG(D_VFSTRACE, "VFS Op:inode=" DFID "(%p),name=%pd\n",
PFID(ll_inode2fid(inode)), inode, dentry);
exp = ll_i2mdexp(inode);
@@ -3067,7 +3067,7 @@ int ll_inode_permission(struct inode *inode, int mask)
return rc;
}
- CDEBUG(D_VFSTRACE, "VFS Op:inode="DFID"(%p), inode mode %x mask %o\n",
+ CDEBUG(D_VFSTRACE, "VFS Op:inode=" DFID "(%p), inode mode %x mask %o\n",
PFID(ll_inode2fid(inode)), inode, inode->i_mode, mask);
/* squash fsuid/fsgid if needed */
@@ -3114,7 +3114,7 @@ int ll_inode_permission(struct inode *inode, int mask)
}
/* -o localflock - only provides locally consistent flock locks */
-struct file_operations ll_file_operations = {
+const struct file_operations ll_file_operations = {
.read_iter = ll_file_read_iter,
.write_iter = ll_file_write_iter,
.unlocked_ioctl = ll_file_ioctl,
@@ -3127,7 +3127,7 @@ struct file_operations ll_file_operations = {
.flush = ll_flush
};
-struct file_operations ll_file_operations_flock = {
+const struct file_operations ll_file_operations_flock = {
.read_iter = ll_file_read_iter,
.write_iter = ll_file_write_iter,
.unlocked_ioctl = ll_file_ioctl,
@@ -3143,7 +3143,7 @@ struct file_operations ll_file_operations_flock = {
};
/* These are for -o noflock - to return ENOSYS on flock calls */
-struct file_operations ll_file_operations_noflock = {
+const struct file_operations ll_file_operations_noflock = {
.read_iter = ll_file_read_iter,
.write_iter = ll_file_write_iter,
.unlocked_ioctl = ll_file_ioctl,
@@ -3322,7 +3322,7 @@ static int ll_layout_fetch(struct inode *inode, struct ldlm_lock *lock)
int lmmsize;
int rc;
- CDEBUG(D_INODE, DFID" LVB_READY=%d l_lvb_data=%p l_lvb_len=%d\n",
+ CDEBUG(D_INODE, DFID " LVB_READY=%d l_lvb_data=%p l_lvb_len=%d\n",
PFID(ll_inode2fid(inode)), ldlm_is_lvb_ready(lock),
lock->l_lvb_data, lock->l_lvb_len);
@@ -3447,7 +3447,7 @@ out:
/* wait for IO to complete if it's still being used. */
if (wait_layout) {
- CDEBUG(D_INODE, "%s: "DFID"(%p) wait for layout reconf\n",
+ CDEBUG(D_INODE, "%s: " DFID "(%p) wait for layout reconf\n",
ll_get_fsname(inode->i_sb, NULL, 0),
PFID(&lli->lli_fid), inode);
@@ -3458,7 +3458,7 @@ out:
if (rc == 0)
rc = -EAGAIN;
- CDEBUG(D_INODE, "%s: file="DFID" waiting layout return: %d.\n",
+ CDEBUG(D_INODE, "%s: file=" DFID " waiting layout return: %d.\n",
ll_get_fsname(inode->i_sb, NULL, 0),
PFID(&lli->lli_fid), rc);
}
@@ -3504,7 +3504,7 @@ again:
it.it_op = IT_LAYOUT;
lockh.cookie = 0ULL;
- LDLM_DEBUG_NOLOCK("%s: requeue layout lock for file "DFID"(%p)",
+ LDLM_DEBUG_NOLOCK("%s: requeue layout lock for file " DFID "(%p)",
ll_get_fsname(inode->i_sb, NULL, 0),
PFID(&lli->lli_fid), inode);
diff --git a/drivers/staging/lustre/lustre/llite/lcommon_cl.c b/drivers/staging/lustre/lustre/llite/lcommon_cl.c
index 8af611033e12..96515b839436 100644
--- a/drivers/staging/lustre/lustre/llite/lcommon_cl.c
+++ b/drivers/staging/lustre/lustre/llite/lcommon_cl.c
@@ -207,7 +207,7 @@ int cl_file_inode_init(struct inode *inode, struct lustre_md *md)
static void cl_object_put_last(struct lu_env *env, struct cl_object *obj)
{
struct lu_object_header *header = obj->co_lu.lo_header;
- wait_queue_t waiter;
+ wait_queue_entry_t waiter;
if (unlikely(atomic_read(&header->loh_ref) != 1)) {
struct lu_site *site = obj->co_lu.lo_dev->ld_site;
diff --git a/drivers/staging/lustre/lustre/llite/llite_internal.h b/drivers/staging/lustre/lustre/llite/llite_internal.h
index d2a0fabd8a69..cd3311abf999 100644
--- a/drivers/staging/lustre/lustre/llite/llite_internal.h
+++ b/drivers/staging/lustre/lustre/llite/llite_internal.h
@@ -470,7 +470,7 @@ struct ll_sb_info {
struct ll_ra_info ll_ra_info;
unsigned int ll_namelen;
- struct file_operations *ll_fop;
+ const struct file_operations *ll_fop;
unsigned int ll_md_brw_pages; /* readdir pages per RPC */
@@ -718,14 +718,14 @@ extern const struct inode_operations ll_special_inode_operations;
struct inode *ll_iget(struct super_block *sb, ino_t hash,
struct lustre_md *lic);
int ll_test_inode_by_fid(struct inode *inode, void *opaque);
-int ll_md_blocking_ast(struct ldlm_lock *, struct ldlm_lock_desc *,
+int ll_md_blocking_ast(struct ldlm_lock *lock, struct ldlm_lock_desc *desc,
void *data, int flag);
struct dentry *ll_splice_alias(struct inode *inode, struct dentry *de);
void ll_update_times(struct ptlrpc_request *request, struct inode *inode);
/* llite/rw.c */
int ll_writepage(struct page *page, struct writeback_control *wbc);
-int ll_writepages(struct address_space *, struct writeback_control *wbc);
+int ll_writepages(struct address_space *mapping, struct writeback_control *wbc);
int ll_readpage(struct file *file, struct page *page);
void ll_readahead_init(struct inode *inode, struct ll_readahead_state *ras);
int vvp_io_write_commit(const struct lu_env *env, struct cl_io *io);
@@ -736,9 +736,9 @@ void ll_cl_remove(struct file *file, const struct lu_env *env);
extern const struct address_space_operations ll_aops;
/* llite/file.c */
-extern struct file_operations ll_file_operations;
-extern struct file_operations ll_file_operations_flock;
-extern struct file_operations ll_file_operations_noflock;
+extern const struct file_operations ll_file_operations;
+extern const struct file_operations ll_file_operations_flock;
+extern const struct file_operations ll_file_operations_noflock;
extern const struct inode_operations ll_file_inode_operations;
int ll_have_md_lock(struct inode *inode, __u64 *bits,
enum ldlm_mode l_req_mode);
@@ -747,7 +747,7 @@ enum ldlm_mode ll_take_md_lock(struct inode *inode, __u64 bits,
enum ldlm_mode mode);
int ll_file_open(struct inode *inode, struct file *file);
int ll_file_release(struct inode *inode, struct file *file);
-int ll_release_openhandle(struct inode *, struct lookup_intent *);
+int ll_release_openhandle(struct inode *inode, struct lookup_intent *it);
int ll_md_real_close(struct inode *inode, fmode_t fmode);
int ll_getattr(const struct path *path, struct kstat *stat,
u32 request_mask, unsigned int flags);
@@ -778,9 +778,9 @@ int ll_hsm_state_set(struct inode *inode, struct hsm_state_set *hss);
/* llite/dcache.c */
extern const struct dentry_operations ll_d_ops;
-void ll_intent_drop_lock(struct lookup_intent *);
-void ll_intent_release(struct lookup_intent *);
-void ll_invalidate_aliases(struct inode *);
+void ll_intent_drop_lock(struct lookup_intent *it);
+void ll_intent_release(struct lookup_intent *it);
+void ll_invalidate_aliases(struct inode *inode);
void ll_lookup_finish_locks(struct lookup_intent *it, struct inode *inode);
int ll_revalidate_it_finish(struct ptlrpc_request *request,
struct lookup_intent *it, struct inode *inode);
@@ -811,7 +811,7 @@ int ll_remount_fs(struct super_block *sb, int *flags, char *data);
int ll_show_options(struct seq_file *seq, struct dentry *dentry);
void ll_dirty_page_discard_warn(struct page *page, int ioret);
int ll_prep_inode(struct inode **inode, struct ptlrpc_request *req,
- struct super_block *, struct lookup_intent *);
+ struct super_block *sb, struct lookup_intent *it);
int ll_obd_statfs(struct inode *inode, void __user *arg);
int ll_get_max_mdsize(struct ll_sb_info *sbi, int *max_mdsize);
int ll_get_default_mdsize(struct ll_sb_info *sbi, int *default_mdsize);
@@ -1253,7 +1253,7 @@ static inline void ll_set_lock_data(struct obd_export *exp, struct inode *inode,
*/
if (it->it_remote_lock_mode) {
handle.cookie = it->it_remote_lock_handle;
- CDEBUG(D_DLMTRACE, "setting l_data to inode "DFID"%p for remote lock %#llx\n",
+ CDEBUG(D_DLMTRACE, "setting l_data to inode " DFID "%p for remote lock %#llx\n",
PFID(ll_inode2fid(inode)), inode,
handle.cookie);
md_set_lock_data(exp, &handle, inode, NULL);
@@ -1261,7 +1261,7 @@ static inline void ll_set_lock_data(struct obd_export *exp, struct inode *inode,
handle.cookie = it->it_lock_handle;
- CDEBUG(D_DLMTRACE, "setting l_data to inode "DFID"%p for lock %#llx\n",
+ CDEBUG(D_DLMTRACE, "setting l_data to inode " DFID "%p for lock %#llx\n",
PFID(ll_inode2fid(inode)), inode, handle.cookie);
md_set_lock_data(exp, &handle, inode, &it->it_lock_bits);
diff --git a/drivers/staging/lustre/lustre/llite/llite_lib.c b/drivers/staging/lustre/lustre/llite/llite_lib.c
index ca5040c69217..974a05d6c969 100644
--- a/drivers/staging/lustre/lustre/llite/llite_lib.c
+++ b/drivers/staging/lustre/lustre/llite/llite_lib.c
@@ -427,13 +427,13 @@ static int client_common_fill_super(struct super_block *sb, char *md, char *dt,
goto out_lock_cn_cb;
}
if (!fid_is_sane(&sbi->ll_root_fid)) {
- CERROR("%s: Invalid root fid "DFID" during mount\n",
+ CERROR("%s: Invalid root fid " DFID " during mount\n",
sbi->ll_md_exp->exp_obd->obd_name,
PFID(&sbi->ll_root_fid));
err = -EINVAL;
goto out_lock_cn_cb;
}
- CDEBUG(D_SUPER, "rootfid "DFID"\n", PFID(&sbi->ll_root_fid));
+ CDEBUG(D_SUPER, "rootfid " DFID "\n", PFID(&sbi->ll_root_fid));
sb->s_op = &lustre_super_operations;
sb->s_xattr = ll_xattr_handlers;
@@ -1079,7 +1079,7 @@ static struct inode *ll_iget_anon_dir(struct super_block *sb,
ino = cl_fid_build_ino(fid, sbi->ll_flags & LL_SBI_32BIT_API);
inode = iget_locked(sb, ino);
if (!inode) {
- CERROR("%s: failed get simple inode "DFID": rc = -ENOENT\n",
+ CERROR("%s: failed get simple inode " DFID ": rc = -ENOENT\n",
ll_get_fsname(sb, NULL, 0), PFID(fid));
return ERR_PTR(-ENOENT);
}
@@ -1090,7 +1090,7 @@ static struct inode *ll_iget_anon_dir(struct super_block *sb,
inode->i_mode = (inode->i_mode & ~S_IFMT) |
(body->mbo_mode & S_IFMT);
- LASSERTF(S_ISDIR(inode->i_mode), "Not slave inode "DFID"\n",
+ LASSERTF(S_ISDIR(inode->i_mode), "Not slave inode " DFID "\n",
PFID(fid));
LTIME_S(inode->i_mtime) = 0;
@@ -1106,7 +1106,7 @@ static struct inode *ll_iget_anon_dir(struct super_block *sb,
LASSERT(lsm);
/* master object FID */
lli->lli_pfid = body->mbo_fid1;
- CDEBUG(D_INODE, "lli %p slave "DFID" master "DFID"\n",
+ CDEBUG(D_INODE, "lli %p slave " DFID " master " DFID "\n",
lli, PFID(fid), PFID(&lli->lli_pfid));
unlock_new_inode(inode);
}
@@ -1174,7 +1174,7 @@ static int ll_update_lsm_md(struct inode *inode, struct lustre_md *md)
int rc;
LASSERT(S_ISDIR(inode->i_mode));
- CDEBUG(D_INODE, "update lsm %p of "DFID"\n", lli->lli_lsm_md,
+ CDEBUG(D_INODE, "update lsm %p of " DFID "\n", lli->lli_lsm_md,
PFID(ll_inode2fid(inode)));
/* no striped information from request. */
@@ -1187,7 +1187,7 @@ static int ll_update_lsm_md(struct inode *inode, struct lustre_md *md)
* migration is done, the temporay MIGRATE layout has
* been removed
*/
- CDEBUG(D_INODE, DFID" finish migration.\n",
+ CDEBUG(D_INODE, DFID " finish migration.\n",
PFID(ll_inode2fid(inode)));
lmv_free_memmd(lli->lli_lsm_md);
lli->lli_lsm_md = NULL;
@@ -1241,7 +1241,7 @@ static int ll_update_lsm_md(struct inode *inode, struct lustre_md *md)
kfree(attr);
- CDEBUG(D_INODE, "Set lsm %p magic %x to "DFID"\n", lsm,
+ CDEBUG(D_INODE, "Set lsm %p magic %x to " DFID "\n", lsm,
lsm->lsm_md_magic, PFID(ll_inode2fid(inode)));
return 0;
}
@@ -1251,7 +1251,7 @@ static int ll_update_lsm_md(struct inode *inode, struct lustre_md *md)
struct lmv_stripe_md *old_lsm = lli->lli_lsm_md;
int idx;
- CERROR("%s: inode "DFID"(%p)'s lmv layout mismatch (%p)/(%p) magic:0x%x/0x%x stripe count: %d/%d master_mdt: %d/%d hash_type:0x%x/0x%x layout: 0x%x/0x%x pool:%s/%s\n",
+ CERROR("%s: inode " DFID "(%p)'s lmv layout mismatch (%p)/(%p) magic:0x%x/0x%x stripe count: %d/%d master_mdt: %d/%d hash_type:0x%x/0x%x layout: 0x%x/0x%x pool:%s/%s\n",
ll_get_fsname(inode->i_sb, NULL, 0), PFID(&lli->lli_fid),
inode, lsm, old_lsm,
lsm->lsm_md_magic, old_lsm->lsm_md_magic,
@@ -1266,13 +1266,13 @@ static int ll_update_lsm_md(struct inode *inode, struct lustre_md *md)
old_lsm->lsm_md_pool_name);
for (idx = 0; idx < old_lsm->lsm_md_stripe_count; idx++) {
- CERROR("%s: sub FIDs in old lsm idx %d, old: "DFID"\n",
+ CERROR("%s: sub FIDs in old lsm idx %d, old: " DFID "\n",
ll_get_fsname(inode->i_sb, NULL, 0), idx,
PFID(&old_lsm->lsm_md_oinfo[idx].lmo_fid));
}
for (idx = 0; idx < lsm->lsm_md_stripe_count; idx++) {
- CERROR("%s: sub FIDs in new lsm idx %d, new: "DFID"\n",
+ CERROR("%s: sub FIDs in new lsm idx %d, new: " DFID "\n",
ll_get_fsname(inode->i_sb, NULL, 0), idx,
PFID(&lsm->lsm_md_oinfo[idx].lmo_fid));
}
@@ -1288,7 +1288,7 @@ void ll_clear_inode(struct inode *inode)
struct ll_inode_info *lli = ll_i2info(inode);
struct ll_sb_info *sbi = ll_i2sbi(inode);
- CDEBUG(D_VFSTRACE, "VFS Op:inode="DFID"(%p)\n",
+ CDEBUG(D_VFSTRACE, "VFS Op:inode=" DFID "(%p)\n",
PFID(ll_inode2fid(inode)), inode);
if (S_ISDIR(inode->i_mode)) {
@@ -1421,7 +1421,7 @@ int ll_setattr_raw(struct dentry *dentry, struct iattr *attr, bool hsm_import)
struct md_op_data *op_data = NULL;
int rc = 0;
- CDEBUG(D_VFSTRACE, "%s: setattr inode "DFID"(%p) from %llu to %llu, valid %x, hsm_import %d\n",
+ CDEBUG(D_VFSTRACE, "%s: setattr inode " DFID "(%p) from %llu to %llu, valid %x, hsm_import %d\n",
ll_get_fsname(inode->i_sb, NULL, 0), PFID(&lli->lli_fid), inode,
i_size_read(inode), attr->ia_size, attr->ia_valid, hsm_import);
@@ -1436,7 +1436,7 @@ int ll_setattr_raw(struct dentry *dentry, struct iattr *attr, bool hsm_import)
* needs another check in addition to the VFS check above.
*/
if (attr->ia_size > ll_file_maxbytes(inode)) {
- CDEBUG(D_INODE, "file "DFID" too large %llu > %llu\n",
+ CDEBUG(D_INODE, "file " DFID " too large %llu > %llu\n",
PFID(&lli->lli_fid), attr->ia_size,
ll_file_maxbytes(inode));
return -EFBIG;
@@ -1785,7 +1785,7 @@ int ll_update_inode(struct inode *inode, struct lustre_md *md)
/* FID shouldn't be changed! */
if (fid_is_sane(&lli->lli_fid)) {
LASSERTF(lu_fid_eq(&lli->lli_fid, &body->mbo_fid1),
- "Trying to change FID "DFID" to the "DFID", inode "DFID"(%p)\n",
+ "Trying to change FID " DFID " to the " DFID ", inode " DFID "(%p)\n",
PFID(&lli->lli_fid), PFID(&body->mbo_fid1),
PFID(ll_inode2fid(inode)), inode);
} else {
@@ -1820,7 +1820,7 @@ int ll_read_inode2(struct inode *inode, void *opaque)
struct ll_inode_info *lli = ll_i2info(inode);
int rc;
- CDEBUG(D_VFSTRACE, "VFS Op:inode="DFID"(%p)\n",
+ CDEBUG(D_VFSTRACE, "VFS Op:inode=" DFID "(%p)\n",
PFID(&lli->lli_fid), inode);
/* Core attributes from the MDS first. This is a new inode, and
@@ -1902,7 +1902,7 @@ int ll_iocontrol(struct inode *inode, struct file *file,
rc = md_getattr(sbi->ll_md_exp, op_data, &req);
ll_finish_md_op_data(op_data);
if (rc) {
- CERROR("%s: failure inode "DFID": rc = %d\n",
+ CERROR("%s: failure inode " DFID ": rc = %d\n",
sbi->ll_md_exp->exp_obd->obd_name,
PFID(ll_inode2fid(inode)), rc);
return -abs(rc);
diff --git a/drivers/staging/lustre/lustre/llite/llite_mmap.c b/drivers/staging/lustre/lustre/llite/llite_mmap.c
index cbbfdaf127a7..ccc7ae15a943 100644
--- a/drivers/staging/lustre/lustre/llite/llite_mmap.c
+++ b/drivers/staging/lustre/lustre/llite/llite_mmap.c
@@ -378,7 +378,7 @@ static int ll_page_mkwrite(struct vm_fault *vmf)
if (!printed && ++count > 16) {
const struct dentry *de = vma->vm_file->f_path.dentry;
- CWARN("app(%s): the page %lu of file "DFID" is under heavy contention\n",
+ CWARN("app(%s): the page %lu of file " DFID " is under heavy contention\n",
current->comm, vmf->pgoff,
PFID(ll_inode2fid(de->d_inode)));
printed = true;
diff --git a/drivers/staging/lustre/lustre/llite/llite_nfs.c b/drivers/staging/lustre/lustre/llite/llite_nfs.c
index 49a930f0fc5d..e50c637fab54 100644
--- a/drivers/staging/lustre/lustre/llite/llite_nfs.c
+++ b/drivers/staging/lustre/lustre/llite/llite_nfs.c
@@ -84,7 +84,7 @@ struct inode *search_inode_for_lustre(struct super_block *sb,
struct md_op_data *op_data;
int rc;
- CDEBUG(D_INFO, "searching inode for:(%lu,"DFID")\n", hash, PFID(fid));
+ CDEBUG(D_INFO, "searching inode for:(%lu," DFID ")\n", hash, PFID(fid));
inode = ilookup5(sb, hash, ll_test_inode_by_fid, (void *)fid);
if (inode)
@@ -109,7 +109,7 @@ struct inode *search_inode_for_lustre(struct super_block *sb,
rc = md_getattr(sbi->ll_md_exp, op_data, &req);
kfree(op_data);
if (rc) {
- CDEBUG(D_INFO, "can't get object attrs, fid "DFID", rc %d\n",
+ CDEBUG(D_INFO, "can't get object attrs, fid " DFID ", rc %d\n",
PFID(fid), rc);
return ERR_PTR(rc);
}
@@ -195,7 +195,7 @@ static int ll_encode_fh(struct inode *inode, __u32 *fh, int *plen,
int fileid_len = sizeof(struct lustre_nfs_fid) / 4;
struct lustre_nfs_fid *nfs_fid = (void *)fh;
- CDEBUG(D_INFO, "%s: encoding for ("DFID") maxlen=%d minlen=%d\n",
+ CDEBUG(D_INFO, "%s: encoding for (" DFID ") maxlen=%d minlen=%d\n",
ll_get_fsname(inode->i_sb, NULL, 0),
PFID(ll_inode2fid(inode)), *plen, fileid_len);
@@ -312,7 +312,7 @@ int ll_dir_get_parent_fid(struct inode *dir, struct lu_fid *parent_fid)
sbi = ll_s2sbi(dir->i_sb);
- CDEBUG(D_INFO, "%s: getting parent for ("DFID")\n",
+ CDEBUG(D_INFO, "%s: getting parent for (" DFID ")\n",
ll_get_fsname(dir->i_sb, NULL, 0),
PFID(ll_inode2fid(dir)));
@@ -329,7 +329,7 @@ int ll_dir_get_parent_fid(struct inode *dir, struct lu_fid *parent_fid)
rc = md_getattr_name(sbi->ll_md_exp, op_data, &req);
ll_finish_md_op_data(op_data);
if (rc) {
- CERROR("%s: failure inode "DFID" get parent: rc = %d\n",
+ CERROR("%s: failure inode " DFID " get parent: rc = %d\n",
ll_get_fsname(dir->i_sb, NULL, 0),
PFID(ll_inode2fid(dir)), rc);
return rc;
diff --git a/drivers/staging/lustre/lustre/llite/lproc_llite.c b/drivers/staging/lustre/lustre/llite/lproc_llite.c
index c742cba60199..aeae6670e262 100644
--- a/drivers/staging/lustre/lustre/llite/lproc_llite.c
+++ b/drivers/staging/lustre/lustre/llite/lproc_llite.c
@@ -39,9 +39,9 @@
#include "vvp_internal.h"
/* debugfs llite mount point registration */
-static struct file_operations ll_rw_extents_stats_fops;
-static struct file_operations ll_rw_extents_stats_pp_fops;
-static struct file_operations ll_rw_offset_stats_fops;
+static const struct file_operations ll_rw_extents_stats_fops;
+static const struct file_operations ll_rw_extents_stats_pp_fops;
+static const struct file_operations ll_rw_offset_stats_fops;
static ssize_t blocksize_show(struct kobject *kobj, struct attribute *attr,
char *buf)
diff --git a/drivers/staging/lustre/lustre/llite/namei.c b/drivers/staging/lustre/lustre/llite/namei.c
index d583696e8378..a208a8b02c2c 100644
--- a/drivers/staging/lustre/lustre/llite/namei.c
+++ b/drivers/staging/lustre/lustre/llite/namei.c
@@ -86,7 +86,7 @@ static int ll_set_inode(struct inode *inode, void *opaque)
inode->i_mode = (inode->i_mode & ~S_IFMT) | (body->mbo_mode & S_IFMT);
if (unlikely(inode->i_mode == 0)) {
- CERROR("Invalid inode "DFID" type\n", PFID(&lli->lli_fid));
+ CERROR("Invalid inode " DFID " type\n", PFID(&lli->lli_fid));
return -EINVAL;
}
@@ -134,7 +134,7 @@ struct inode *ll_iget(struct super_block *sb, ino_t hash,
}
} else if (!(inode->i_state & (I_FREEING | I_CLEAR))) {
rc = ll_update_inode(inode, md);
- CDEBUG(D_VFSTRACE, "got inode: "DFID"(%p): rc = %d\n",
+ CDEBUG(D_VFSTRACE, "got inode: " DFID "(%p): rc = %d\n",
PFID(&md->body->mbo_fid1), inode, rc);
if (rc) {
if (S_ISDIR(inode->i_mode))
@@ -205,7 +205,7 @@ int ll_md_blocking_ast(struct ldlm_lock *lock, struct ldlm_lock_desc *desc,
if (!fid_res_name_eq(ll_inode2fid(inode),
&lock->l_resource->lr_name)) {
- LDLM_ERROR(lock, "data mismatch with object "DFID"(%p)",
+ LDLM_ERROR(lock, "data mismatch with object " DFID "(%p)",
PFID(ll_inode2fid(inode)), inode);
LBUG();
}
@@ -257,7 +257,7 @@ int ll_md_blocking_ast(struct ldlm_lock *lock, struct ldlm_lock_desc *desc,
rc = ll_layout_conf(inode, &conf);
if (rc < 0)
CDEBUG(D_INODE, "cannot invalidate layout of "
- DFID": rc = %d\n",
+ DFID ": rc = %d\n",
PFID(ll_inode2fid(inode)), rc);
}
@@ -274,7 +274,7 @@ int ll_md_blocking_ast(struct ldlm_lock *lock, struct ldlm_lock_desc *desc,
if ((bits & MDS_INODELOCK_UPDATE) && S_ISDIR(inode->i_mode)) {
struct ll_inode_info *lli = ll_i2info(inode);
- CDEBUG(D_INODE, "invalidating inode "DFID" lli = %p, pfid = "DFID"\n",
+ CDEBUG(D_INODE, "invalidating inode " DFID " lli = %p, pfid = " DFID "\n",
PFID(ll_inode2fid(inode)), lli,
PFID(&lli->lli_pfid));
@@ -290,7 +290,7 @@ int ll_md_blocking_ast(struct ldlm_lock *lock, struct ldlm_lock_desc *desc,
* we have to invalidate the negative children
* on master inode
*/
- CDEBUG(D_INODE, "Invalidate s"DFID" m"DFID"\n",
+ CDEBUG(D_INODE, "Invalidate s" DFID " m" DFID "\n",
PFID(ll_inode2fid(inode)),
PFID(&lli->lli_pfid));
@@ -542,7 +542,7 @@ static struct dentry *ll_lookup_it(struct inode *parent, struct dentry *dentry,
if (dentry->d_name.len > ll_i2sbi(parent)->ll_namelen)
return ERR_PTR(-ENAMETOOLONG);
- CDEBUG(D_VFSTRACE, "VFS Op:name=%pd, dir="DFID"(%p),intent=%s\n",
+ CDEBUG(D_VFSTRACE, "VFS Op:name=%pd, dir=" DFID "(%p),intent=%s\n",
dentry, PFID(ll_inode2fid(parent)), parent, LL_IT2STR(it));
if (d_mountpoint(dentry))
@@ -650,7 +650,7 @@ static struct dentry *ll_lookup_nd(struct inode *parent, struct dentry *dentry,
struct lookup_intent *itp, it = { .it_op = IT_GETATTR };
struct dentry *de;
- CDEBUG(D_VFSTRACE, "VFS Op:name=%pd, dir="DFID"(%p),flags=%u\n",
+ CDEBUG(D_VFSTRACE, "VFS Op:name=%pd, dir=" DFID "(%p),flags=%u\n",
dentry, PFID(ll_inode2fid(parent)), parent, flags);
/* Optimize away (CREATE && !OPEN). Let .create handle the race.
@@ -678,14 +678,14 @@ static struct dentry *ll_lookup_nd(struct inode *parent, struct dentry *dentry,
* together.
*/
static int ll_atomic_open(struct inode *dir, struct dentry *dentry,
- struct file *file, unsigned open_flags,
+ struct file *file, unsigned int open_flags,
umode_t mode, int *opened)
{
struct lookup_intent *it;
struct dentry *de;
int rc = 0;
- CDEBUG(D_VFSTRACE, "VFS Op:name=%pd, dir="DFID"(%p),file %p,open_flags %x,mode %x opened %d\n",
+ CDEBUG(D_VFSTRACE, "VFS Op:name=%pd, dir=" DFID "(%p),file %p,open_flags %x,mode %x opened %d\n",
dentry, PFID(ll_inode2fid(dir)), dir, file, open_flags, mode,
*opened);
@@ -792,7 +792,7 @@ static struct inode *ll_create_node(struct inode *dir, struct lookup_intent *it)
* lock on the inode. Since we finally have an inode pointer,
* stuff it in the lock.
*/
- CDEBUG(D_DLMTRACE, "setting l_ast_data to inode "DFID"(%p)\n",
+ CDEBUG(D_DLMTRACE, "setting l_ast_data to inode " DFID "(%p)\n",
PFID(ll_inode2fid(dir)), inode);
ll_set_lock_data(sbi->ll_md_exp, inode, it, NULL);
out:
@@ -820,7 +820,7 @@ static int ll_create_it(struct inode *dir, struct dentry *dentry,
struct inode *inode;
int rc = 0;
- CDEBUG(D_VFSTRACE, "VFS Op:name=%pd, dir="DFID"(%p), intent=%s\n",
+ CDEBUG(D_VFSTRACE, "VFS Op:name=%pd, dir=" DFID "(%p), intent=%s\n",
dentry, PFID(ll_inode2fid(dir)), dir, LL_IT2STR(it));
rc = it_open_error(DISP_OPEN_CREATE, it);
@@ -844,7 +844,7 @@ void ll_update_times(struct ptlrpc_request *request, struct inode *inode)
LASSERT(body);
if (body->mbo_valid & OBD_MD_FLMTIME &&
body->mbo_mtime > LTIME_S(inode->i_mtime)) {
- CDEBUG(D_INODE, "setting fid "DFID" mtime from %lu to %llu\n",
+ CDEBUG(D_INODE, "setting fid " DFID " mtime from %lu to %llu\n",
PFID(ll_inode2fid(inode)), LTIME_S(inode->i_mtime),
body->mbo_mtime);
LTIME_S(inode->i_mtime) = body->mbo_mtime;
@@ -942,7 +942,7 @@ static int ll_mknod(struct inode *dir, struct dentry *dchild,
{
int err;
- CDEBUG(D_VFSTRACE, "VFS Op:name=%pd, dir="DFID"(%p) mode %o dev %x\n",
+ CDEBUG(D_VFSTRACE, "VFS Op:name=%pd, dir=" DFID "(%p) mode %o dev %x\n",
dchild, PFID(ll_inode2fid(dir)), dir, mode,
old_encode_dev(rdev));
@@ -982,7 +982,7 @@ static int ll_create_nd(struct inode *dir, struct dentry *dentry,
{
int rc;
- CDEBUG(D_VFSTRACE, "VFS Op:name=%pd, dir="DFID"(%p), flags=%u, excl=%d\n",
+ CDEBUG(D_VFSTRACE, "VFS Op:name=%pd, dir=" DFID "(%p), flags=%u, excl=%d\n",
dentry, PFID(ll_inode2fid(dir)), dir, mode, want_excl);
rc = ll_mknod(dir, dentry, mode, 0);
@@ -1032,7 +1032,7 @@ static int ll_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode)
{
int err;
- CDEBUG(D_VFSTRACE, "VFS Op:name=%pd, dir"DFID"(%p)\n",
+ CDEBUG(D_VFSTRACE, "VFS Op:name=%pd, dir" DFID "(%p)\n",
dentry, PFID(ll_inode2fid(dir)), dir);
if (!IS_POSIXACL(dir) || !exp_connect_umask(ll_i2mdexp(dir)))
@@ -1052,7 +1052,7 @@ static int ll_rmdir(struct inode *dir, struct dentry *dchild)
struct md_op_data *op_data;
int rc;
- CDEBUG(D_VFSTRACE, "VFS Op:name=%pd, dir="DFID"(%p)\n",
+ CDEBUG(D_VFSTRACE, "VFS Op:name=%pd, dir=" DFID "(%p)\n",
dchild, PFID(ll_inode2fid(dir)), dir);
op_data = ll_prep_md_op_data(NULL, dir, NULL,
@@ -1082,7 +1082,7 @@ static int ll_symlink(struct inode *dir, struct dentry *dentry,
{
int err;
- CDEBUG(D_VFSTRACE, "VFS Op:name=%pd, dir="DFID"(%p),target=%.*s\n",
+ CDEBUG(D_VFSTRACE, "VFS Op:name=%pd, dir=" DFID "(%p),target=%.*s\n",
dentry, PFID(ll_inode2fid(dir)), dir, 3000, oldname);
err = ll_new_node(dir, dentry, oldname, S_IFLNK | 0777,
@@ -1103,7 +1103,7 @@ static int ll_link(struct dentry *old_dentry, struct inode *dir,
struct md_op_data *op_data;
int err;
- CDEBUG(D_VFSTRACE, "VFS Op: inode="DFID"(%p), dir="DFID"(%p), target=%pd\n",
+ CDEBUG(D_VFSTRACE, "VFS Op: inode=" DFID "(%p), dir=" DFID "(%p), target=%pd\n",
PFID(ll_inode2fid(src)), src, PFID(ll_inode2fid(dir)), dir,
new_dentry);
@@ -1138,7 +1138,7 @@ static int ll_rename(struct inode *src, struct dentry *src_dchild,
return -EINVAL;
CDEBUG(D_VFSTRACE,
- "VFS Op:oldname=%pd, src_dir="DFID"(%p), newname=%pd, tgt_dir="DFID"(%p)\n",
+ "VFS Op:oldname=%pd, src_dir=" DFID "(%p), newname=%pd, tgt_dir=" DFID "(%p)\n",
src_dchild, PFID(ll_inode2fid(src)), src,
tgt_dchild, PFID(ll_inode2fid(tgt)), tgt);
diff --git a/drivers/staging/lustre/lustre/llite/rw26.c b/drivers/staging/lustre/lustre/llite/rw26.c
index 420f296f9658..3619cd8bb5f3 100644
--- a/drivers/staging/lustre/lustre/llite/rw26.c
+++ b/drivers/staging/lustre/lustre/llite/rw26.c
@@ -327,7 +327,7 @@ static ssize_t ll_direct_IO_26(struct kiocb *iocb, struct iov_iter *iter)
if ((file_offset & ~PAGE_MASK) || (count & ~PAGE_MASK))
return -EINVAL;
- CDEBUG(D_VFSTRACE, "VFS Op:inode="DFID"(%p), size=%zd (max %lu), offset=%lld=%llx, pages %zd (max %lu)\n",
+ CDEBUG(D_VFSTRACE, "VFS Op:inode=" DFID "(%p), size=%zd (max %lu), offset=%lld=%llx, pages %zd (max %lu)\n",
PFID(ll_inode2fid(inode)), inode, count, MAX_DIO_SIZE,
file_offset, file_offset, count >> PAGE_SHIFT,
MAX_DIO_SIZE >> PAGE_SHIFT);
@@ -547,7 +547,7 @@ out:
}
static int ll_write_end(struct file *file, struct address_space *mapping,
- loff_t pos, unsigned len, unsigned copied,
+ loff_t pos, unsigned int len, unsigned int copied,
struct page *vmpage, void *fsdata)
{
struct ll_cl_context *lcc = fsdata;
diff --git a/drivers/staging/lustre/lustre/llite/statahead.c b/drivers/staging/lustre/lustre/llite/statahead.c
index fb7c315b33cb..9bbca018a5fe 100644
--- a/drivers/staging/lustre/lustre/llite/statahead.c
+++ b/drivers/staging/lustre/lustre/llite/statahead.c
@@ -528,7 +528,7 @@ static void ll_agl_trigger(struct inode *inode, struct ll_statahead_info *sai)
}
CDEBUG(D_READA, "Handling (init) async glimpse: inode = "
- DFID", idx = %llu\n", PFID(&lli->lli_fid), index);
+ DFID ", idx = %llu\n", PFID(&lli->lli_fid), index);
cl_agl(inode);
lli->lli_agl_index = 0;
@@ -536,7 +536,7 @@ static void ll_agl_trigger(struct inode *inode, struct ll_statahead_info *sai)
up_write(&lli->lli_glimpse_sem);
CDEBUG(D_READA, "Handled (init) async glimpse: inode= "
- DFID", idx = %llu, rc = %d\n",
+ DFID ", idx = %llu, rc = %d\n",
PFID(&lli->lli_fid), index, rc);
iput(inode);
@@ -1008,7 +1008,7 @@ static int ll_statahead_thread(void *arg)
sai->sai_in_readpage = 0;
if (IS_ERR(page)) {
rc = PTR_ERR(page);
- CDEBUG(D_READA, "error reading dir "DFID" at %llu/%llu: opendir_pid = %u: rc = %d\n",
+ CDEBUG(D_READA, "error reading dir " DFID " at %llu/%llu: opendir_pid = %u: rc = %d\n",
PFID(ll_inode2fid(dir)), pos, sai->sai_index,
lli->lli_opendir_pid, rc);
break;
@@ -1105,7 +1105,7 @@ static int ll_statahead_thread(void *arg)
if (sa_low_hit(sai)) {
rc = -EFAULT;
atomic_inc(&sbi->ll_sa_wrong);
- CDEBUG(D_READA, "Statahead for dir "DFID" hit ratio too low: hit/miss %llu/%llu, sent/replied %llu/%llu, stopping statahead thread: pid %d\n",
+ CDEBUG(D_READA, "Statahead for dir " DFID " hit ratio too low: hit/miss %llu/%llu, sent/replied %llu/%llu, stopping statahead thread: pid %d\n",
PFID(&lli->lli_fid), sai->sai_hit,
sai->sai_miss, sai->sai_sent,
sai->sai_replied, current_pid());
@@ -1211,7 +1211,7 @@ void ll_deauthorize_statahead(struct inode *dir, void *key)
LASSERT(lli->lli_opendir_key == key);
LASSERT(lli->lli_opendir_pid);
- CDEBUG(D_READA, "deauthorize statahead for "DFID"\n",
+ CDEBUG(D_READA, "deauthorize statahead for " DFID "\n",
PFID(&lli->lli_fid));
spin_lock(&lli->lli_sa_lock);
@@ -1274,7 +1274,7 @@ static int is_first_dirent(struct inode *dir, struct dentry *dentry)
struct ll_inode_info *lli = ll_i2info(dir);
rc = PTR_ERR(page);
- CERROR("%s: error reading dir "DFID" at %llu: opendir_pid = %u : rc = %d\n",
+ CERROR("%s: error reading dir " DFID " at %llu: opendir_pid = %u : rc = %d\n",
ll_get_fsname(dir->i_sb, NULL, 0),
PFID(ll_inode2fid(dir)), pos,
lli->lli_opendir_pid, rc);
@@ -1471,7 +1471,7 @@ static int revalidate_statahead_dentry(struct inode *dir,
} else if ((*dentryp)->d_inode != inode) {
/* revalidate, but inode is recreated */
CDEBUG(D_READA,
- "%s: stale dentry %pd inode "DFID", statahead inode "DFID"\n",
+ "%s: stale dentry %pd inode " DFID ", statahead inode " DFID "\n",
ll_get_fsname((*dentryp)->d_inode->i_sb,
NULL, 0),
*dentryp,
diff --git a/drivers/staging/lustre/lustre/llite/symlink.c b/drivers/staging/lustre/lustre/llite/symlink.c
index 60aac42e5344..3cd33483afaf 100644
--- a/drivers/staging/lustre/lustre/llite/symlink.c
+++ b/drivers/staging/lustre/lustre/llite/symlink.c
@@ -72,7 +72,7 @@ static int ll_readlink_internal(struct inode *inode,
ll_finish_md_op_data(op_data);
if (rc) {
if (rc != -ENOENT)
- CERROR("%s: inode "DFID": rc = %d\n",
+ CERROR("%s: inode " DFID ": rc = %d\n",
ll_get_fsname(inode->i_sb, NULL, 0),
PFID(ll_inode2fid(inode)), rc);
goto failed;
@@ -87,7 +87,7 @@ static int ll_readlink_internal(struct inode *inode,
LASSERT(symlen != 0);
if (body->mbo_eadatasize != symlen) {
- CERROR("%s: inode "DFID": symlink length %d not expected %d\n",
+ CERROR("%s: inode " DFID ": symlink length %d not expected %d\n",
ll_get_fsname(inode->i_sb, NULL, 0),
PFID(ll_inode2fid(inode)), body->mbo_eadatasize - 1,
symlen - 1);
diff --git a/drivers/staging/lustre/lustre/llite/vvp_dev.c b/drivers/staging/lustre/lustre/llite/vvp_dev.c
index 6cb2db28eb60..8e45672b4617 100644
--- a/drivers/staging/lustre/lustre/llite/vvp_dev.c
+++ b/drivers/staging/lustre/lustre/llite/vvp_dev.c
@@ -381,11 +381,11 @@ int cl_sb_fini(struct super_block *sb)
#define PGC_DEPTH_SHIFT (32)
struct vvp_pgcache_id {
- unsigned vpi_bucket;
- unsigned vpi_depth;
+ unsigned int vpi_bucket;
+ unsigned int vpi_depth;
uint32_t vpi_index;
- unsigned vpi_curdep;
+ unsigned int vpi_curdep;
struct lu_object_header *vpi_obj;
};
diff --git a/drivers/staging/lustre/lustre/llite/vvp_io.c b/drivers/staging/lustre/lustre/llite/vvp_io.c
index aa31bc0a58a6..c5ba265ef6ad 100644
--- a/drivers/staging/lustre/lustre/llite/vvp_io.c
+++ b/drivers/staging/lustre/lustre/llite/vvp_io.c
@@ -325,7 +325,7 @@ static void vvp_io_fini(const struct lu_env *env, const struct cl_io_slice *ios)
io->ci_need_restart = vio->vui_layout_gen != gen;
if (io->ci_need_restart) {
CDEBUG(D_VFSTRACE,
- DFID" layout changed from %d to %d.\n",
+ DFID " layout changed from %d to %d.\n",
PFID(lu_object_fid(&obj->co_lu)),
vio->vui_layout_gen, gen);
/* today successful restore is the only possible case */
diff --git a/drivers/staging/lustre/lustre/llite/vvp_object.c b/drivers/staging/lustre/lustre/llite/vvp_object.c
index 8e18cf86cefc..9bfd72e514d1 100644
--- a/drivers/staging/lustre/lustre/llite/vvp_object.c
+++ b/drivers/staging/lustre/lustre/llite/vvp_object.c
@@ -70,7 +70,7 @@ static int vvp_object_print(const struct lu_env *env, void *cookie,
atomic_read(&obj->vob_mmap_cnt), inode);
if (inode) {
lli = ll_i2info(inode);
- (*p)(env, cookie, "%lu/%u %o %u %d %p "DFID,
+ (*p)(env, cookie, "%lu/%u %o %u %d %p " DFID,
inode->i_ino, inode->i_generation, inode->i_mode,
inode->i_nlink, atomic_read(&inode->i_count),
lli->lli_clob, PFID(&lli->lli_fid));
diff --git a/drivers/staging/lustre/lustre/llite/xattr.c b/drivers/staging/lustre/lustre/llite/xattr.c
index 6187bffec8c4..bd30abdecfb9 100644
--- a/drivers/staging/lustre/lustre/llite/xattr.c
+++ b/drivers/staging/lustre/lustre/llite/xattr.c
@@ -195,7 +195,7 @@ static int ll_xattr_set(const struct xattr_handler *handler,
LASSERT(inode);
LASSERT(name);
- CDEBUG(D_VFSTRACE, "VFS Op:inode="DFID"(%p), xattr %s\n",
+ CDEBUG(D_VFSTRACE, "VFS Op:inode=" DFID "(%p), xattr %s\n",
PFID(ll_inode2fid(inode)), inode, name);
if (!strcmp(name, "lov")) {
@@ -370,7 +370,7 @@ static int ll_xattr_get_common(const struct xattr_handler *handler,
#endif
int rc;
- CDEBUG(D_VFSTRACE, "VFS Op:inode="DFID"(%p)\n",
+ CDEBUG(D_VFSTRACE, "VFS Op:inode=" DFID "(%p)\n",
PFID(ll_inode2fid(inode)), inode);
ll_stats_ops_tally(ll_i2sbi(inode), LPROC_LL_GETXATTR, 1);
@@ -523,7 +523,7 @@ ssize_t ll_listxattr(struct dentry *dentry, char *buffer, size_t size)
LASSERT(inode);
- CDEBUG(D_VFSTRACE, "VFS Op:inode="DFID"(%p)\n",
+ CDEBUG(D_VFSTRACE, "VFS Op:inode=" DFID "(%p)\n",
PFID(ll_inode2fid(inode)), inode);
ll_stats_ops_tally(ll_i2sbi(inode), LPROC_LL_LISTXATTR, 1);
diff --git a/drivers/staging/lustre/lustre/llite/xattr_cache.c b/drivers/staging/lustre/lustre/llite/xattr_cache.c
index 38f75f6aa887..82cf4211cc0f 100644
--- a/drivers/staging/lustre/lustre/llite/xattr_cache.c
+++ b/drivers/staging/lustre/lustre/llite/xattr_cache.c
@@ -311,7 +311,7 @@ static int ll_xattr_find_get_lock(struct inode *inode,
if (rc < 0) {
CDEBUG(D_CACHE,
- "md_intent_lock failed with %d for fid "DFID"\n",
+ "md_intent_lock failed with %d for fid " DFID "\n",
rc, PFID(ll_inode2fid(inode)));
mutex_unlock(&lli->lli_xattrs_enq_lock);
return rc;
@@ -365,7 +365,7 @@ static int ll_xattr_cache_refill(struct inode *inode, struct lookup_intent *oit)
}
if (oit->it_status < 0) {
- CDEBUG(D_CACHE, "getxattr intent returned %d for fid "DFID"\n",
+ CDEBUG(D_CACHE, "getxattr intent returned %d for fid " DFID "\n",
oit->it_status, PFID(ll_inode2fid(inode)));
rc = oit->it_status;
/* xattr data is so large that we don't want to cache it */
diff --git a/drivers/staging/lustre/lustre/lmv/lmv_fld.c b/drivers/staging/lustre/lustre/lmv/lmv_fld.c
index a5265f9b5797..6f8070fb3226 100644
--- a/drivers/staging/lustre/lustre/lmv/lmv_fld.c
+++ b/drivers/staging/lustre/lustre/lmv/lmv_fld.c
@@ -70,7 +70,7 @@ int lmv_fld_lookup(struct lmv_obd *lmv, const struct lu_fid *fid, u32 *mds)
return rc;
}
- CDEBUG(D_INODE, "FLD lookup got mds #%x for fid="DFID"\n",
+ CDEBUG(D_INODE, "FLD lookup got mds #%x for fid=" DFID "\n",
*mds, PFID(fid));
if (*mds >= lmv->desc.ld_tgt_count) {
diff --git a/drivers/staging/lustre/lustre/lmv/lmv_intent.c b/drivers/staging/lustre/lustre/lmv/lmv_intent.c
index aa42066678e0..f49db6c23217 100644
--- a/drivers/staging/lustre/lustre/lmv/lmv_intent.c
+++ b/drivers/staging/lustre/lustre/lmv/lmv_intent.c
@@ -213,7 +213,7 @@ int lmv_revalidate_slaves(struct obd_export *exp,
lockh = (struct lustre_handle *)&it.it_lock_handle;
if (rc > 0 && !req) {
/* slave inode is still valid */
- CDEBUG(D_INODE, "slave "DFID" is still valid.\n",
+ CDEBUG(D_INODE, "slave " DFID " is still valid.\n",
PFID(&fid));
rc = 0;
} else {
@@ -435,7 +435,7 @@ static int lmv_intent_lookup(struct obd_export *exp,
if (IS_ERR(tgt))
return PTR_ERR(tgt);
- CDEBUG(D_INODE, "Try other stripes " DFID"\n",
+ CDEBUG(D_INODE, "Try other stripes " DFID "\n",
PFID(&oinfo->lmo_fid));
op_data->op_fid1 = oinfo->lmo_fid;
@@ -479,7 +479,7 @@ int lmv_intent_lock(struct obd_export *exp, struct md_op_data *op_data,
LASSERT(fid_is_sane(&op_data->op_fid1));
- CDEBUG(D_INODE, "INTENT LOCK '%s' for "DFID" '%*s' on "DFID"\n",
+ CDEBUG(D_INODE, "INTENT LOCK '%s' for " DFID " '%*s' on " DFID "\n",
LL_IT2STR(it), PFID(&op_data->op_fid2),
(int)op_data->op_namelen, op_data->op_name,
PFID(&op_data->op_fid1));
diff --git a/drivers/staging/lustre/lustre/lmv/lmv_obd.c b/drivers/staging/lustre/lustre/lmv/lmv_obd.c
index 732595125d8a..64fcaef0bacd 100644
--- a/drivers/staging/lustre/lustre/lmv/lmv_obd.c
+++ b/drivers/staging/lustre/lustre/lmv/lmv_obd.c
@@ -75,7 +75,7 @@ static void lmv_activate_target(struct lmv_obd *lmv,
static int lmv_set_mdc_active(struct lmv_obd *lmv, const struct obd_uuid *uuid,
int activate)
{
- struct lmv_tgt_desc *uninitialized_var(tgt);
+ struct lmv_tgt_desc *tgt = NULL;
struct obd_device *obd;
u32 i;
int rc = 0;
@@ -673,7 +673,7 @@ repeat_fid2path:
*ptr = '/';
}
- CDEBUG(D_INFO, "%s: get path %s "DFID" rec: %llu ln: %u\n",
+ CDEBUG(D_INFO, "%s: get path %s " DFID " rec: %llu ln: %u\n",
tgt->ltd_exp->exp_obd->obd_name,
gf->gf_path, PFID(&gf->gf_fid), gf->gf_recno,
gf->gf_linkno);
@@ -693,7 +693,7 @@ repeat_fid2path:
}
if (!fid_is_sane(&gf->gf_fid)) {
- CERROR("%s: invalid FID "DFID": rc = %d\n",
+ CERROR("%s: invalid FID " DFID ": rc = %d\n",
tgt->ltd_exp->exp_obd->obd_name,
PFID(&gf->gf_fid), -EINVAL);
rc = -EINVAL;
@@ -1508,7 +1508,7 @@ static int lmv_null_inode(struct obd_export *exp, const struct lu_fid *fid)
if (rc)
return rc;
- CDEBUG(D_INODE, "CBDATA for "DFID"\n", PFID(fid));
+ CDEBUG(D_INODE, "CBDATA for " DFID "\n", PFID(fid));
/*
* With DNE every object can have two locks in different namespaces:
@@ -1540,7 +1540,7 @@ static int lmv_close(struct obd_export *exp, struct md_op_data *op_data,
if (IS_ERR(tgt))
return PTR_ERR(tgt);
- CDEBUG(D_INODE, "CLOSE "DFID"\n", PFID(&op_data->op_fid1));
+ CDEBUG(D_INODE, "CLOSE " DFID "\n", PFID(&op_data->op_fid1));
return md_close(tgt->ltd_exp, op_data, mod, request);
}
@@ -1672,7 +1672,7 @@ static int lmv_create(struct obd_export *exp, struct md_op_data *op_data,
if (IS_ERR(tgt))
return PTR_ERR(tgt);
- CDEBUG(D_INODE, "CREATE name '%.*s' on "DFID" -> mds #%x\n",
+ CDEBUG(D_INODE, "CREATE name '%.*s' on " DFID " -> mds #%x\n",
(int)op_data->op_namelen, op_data->op_name,
PFID(&op_data->op_fid1), op_data->op_mds);
@@ -1694,7 +1694,7 @@ static int lmv_create(struct obd_export *exp, struct md_op_data *op_data,
CDEBUG(D_CONFIG, "Server doesn't support striped dirs\n");
}
- CDEBUG(D_INODE, "CREATE obj "DFID" -> mds #%x\n",
+ CDEBUG(D_INODE, "CREATE obj " DFID " -> mds #%x\n",
PFID(&op_data->op_fid1), op_data->op_mds);
op_data->op_flags |= MF_MDC_CANCEL_FID1;
@@ -1704,7 +1704,7 @@ static int lmv_create(struct obd_export *exp, struct md_op_data *op_data,
if (rc == 0) {
if (!*request)
return rc;
- CDEBUG(D_INODE, "Created - "DFID"\n", PFID(&op_data->op_fid2));
+ CDEBUG(D_INODE, "Created - " DFID "\n", PFID(&op_data->op_fid2));
}
return rc;
}
@@ -1724,7 +1724,7 @@ lmv_enqueue(struct obd_export *exp, struct ldlm_enqueue_info *einfo,
if (rc)
return rc;
- CDEBUG(D_INODE, "ENQUEUE '%s' on "DFID"\n",
+ CDEBUG(D_INODE, "ENQUEUE '%s' on " DFID "\n",
LL_IT2STR(it), PFID(&op_data->op_fid1));
tgt = lmv_locate_mds(lmv, op_data, &op_data->op_fid1);
@@ -1769,7 +1769,7 @@ lmv_getattr_name(struct obd_export *exp, struct md_op_data *op_data,
if (body->mbo_valid & OBD_MD_MDS) {
struct lu_fid rid = body->mbo_fid1;
- CDEBUG(D_INODE, "Request attrs for "DFID"\n",
+ CDEBUG(D_INODE, "Request attrs for " DFID "\n",
PFID(&rid));
tgt = lmv_find_target(lmv, &rid);
@@ -1818,13 +1818,13 @@ static int lmv_early_cancel(struct obd_export *exp, struct lmv_tgt_desc *tgt,
}
if (tgt->ltd_idx != op_tgt) {
- CDEBUG(D_INODE, "EARLY_CANCEL on "DFID"\n", PFID(fid));
+ CDEBUG(D_INODE, "EARLY_CANCEL on " DFID "\n", PFID(fid));
policy.l_inodebits.bits = bits;
rc = md_cancel_unused(tgt->ltd_exp, fid, &policy,
mode, LCF_ASYNC, NULL);
} else {
CDEBUG(D_INODE,
- "EARLY_CANCEL skip operation target %d on "DFID"\n",
+ "EARLY_CANCEL skip operation target %d on " DFID "\n",
op_tgt, PFID(fid));
op_data->op_flags |= flag;
rc = 0;
@@ -1851,7 +1851,7 @@ static int lmv_link(struct obd_export *exp, struct md_op_data *op_data,
LASSERT(op_data->op_namelen != 0);
- CDEBUG(D_INODE, "LINK "DFID":%*s to "DFID"\n",
+ CDEBUG(D_INODE, "LINK " DFID ":%*s to " DFID "\n",
PFID(&op_data->op_fid2), (int)op_data->op_namelen,
op_data->op_name, PFID(&op_data->op_fid1));
@@ -1901,7 +1901,7 @@ static int lmv_rename(struct obd_export *exp, struct md_op_data *op_data,
LASSERT(oldlen != 0);
- CDEBUG(D_INODE, "RENAME %.*s in "DFID":%d to %.*s in "DFID":%d\n",
+ CDEBUG(D_INODE, "RENAME %.*s in " DFID ":%d to %.*s in " DFID ":%d\n",
(int)oldlen, old, PFID(&op_data->op_fid1),
op_data->op_mea1 ? op_data->op_mea1->lsm_md_stripe_count : 0,
(int)newlen, new, PFID(&op_data->op_fid2),
@@ -1916,7 +1916,7 @@ static int lmv_rename(struct obd_export *exp, struct md_op_data *op_data,
op_data->op_cap = cfs_curproc_cap_pack();
if (op_data->op_cli_flags & CLI_MIGRATE) {
- LASSERTF(fid_is_sane(&op_data->op_fid3), "invalid FID "DFID"\n",
+ LASSERTF(fid_is_sane(&op_data->op_fid3), "invalid FID " DFID "\n",
PFID(&op_data->op_fid3));
if (op_data->op_mea1) {
@@ -2069,7 +2069,7 @@ static int lmv_setattr(struct obd_export *exp, struct md_op_data *op_data,
if (rc)
return rc;
- CDEBUG(D_INODE, "SETATTR for "DFID", valid 0x%x\n",
+ CDEBUG(D_INODE, "SETATTR for " DFID ", valid 0x%x\n",
PFID(&op_data->op_fid1), op_data->op_attr.ia_valid);
op_data->op_flags |= MF_MDC_CANCEL_FID1;
@@ -2274,6 +2274,7 @@ static int lmv_read_striped_page(struct obd_export *exp,
struct lu_fid master_fid = op_data->op_fid1;
struct obd_device *obd = exp->exp_obd;
__u64 hash_offset = offset;
+ __u32 ldp_flags;
struct page *min_ent_page = NULL;
struct page *ent_page = NULL;
struct lu_dirent *min_ent = NULL;
@@ -2301,7 +2302,7 @@ static int lmv_read_striped_page(struct obd_export *exp,
dp = kmap(ent_page);
memset(dp, 0, sizeof(*dp));
dp->ldp_hash_start = cpu_to_le64(offset);
- dp->ldp_flags |= LDF_COLLIDE;
+ ldp_flags = LDF_COLLIDE;
area = dp + 1;
left_bytes = PAGE_SIZE - sizeof(*dp);
@@ -2379,8 +2380,8 @@ out:
ent_page = NULL;
} else {
if (ent == area)
- dp->ldp_flags |= LDF_EMPTY;
- dp->ldp_flags = cpu_to_le32(dp->ldp_flags);
+ ldp_flags |= LDF_EMPTY;
+ dp->ldp_flags |= cpu_to_le32(ldp_flags);
dp->ldp_hash_end = cpu_to_le64(hash_offset);
}
@@ -2413,9 +2414,8 @@ static int lmv_read_page(struct obd_export *exp, struct md_op_data *op_data,
if (rc)
return rc;
- if (unlikely(lsm)) {
+ if (unlikely(lsm))
return lmv_read_striped_page(exp, op_data, cb_op, offset, ppage);
- }
tgt = lmv_find_target(lmv, &op_data->op_fid1);
if (IS_ERR(tgt))
@@ -2577,7 +2577,7 @@ try_next_stripe:
if (likely(!(body->mbo_valid & OBD_MD_MDS)))
return rc;
- CDEBUG(D_INODE, "%s: try unlink to another MDT for "DFID"\n",
+ CDEBUG(D_INODE, "%s: try unlink to another MDT for " DFID "\n",
exp->exp_obd->obd_name, PFID(&body->mbo_fid1));
/* This is a remote object, try remote MDT, Note: it may
@@ -2781,7 +2781,7 @@ static int lmv_unpack_md_v1(struct obd_export *exp, struct lmv_stripe_md *lsm,
&lsm->lsm_md_oinfo[i].lmo_mds);
if (rc)
return rc;
- CDEBUG(D_INFO, "unpack fid #%d "DFID"\n", i,
+ CDEBUG(D_INFO, "unpack fid #%d " DFID "\n", i,
PFID(&lsm->lsm_md_oinfo[i].lmo_fid));
}
@@ -2925,7 +2925,7 @@ static enum ldlm_mode lmv_lock_match(struct obd_export *exp, __u64 flags,
int tgt;
u32 i;
- CDEBUG(D_INODE, "Lock match for "DFID"\n", PFID(fid));
+ CDEBUG(D_INODE, "Lock match for " DFID "\n", PFID(fid));
/*
* With DNE every object can have two locks in different namespaces:
@@ -2937,7 +2937,7 @@ static enum ldlm_mode lmv_lock_match(struct obd_export *exp, __u64 flags,
i < lmv->desc.ld_tgt_count;
i++, tgt = (tgt + 1) % lmv->desc.ld_tgt_count) {
if (tgt < 0) {
- CDEBUG(D_HA, "%s: "DFID" is inaccessible: rc = %d\n",
+ CDEBUG(D_HA, "%s: " DFID " is inaccessible: rc = %d\n",
obd->obd_name, PFID(fid), tgt);
tgt = 0;
}
@@ -3107,9 +3107,8 @@ static int lmv_quotactl(struct obd_device *unused, struct obd_export *exp,
return -EIO;
}
- if (oqctl->qc_cmd != Q_GETOQUOTA) {
+ if (oqctl->qc_cmd != Q_GETOQUOTA)
return obd_quotactl(tgt->ltd_exp, oqctl);
- }
for (i = 0; i < lmv->desc.ld_tgt_count; i++) {
int err;
@@ -3149,7 +3148,7 @@ static int lmv_merge_attr(struct obd_export *exp,
for (i = 0; i < lsm->lsm_md_stripe_count; i++) {
struct inode *inode = lsm->lsm_md_oinfo[i].lmo_root;
- CDEBUG(D_INFO, ""DFID" size %llu, blocks %llu nlink %u, atime %lu ctime %lu, mtime %lu.\n",
+ CDEBUG(D_INFO, "" DFID " size %llu, blocks %llu nlink %u, atime %lu ctime %lu, mtime %lu.\n",
PFID(&lsm->lsm_md_oinfo[i].lmo_fid),
i_size_read(inode), (unsigned long long)inode->i_blocks,
inode->i_nlink, LTIME_S(inode->i_atime),
diff --git a/drivers/staging/lustre/lustre/lov/lov_cl_internal.h b/drivers/staging/lustre/lustre/lov/lov_cl_internal.h
index 391c632365ae..e889d3a7de9c 100644
--- a/drivers/staging/lustre/lustre/lov/lov_cl_internal.h
+++ b/drivers/staging/lustre/lustre/lov/lov_cl_internal.h
@@ -370,7 +370,7 @@ struct lov_thread_info {
struct ost_lvb lti_lvb;
struct cl_2queue lti_cl2q;
struct cl_page_list lti_plist;
- wait_queue_t lti_waiter;
+ wait_queue_entry_t lti_waiter;
struct cl_attr lti_attr;
};
diff --git a/drivers/staging/lustre/lustre/lov/lov_io.c b/drivers/staging/lustre/lustre/lov/lov_io.c
index df77b2586612..babf39adef85 100644
--- a/drivers/staging/lustre/lustre/lov/lov_io.c
+++ b/drivers/staging/lustre/lustre/lov/lov_io.c
@@ -1021,7 +1021,7 @@ int lov_io_init_empty(const struct lu_env *env, struct cl_object *obj,
break;
case CIT_FAULT:
result = -EFAULT;
- CERROR("Page fault on a file without stripes: "DFID"\n",
+ CERROR("Page fault on a file without stripes: " DFID "\n",
PFID(lu_object_fid(&obj->co_lu)));
break;
}
diff --git a/drivers/staging/lustre/lustre/lov/lov_merge.c b/drivers/staging/lustre/lustre/lov/lov_merge.c
index 391dfd207177..034b4fcb38f5 100644
--- a/drivers/staging/lustre/lustre/lov/lov_merge.c
+++ b/drivers/staging/lustre/lustre/lov/lov_merge.c
@@ -57,7 +57,7 @@ int lov_merge_lvb_kms(struct lov_stripe_md *lsm,
assert_spin_locked(&lsm->lsm_lock);
LASSERT(lsm->lsm_lock_owner == current_pid());
- CDEBUG(D_INODE, "MDT ID "DOSTID" initial value: s=%llu m=%llu a=%llu c=%llu b=%llu\n",
+ CDEBUG(D_INODE, "MDT ID " DOSTID " initial value: s=%llu m=%llu a=%llu c=%llu b=%llu\n",
POSTID(&lsm->lsm_oi), lvb->lvb_size, lvb->lvb_mtime,
lvb->lvb_atime, lvb->lvb_ctime, lvb->lvb_blocks);
for (i = 0; i < lsm->lsm_stripe_count; i++) {
@@ -89,7 +89,7 @@ int lov_merge_lvb_kms(struct lov_stripe_md *lsm,
if (loi->loi_lvb.lvb_ctime > current_ctime)
current_ctime = loi->loi_lvb.lvb_ctime;
- CDEBUG(D_INODE, "MDT ID "DOSTID" on OST[%u]: s=%llu m=%llu a=%llu c=%llu b=%llu\n",
+ CDEBUG(D_INODE, "MDT ID " DOSTID " on OST[%u]: s=%llu m=%llu a=%llu c=%llu b=%llu\n",
POSTID(&lsm->lsm_oi), loi->loi_ost_idx,
loi->loi_lvb.lvb_size, loi->loi_lvb.lvb_mtime,
loi->loi_lvb.lvb_atime, loi->loi_lvb.lvb_ctime,
diff --git a/drivers/staging/lustre/lustre/lov/lov_object.c b/drivers/staging/lustre/lustre/lov/lov_object.c
index ab3ecfeeadc8..14f38268d414 100644
--- a/drivers/staging/lustre/lustre/lov/lov_object.c
+++ b/drivers/staging/lustre/lustre/lov/lov_object.c
@@ -153,8 +153,7 @@ static int lov_init_sub(const struct lu_env *env, struct lov_object *lov,
subhdr = cl_object_header(stripe);
oinfo = lov->lo_lsm->lsm_oinfo[idx];
- CDEBUG(D_INODE, DFID"@%p[%d] -> "DFID"@%p: ostid: "DOSTID
- " idx: %d gen: %d\n",
+ CDEBUG(D_INODE, DFID "@%p[%d] -> " DFID "@%p: ostid: " DOSTID " idx: %d gen: %d\n",
PFID(&subhdr->coh_lu.loh_fid), subhdr, idx,
PFID(&hdr->coh_lu.loh_fid), hdr, POSTID(&oinfo->loi_oi),
oinfo->loi_ost_idx, oinfo->loi_ost_gen);
@@ -371,7 +370,7 @@ static void lov_subobject_kill(const struct lu_env *env, struct lov_object *lov,
struct lov_layout_raid0 *r0;
struct lu_site *site;
struct lu_site_bkt_data *bkt;
- wait_queue_t *waiter;
+ wait_queue_entry_t *waiter;
r0 = &lov->u.raid0;
LASSERT(r0->lo_sub[idx] == los);
@@ -757,7 +756,7 @@ static int lov_layout_change(const struct lu_env *unused,
LASSERT(0 <= llt && llt < ARRAY_SIZE(lov_dispatch));
- CDEBUG(D_INODE, DFID" from %s to %s\n",
+ CDEBUG(D_INODE, DFID " from %s to %s\n",
PFID(lu_object_fid(lov2lu(lov))),
llt2str(lov->lo_type), llt2str(llt));
@@ -904,7 +903,7 @@ static int lov_conf_set(const struct lu_env *env, struct cl_object *obj,
out:
lov_conf_unlock(lov);
lov_lsm_put(lsm);
- CDEBUG(D_INODE, DFID" lo_layout_invalid=%d\n",
+ CDEBUG(D_INODE, DFID " lo_layout_invalid=%d\n",
PFID(lu_object_fid(lov2lu(lov))), lov->lo_layout_invalid);
return result;
}
diff --git a/drivers/staging/lustre/lustre/lov/lov_pack.c b/drivers/staging/lustre/lustre/lov/lov_pack.c
index 2e1bd47337fd..638b7646ca2c 100644
--- a/drivers/staging/lustre/lustre/lov/lov_pack.c
+++ b/drivers/staging/lustre/lustre/lov/lov_pack.c
@@ -56,7 +56,7 @@ void lov_dump_lmm_common(int level, void *lmmp)
struct ost_id oi;
lmm_oi_le_to_cpu(&oi, &lmm->lmm_oi);
- CDEBUG(level, "objid "DOSTID", magic 0x%08x, pattern %#x\n",
+ CDEBUG(level, "objid " DOSTID ", magic 0x%08x, pattern %#x\n",
POSTID(&oi), le32_to_cpu(lmm->lmm_magic),
le32_to_cpu(lmm->lmm_pattern));
CDEBUG(level, "stripe_size %u, stripe_count %u, layout_gen %u\n",
@@ -80,7 +80,7 @@ static void lov_dump_lmm_objects(int level, struct lov_ost_data *lod,
struct ost_id oi;
ostid_le_to_cpu(&lod->l_ost_oi, &oi);
- CDEBUG(level, "stripe %u idx %u subobj "DOSTID"\n", i,
+ CDEBUG(level, "stripe %u idx %u subobj " DOSTID "\n", i,
le32_to_cpu(lod->l_ost_idx), POSTID(&oi));
}
}
@@ -95,7 +95,7 @@ void lov_dump_lmm_v1(int level, struct lov_mds_md_v1 *lmm)
void lov_dump_lmm_v3(int level, struct lov_mds_md_v3 *lmm)
{
lov_dump_lmm_common(level, lmm);
- CDEBUG(level, "pool_name "LOV_POOLNAMEF"\n", lmm->lmm_pool_name);
+ CDEBUG(level, "pool_name " LOV_POOLNAMEF "\n", lmm->lmm_pool_name);
lov_dump_lmm_objects(level, lmm->lmm_objects,
le16_to_cpu(lmm->lmm_stripe_count));
}
@@ -293,18 +293,10 @@ int lov_getstripe(struct lov_object *obj, struct lov_stripe_md *lsm,
size_t lmmk_size;
size_t lum_size;
int rc;
- mm_segment_t seg;
if (!lsm)
return -ENODATA;
- /*
- * "Switch to kernel segment" to allow copying from kernel space by
- * copy_{to,from}_user().
- */
- seg = get_fs();
- set_fs(KERNEL_DS);
-
if (lsm->lsm_magic != LOV_MAGIC_V1 && lsm->lsm_magic != LOV_MAGIC_V3) {
CERROR("bad LSM MAGIC: 0x%08X != 0x%08X nor 0x%08X\n",
lsm->lsm_magic, LOV_MAGIC_V1, LOV_MAGIC_V3);
@@ -406,6 +398,5 @@ int lov_getstripe(struct lov_object *obj, struct lov_stripe_md *lsm,
out_free:
kvfree(lmmk);
out:
- set_fs(seg);
return rc;
}
diff --git a/drivers/staging/lustre/lustre/lov/lov_pool.c b/drivers/staging/lustre/lustre/lov/lov_pool.c
index 7daa8671fdc3..39daa17e0736 100644
--- a/drivers/staging/lustre/lustre/lov/lov_pool.c
+++ b/drivers/staging/lustre/lustre/lov/lov_pool.c
@@ -286,7 +286,7 @@ static int pool_proc_open(struct inode *inode, struct file *file)
return rc;
}
-static struct file_operations pool_proc_operations = {
+static const struct file_operations pool_proc_operations = {
.open = pool_proc_open,
.read = seq_read,
.llseek = seq_lseek,
@@ -429,7 +429,7 @@ int lov_pool_new(struct obd_device *obd, char *poolname)
poolname, new_pool,
&pool_proc_operations);
if (IS_ERR_OR_NULL(new_pool->pool_debugfs_entry)) {
- CWARN("Cannot add debugfs pool entry "LOV_POOLNAMEF"\n",
+ CWARN("Cannot add debugfs pool entry " LOV_POOLNAMEF "\n",
poolname);
new_pool->pool_debugfs_entry = NULL;
lov_pool_putref(new_pool);
@@ -450,7 +450,7 @@ int lov_pool_new(struct obd_device *obd, char *poolname)
goto out_err;
}
- CDEBUG(D_CONFIG, LOV_POOLNAMEF" is pool #%d\n",
+ CDEBUG(D_CONFIG, LOV_POOLNAMEF " is pool #%d\n",
poolname, lov->lov_pool_count);
return 0;
@@ -531,7 +531,7 @@ int lov_pool_add(struct obd_device *obd, char *poolname, char *ostname)
if (rc)
goto out;
- CDEBUG(D_CONFIG, "Added %s to "LOV_POOLNAMEF" as member %d\n",
+ CDEBUG(D_CONFIG, "Added %s to " LOV_POOLNAMEF " as member %d\n",
ostname, poolname, pool_tgt_count(pool));
out:
@@ -575,7 +575,7 @@ int lov_pool_remove(struct obd_device *obd, char *poolname, char *ostname)
lov_ost_pool_remove(&pool->pool_obds, lov_idx);
- CDEBUG(D_CONFIG, "%s removed from "LOV_POOLNAMEF"\n", ostname,
+ CDEBUG(D_CONFIG, "%s removed from " LOV_POOLNAMEF "\n", ostname,
poolname);
out:
diff --git a/drivers/staging/lustre/lustre/mdc/mdc_locks.c b/drivers/staging/lustre/lustre/mdc/mdc_locks.c
index 392b0e38a91e..3eb66cea65db 100644
--- a/drivers/staging/lustre/lustre/mdc/mdc_locks.c
+++ b/drivers/staging/lustre/lustre/mdc/mdc_locks.c
@@ -830,7 +830,7 @@ resend:
ptlrpc_req_finished(req);
resends++;
- CDEBUG(D_HA, "%s: resend:%d op:%d "DFID"/"DFID"\n",
+ CDEBUG(D_HA, "%s: resend:%d op:%d " DFID "/" DFID "\n",
obddev->obd_name, resends, it->it_op,
PFID(&op_data->op_fid1), PFID(&op_data->op_fid2));
@@ -911,13 +911,13 @@ static int mdc_finish_intent_lock(struct obd_export *exp,
OBD_FAIL_TIMEOUT(OBD_FAIL_MDC_ENQUEUE_PAUSE, obd_timeout);
}
- if (it->it_op & IT_CREAT) {
+ if (it->it_op & IT_CREAT)
/* XXX this belongs in ll_create_it */
- } else if (it->it_op == IT_OPEN) {
+ ;
+ else if (it->it_op == IT_OPEN)
LASSERT(!it_disposition(it, DISP_OPEN_CREATE));
- } else {
+ else
LASSERT(it->it_op & (IT_GETATTR | IT_LOOKUP | IT_LAYOUT));
- }
/* If we already have a matching lock, then cancel the new
* one. We have to set the data here instead of in
@@ -933,7 +933,7 @@ static int mdc_finish_intent_lock(struct obd_export *exp,
LASSERTF(fid_res_name_eq(&mdt_body->mbo_fid1,
&lock->l_resource->lr_name),
- "Lock res_id: "DLDLMRES", fid: "DFID"\n",
+ "Lock res_id: " DLDLMRES ", fid: " DFID "\n",
PLDLMRES(lock->l_resource), PFID(&mdt_body->mbo_fid1));
LDLM_LOCK_PUT(lock);
@@ -1063,7 +1063,7 @@ int mdc_intent_lock(struct obd_export *exp, struct md_op_data *op_data,
LASSERT(it);
- CDEBUG(D_DLMTRACE, "(name: %.*s,"DFID") in obj "DFID
+ CDEBUG(D_DLMTRACE, "(name: %.*s," DFID ") in obj " DFID
", intent: %s flags %#Lo\n", (int)op_data->op_namelen,
op_data->op_name, PFID(&op_data->op_fid2),
PFID(&op_data->op_fid1), ldlm_it2str(it->it_op),
diff --git a/drivers/staging/lustre/lustre/mdc/mdc_reint.c b/drivers/staging/lustre/lustre/mdc/mdc_reint.c
index 07b168490f09..2287bd46d527 100644
--- a/drivers/staging/lustre/lustre/mdc/mdc_reint.c
+++ b/drivers/staging/lustre/lustre/mdc/mdc_reint.c
@@ -227,7 +227,7 @@ rebuild:
ptlrpc_req_finished(req);
resends++;
- CDEBUG(D_HA, "%s: resend:%d create on "DFID"/"DFID"\n",
+ CDEBUG(D_HA, "%s: resend:%d create on " DFID "/" DFID "\n",
exp->exp_obd->obd_name, resends,
PFID(&op_data->op_fid1), PFID(&op_data->op_fid2));
diff --git a/drivers/staging/lustre/lustre/mdc/mdc_request.c b/drivers/staging/lustre/lustre/mdc/mdc_request.c
index 6bc2fb858680..1a3fa1bb7f25 100644
--- a/drivers/staging/lustre/lustre/mdc/mdc_request.c
+++ b/drivers/staging/lustre/lustre/mdc/mdc_request.c
@@ -105,7 +105,7 @@ static int mdc_getstatus(struct obd_export *exp, struct lu_fid *rootfid)
*rootfid = body->mbo_fid1;
CDEBUG(D_NET,
- "root fid="DFID", last_committed=%llu\n",
+ "root fid=" DFID ", last_committed=%llu\n",
PFID(rootfid),
lustre_msg_get_last_committed(req->rq_repmsg));
out:
@@ -713,7 +713,7 @@ static int mdc_close(struct obd_export *exp, struct md_op_data *op_data,
/* allocate a FID for volatile file */
rc = mdc_fid_alloc(NULL, exp, &op_data->op_fid2, op_data);
if (rc < 0) {
- CERROR("%s: "DFID" failed to allocate FID: %d\n",
+ CERROR("%s: " DFID " failed to allocate FID: %d\n",
obd->obd_name, PFID(&op_data->op_fid1), rc);
/* save the errcode and proceed to close */
saved_rc = rc;
@@ -753,7 +753,7 @@ static int mdc_close(struct obd_export *exp, struct md_op_data *op_data,
/*
* TODO: repeat close after errors
*/
- CWARN("%s: close of FID "DFID" failed, file reference will be dropped when this client unmounts or is evicted\n",
+ CWARN("%s: close of FID " DFID " failed, file reference will be dropped when this client unmounts or is evicted\n",
obd->obd_name, PFID(&op_data->op_fid1));
rc = -ENOMEM;
goto out;
@@ -1254,7 +1254,7 @@ static int mdc_read_page(struct obd_export *exp, struct md_op_data *op_data,
ptlrpc_req_finished(enq_req);
if (rc < 0) {
- CERROR("%s: "DFID" lock enqueue fails: rc = %d\n",
+ CERROR("%s: " DFID " lock enqueue fails: rc = %d\n",
exp->exp_obd->obd_name, PFID(&op_data->op_fid1), rc);
return rc;
}
@@ -1298,7 +1298,7 @@ static int mdc_read_page(struct obd_export *exp, struct md_op_data *op_data,
rp_param.rp_hash64),
mdc_read_page_remote, &rp_param);
if (IS_ERR(page)) {
- CERROR("%s: read cache page: "DFID" at %llu: rc %ld\n",
+ CERROR("%s: read cache page: " DFID " at %llu: rc %ld\n",
exp->exp_obd->obd_name, PFID(&op_data->op_fid1),
rp_param.rp_off, PTR_ERR(page));
rc = PTR_ERR(page);
@@ -1308,7 +1308,7 @@ static int mdc_read_page(struct obd_export *exp, struct md_op_data *op_data,
wait_on_page_locked(page);
(void)kmap(page);
if (!PageUptodate(page)) {
- CERROR("%s: page not updated: "DFID" at %llu: rc %d\n",
+ CERROR("%s: page not updated: " DFID " at %llu: rc %d\n",
exp->exp_obd->obd_name, PFID(&op_data->op_fid1),
rp_param.rp_off, -5);
goto fail;
@@ -1316,7 +1316,7 @@ static int mdc_read_page(struct obd_export *exp, struct md_op_data *op_data,
if (!PageChecked(page))
SetPageChecked(page);
if (PageError(page)) {
- CERROR("%s: page error: "DFID" at %llu: rc %d\n",
+ CERROR("%s: page error: " DFID " at %llu: rc %d\n",
exp->exp_obd->obd_name, PFID(&op_data->op_fid1),
rp_param.rp_off, -5);
goto fail;
@@ -1436,7 +1436,7 @@ static int mdc_ioc_fid2path(struct obd_export *exp, struct getinfo_fid2path *gf)
memcpy(key, KEY_FID2PATH, sizeof(KEY_FID2PATH));
memcpy(key + cfs_size_round(sizeof(KEY_FID2PATH)), gf, sizeof(*gf));
- CDEBUG(D_IOCTL, "path get "DFID" from %llu #%d\n",
+ CDEBUG(D_IOCTL, "path get " DFID " from %llu #%d\n",
PFID(&gf->gf_fid), gf->gf_recno, gf->gf_linkno);
if (!fid_is_sane(&gf->gf_fid)) {
diff --git a/drivers/staging/lustre/lustre/mgc/mgc_request.c b/drivers/staging/lustre/lustre/mgc/mgc_request.c
index 6a76605b3c3d..eee0b667a33c 100644
--- a/drivers/staging/lustre/lustre/mgc/mgc_request.c
+++ b/drivers/staging/lustre/lustre/mgc/mgc_request.c
@@ -800,7 +800,7 @@ static int mgc_blocking_ast(struct ldlm_lock *lock, struct ldlm_lock_desc *desc,
/* We've given up the lock, prepare ourselves to update. */
LDLM_DEBUG(lock, "MGC cancel CB");
- CDEBUG(D_MGC, "Lock res "DLDLMRES" (%.8s)\n",
+ CDEBUG(D_MGC, "Lock res " DLDLMRES " (%.8s)\n",
PLDLMRES(lock->l_resource),
(char *)&lock->l_resource->lr_name.name[0]);
diff --git a/drivers/staging/lustre/lustre/obdclass/cl_lock.c b/drivers/staging/lustre/lustre/obdclass/cl_lock.c
index 9d7b5939b0fd..a343e3ab2257 100644
--- a/drivers/staging/lustre/lustre/obdclass/cl_lock.c
+++ b/drivers/staging/lustre/lustre/obdclass/cl_lock.c
@@ -246,7 +246,7 @@ void cl_lock_descr_print(const struct lu_env *env, void *cookie,
const struct lu_fid *fid;
fid = lu_object_fid(&descr->cld_obj->co_lu);
- (*printer)(env, cookie, DDESCR"@"DFID, PDESCR(descr), PFID(fid));
+ (*printer)(env, cookie, DDESCR "@" DFID, PDESCR(descr), PFID(fid));
}
EXPORT_SYMBOL(cl_lock_descr_print);
diff --git a/drivers/staging/lustre/lustre/obdclass/cl_page.c b/drivers/staging/lustre/lustre/obdclass/cl_page.c
index 71fcc4cc9e72..6b8c41b6f379 100644
--- a/drivers/staging/lustre/lustre/obdclass/cl_page.c
+++ b/drivers/staging/lustre/lustre/obdclass/cl_page.c
@@ -193,7 +193,7 @@ struct cl_page *cl_page_find(const struct lu_env *env,
hdr = cl_object_header(o);
- CDEBUG(D_PAGE, "%lu@"DFID" %p %lx %d\n",
+ CDEBUG(D_PAGE, "%lu@" DFID " %p %lx %d\n",
idx, PFID(&hdr->coh_lu.loh_fid), vmpage, vmpage->private, type);
/* fast path. */
if (type == CPT_CACHEABLE) {
diff --git a/drivers/staging/lustre/lustre/obdclass/llog_cat.c b/drivers/staging/lustre/lustre/obdclass/llog_cat.c
index ce8e2f6f002a..8f1533c127a8 100644
--- a/drivers/staging/lustre/lustre/obdclass/llog_cat.c
+++ b/drivers/staging/lustre/lustre/obdclass/llog_cat.c
@@ -78,7 +78,7 @@ static int llog_cat_id2handle(const struct lu_env *env,
if (ostid_id(&cgl->lgl_oi) == ostid_id(&logid->lgl_oi) &&
ostid_seq(&cgl->lgl_oi) == ostid_seq(&logid->lgl_oi)) {
if (cgl->lgl_ogen != logid->lgl_ogen) {
- CERROR("%s: log "DOSTID" generation %x != %x\n",
+ CERROR("%s: log " DOSTID " generation %x != %x\n",
loghandle->lgh_ctxt->loc_obd->obd_name,
POSTID(&logid->lgl_oi), cgl->lgl_ogen,
logid->lgl_ogen);
@@ -95,7 +95,7 @@ static int llog_cat_id2handle(const struct lu_env *env,
rc = llog_open(env, cathandle->lgh_ctxt, &loghandle, logid, NULL,
LLOG_OPEN_EXISTS);
if (rc < 0) {
- CERROR("%s: error opening log id "DOSTID":%x: rc = %d\n",
+ CERROR("%s: error opening log id " DOSTID ":%x: rc = %d\n",
cathandle->lgh_ctxt->loc_obd->obd_name,
POSTID(&logid->lgl_oi), logid->lgl_ogen, rc);
return rc;
@@ -152,13 +152,13 @@ static int llog_cat_process_cb(const struct lu_env *env,
CERROR("invalid record in catalog\n");
return -EINVAL;
}
- CDEBUG(D_HA, "processing log "DOSTID":%x at index %u of catalog "
- DOSTID"\n", POSTID(&lir->lid_id.lgl_oi), lir->lid_id.lgl_ogen,
+ CDEBUG(D_HA, "processing log " DOSTID ":%x at index %u of catalog "
+ DOSTID "\n", POSTID(&lir->lid_id.lgl_oi), lir->lid_id.lgl_ogen,
rec->lrh_index, POSTID(&cat_llh->lgh_id.lgl_oi));
rc = llog_cat_id2handle(env, cat_llh, &llh, &lir->lid_id);
if (rc) {
- CERROR("%s: cannot find handle for llog "DOSTID": %d\n",
+ CERROR("%s: cannot find handle for llog " DOSTID ": %d\n",
cat_llh->lgh_ctxt->loc_obd->obd_name,
POSTID(&lir->lid_id.lgl_oi), rc);
return rc;
@@ -204,7 +204,7 @@ static int llog_cat_process_or_fork(const struct lu_env *env,
if (llh->llh_cat_idx > cat_llh->lgh_last_idx) {
struct llog_process_cat_data cd;
- CWARN("catlog "DOSTID" crosses index zero\n",
+ CWARN("catlog " DOSTID " crosses index zero\n",
POSTID(&cat_llh->lgh_id.lgl_oi));
cd.lpcd_first_idx = llh->llh_cat_idx;
diff --git a/drivers/staging/lustre/lustre/obdclass/llog_swab.c b/drivers/staging/lustre/lustre/obdclass/llog_swab.c
index 723c212c6747..016046d26010 100644
--- a/drivers/staging/lustre/lustre/obdclass/llog_swab.c
+++ b/drivers/staging/lustre/lustre/obdclass/llog_swab.c
@@ -44,7 +44,7 @@
static void print_llogd_body(struct llogd_body *d)
{
CDEBUG(D_OTHER, "llogd body: %p\n", d);
- CDEBUG(D_OTHER, "\tlgd_logid.lgl_oi: "DOSTID"\n",
+ CDEBUG(D_OTHER, "\tlgd_logid.lgl_oi: " DOSTID "\n",
POSTID(&d->lgd_logid.lgl_oi));
CDEBUG(D_OTHER, "\tlgd_logid.lgl_ogen: %#x\n", d->lgd_logid.lgl_ogen);
CDEBUG(D_OTHER, "\tlgd_ctxt_idx: %#x\n", d->lgd_ctxt_idx);
diff --git a/drivers/staging/lustre/lustre/obdclass/lprocfs_status.c b/drivers/staging/lustre/lustre/obdclass/lprocfs_status.c
index 1ec6e3767d81..bc19f19d38d9 100644
--- a/drivers/staging/lustre/lustre/obdclass/lprocfs_status.c
+++ b/drivers/staging/lustre/lustre/obdclass/lprocfs_status.c
@@ -301,7 +301,7 @@ EXPORT_SYMBOL(lprocfs_seq_release);
struct dentry *ldebugfs_add_simple(struct dentry *root,
char *name, void *data,
- struct file_operations *fops)
+ const struct file_operations *fops)
{
struct dentry *entry;
umode_t mode = 0;
@@ -389,40 +389,6 @@ out:
EXPORT_SYMBOL_GPL(ldebugfs_register);
/* Generic callbacks */
-int lprocfs_rd_uint(struct seq_file *m, void *data)
-{
- seq_printf(m, "%u\n", *(unsigned int *)data);
- return 0;
-}
-EXPORT_SYMBOL(lprocfs_rd_uint);
-
-int lprocfs_wr_uint(struct file *file, const char __user *buffer,
- unsigned long count, void *data)
-{
- unsigned *p = data;
- char dummy[MAX_STRING_SIZE + 1], *end;
- unsigned long tmp;
-
- if (count >= sizeof(dummy))
- return -EINVAL;
-
- if (count == 0)
- return 0;
-
- if (copy_from_user(dummy, buffer, count))
- return -EFAULT;
-
- dummy[count] = '\0';
-
- tmp = simple_strtoul(dummy, &end, 0);
- if (dummy == end)
- return -EINVAL;
-
- *p = (unsigned int)tmp;
- return count;
-}
-EXPORT_SYMBOL(lprocfs_wr_uint);
-
static ssize_t uuid_show(struct kobject *kobj, struct attribute *attr,
char *buf)
{
@@ -736,7 +702,7 @@ static int obd_import_flags2str(struct obd_import *imp, struct seq_file *m)
bool first = true;
if (imp->imp_obd->obd_no_recov) {
- seq_printf(m, "no_recov");
+ seq_puts(m, "no_recov");
first = false;
}
@@ -802,15 +768,15 @@ int lprocfs_rd_import(struct seq_file *m, void *data)
imp->imp_connect_data.ocd_instance);
obd_connect_seq_flags2str(m, imp->imp_connect_data.ocd_connect_flags,
", ");
- seq_printf(m, " ]\n");
+ seq_puts(m, " ]\n");
obd_connect_data_seqprint(m, ocd);
- seq_printf(m, " import_flags: [ ");
+ seq_puts(m, " import_flags: [ ");
obd_import_flags2str(imp, m);
- seq_printf(m,
- " ]\n"
- " connection:\n"
- " failover_nids: [ ");
+ seq_puts(m,
+ " ]\n"
+ " connection:\n"
+ " failover_nids: [ ");
spin_lock(&imp->imp_lock);
j = 0;
list_for_each_entry(conn, &imp->imp_conn_list, oic_item) {
@@ -943,7 +909,7 @@ int lprocfs_rd_state(struct seq_file *m, void *data)
seq_printf(m, "current_state: %s\n",
ptlrpc_import_state_name(imp->imp_state));
- seq_printf(m, "state_history:\n");
+ seq_puts(m, "state_history:\n");
k = imp->imp_state_hist_idx;
for (j = 0; j < IMP_STATE_HIST_LEN; j++) {
struct import_state_hist *ish =
@@ -965,7 +931,7 @@ int lprocfs_at_hist_helper(struct seq_file *m, struct adaptive_timeout *at)
for (i = 0; i < AT_BINS; i++)
seq_printf(m, "%3u ", at->at_hist[i]);
- seq_printf(m, "\n");
+ seq_puts(m, "\n");
return 0;
}
EXPORT_SYMBOL(lprocfs_at_hist_helper);
@@ -1033,7 +999,7 @@ int lprocfs_rd_connect_flags(struct seq_file *m, void *data)
flags = obd->u.cli.cl_import->imp_connect_data.ocd_connect_flags;
seq_printf(m, "flags=%#llx\n", flags);
obd_connect_seq_flags2str(m, flags, "\n");
- seq_printf(m, "\n");
+ seq_puts(m, "\n");
up_read(&obd->u.cli.cl_sem);
return 0;
}
diff --git a/drivers/staging/lustre/lustre/obdclass/lu_object.c b/drivers/staging/lustre/lustre/obdclass/lu_object.c
index abcf951208d2..bb9d514525ce 100644
--- a/drivers/staging/lustre/lustre/obdclass/lu_object.c
+++ b/drivers/staging/lustre/lustre/obdclass/lu_object.c
@@ -512,7 +512,7 @@ void lu_object_header_print(const struct lu_env *env, void *cookie,
lu_printer_t printer,
const struct lu_object_header *hdr)
{
- (*printer)(env, cookie, "header@%p[%#lx, %d, "DFID"%s%s%s]",
+ (*printer)(env, cookie, "header@%p[%#lx, %d, " DFID "%s%s%s]",
hdr, hdr->loh_flags, atomic_read(&hdr->loh_ref),
PFID(&hdr->loh_fid),
hlist_unhashed(&hdr->loh_hash) ? "" : " hash",
@@ -556,7 +556,7 @@ EXPORT_SYMBOL(lu_object_print);
static struct lu_object *htable_lookup(struct lu_site *s,
struct cfs_hash_bd *bd,
const struct lu_fid *f,
- wait_queue_t *waiter,
+ wait_queue_entry_t *waiter,
__u64 *version)
{
struct lu_site_bkt_data *bkt;
@@ -670,7 +670,7 @@ static struct lu_object *lu_object_find_try(const struct lu_env *env,
struct lu_device *dev,
const struct lu_fid *f,
const struct lu_object_conf *conf,
- wait_queue_t *waiter)
+ wait_queue_entry_t *waiter)
{
struct lu_object *o;
struct lu_object *shadow;
@@ -750,7 +750,7 @@ struct lu_object *lu_object_find_at(const struct lu_env *env,
{
struct lu_site_bkt_data *bkt;
struct lu_object *obj;
- wait_queue_t wait;
+ wait_queue_entry_t wait;
while (1) {
obj = lu_object_find_try(env, dev, f, conf, &wait);
@@ -918,9 +918,8 @@ static unsigned long lu_htable_order(struct lu_device *top)
cache_size = cache_size / 100 * lu_cache_percent *
(PAGE_SIZE / 1024);
- for (bits = 1; (1 << bits) < cache_size; ++bits) {
+ for (bits = 1; (1 << bits) < cache_size; ++bits)
;
- }
return clamp_t(typeof(bits), bits, LU_SITE_BITS_MIN, bits_max);
}
diff --git a/drivers/staging/lustre/lustre/obdecho/echo_client.c b/drivers/staging/lustre/lustre/obdecho/echo_client.c
index 77b4c5504689..1c4a8fe87dd8 100644
--- a/drivers/staging/lustre/lustre/obdecho/echo_client.c
+++ b/drivers/staging/lustre/lustre/obdecho/echo_client.c
@@ -277,7 +277,7 @@ static int echo_page_print(const struct lu_env *env,
{
struct echo_page *ep = cl2echo_page(slice);
- (*printer)(env, cookie, LUSTRE_ECHO_CLIENT_NAME"-page@%p %d vm@%p\n",
+ (*printer)(env, cookie, LUSTRE_ECHO_CLIENT_NAME "-page@%p %d vm@%p\n",
ep, mutex_is_locked(&ep->ep_lock),
slice->cpl_page->cp_vmpage);
return 0;
@@ -1121,7 +1121,7 @@ static int echo_create_object(const struct lu_env *env, struct echo_device *ed,
}
cl_echo_object_put(eco);
- CDEBUG(D_INFO, "oa oid "DOSTID"\n", POSTID(&oa->o_oi));
+ CDEBUG(D_INFO, "oa oid " DOSTID "\n", POSTID(&oa->o_oi));
failed:
if (created && rc)
@@ -1646,9 +1646,8 @@ static int echo_client_connect(const struct lu_env *env,
struct lustre_handle conn = { 0 };
rc = class_connect(&conn, src, cluuid);
- if (rc == 0) {
+ if (rc == 0)
*exp = class_conn2export(&conn);
- }
return rc;
}
diff --git a/drivers/staging/lustre/lustre/osc/osc_cache.c b/drivers/staging/lustre/lustre/osc/osc_cache.c
index c5ccf568313a..d8a95f8fe1ff 100644
--- a/drivers/staging/lustre/lustre/osc/osc_cache.c
+++ b/drivers/staging/lustre/lustre/osc/osc_cache.c
@@ -472,7 +472,7 @@ static void osc_extent_insert(struct osc_object *obj, struct osc_extent *ext)
else if (ext->oe_start > tmp->oe_end)
n = &(*n)->rb_right;
else
- EASSERTF(0, tmp, EXTSTR"\n", EXTPARA(ext));
+ EASSERTF(0, tmp, EXTSTR "\n", EXTPARA(ext));
}
rb_link_node(&ext->oe_node, parent, n);
rb_insert_color(&ext->oe_node, &obj->oo_root);
@@ -690,7 +690,7 @@ static struct osc_extent *osc_extent_find(const struct lu_env *env,
/* grants has been allocated by caller */
LASSERTF(*grants >= chunksize + cli->cl_extent_tax,
"%u/%u/%u.\n", *grants, chunksize, cli->cl_extent_tax);
- LASSERTF((max_end - cur->oe_start) < max_pages, EXTSTR"\n",
+ LASSERTF((max_end - cur->oe_start) < max_pages, EXTSTR "\n",
EXTPARA(cur));
restart:
@@ -709,7 +709,7 @@ restart:
/* if covering by different locks, no chance to match */
if (olck->ols_dlmlock != ext->oe_dlmlock) {
EASSERTF(!overlapped(ext, cur), ext,
- EXTSTR"\n", EXTPARA(cur));
+ EXTSTR "\n", EXTPARA(cur));
ext = next_extent(ext);
continue;
@@ -732,7 +732,7 @@ restart:
*/
EASSERTF((ext->oe_start <= cur->oe_start &&
ext->oe_end >= cur->oe_end),
- ext, EXTSTR"\n", EXTPARA(cur));
+ ext, EXTSTR "\n", EXTPARA(cur));
if (ext->oe_state > OES_CACHE || ext->oe_fsync_wait) {
/* for simplicity, we wait for this extent to
@@ -1406,9 +1406,8 @@ static void osc_release_write_grant(struct client_obd *cli,
struct brw_page *pga)
{
assert_spin_locked(&cli->cl_loi_list_lock);
- if (!(pga->flag & OBD_BRW_FROM_GRANT)) {
+ if (!(pga->flag & OBD_BRW_FROM_GRANT))
return;
- }
pga->flag &= ~OBD_BRW_FROM_GRANT;
atomic_long_dec(&obd_dirty_pages);
@@ -1890,10 +1889,10 @@ struct extent_rpc_data {
unsigned int erd_max_chunks;
};
-static inline unsigned osc_extent_chunks(const struct osc_extent *ext)
+static inline unsigned int osc_extent_chunks(const struct osc_extent *ext)
{
struct client_obd *cli = osc_cli(ext->oe_obj);
- unsigned ppc_bits = cli->cl_chunkbits - PAGE_SHIFT;
+ unsigned int ppc_bits = cli->cl_chunkbits - PAGE_SHIFT;
return (ext->oe_end >> ppc_bits) - (ext->oe_start >> ppc_bits) + 1;
}
@@ -1951,7 +1950,7 @@ static int try_to_add_extent_for_io(struct client_obd *cli,
return 1;
}
-static inline unsigned osc_max_write_chunks(const struct client_obd *cli)
+static inline unsigned int osc_max_write_chunks(const struct client_obd *cli)
{
/*
* LU-8135:
diff --git a/drivers/staging/lustre/lustre/osc/osc_internal.h b/drivers/staging/lustre/lustre/osc/osc_internal.h
index 845e795d8795..13a40f6423ff 100644
--- a/drivers/staging/lustre/lustre/osc/osc_internal.h
+++ b/drivers/staging/lustre/lustre/osc/osc_internal.h
@@ -62,7 +62,7 @@ struct osc_async_page {
struct list_head oap_rpc_item;
u64 oap_obj_off;
- unsigned oap_page_off;
+ unsigned int oap_page_off;
enum async_flags oap_async_flags;
struct brw_page oap_brw_page;
diff --git a/drivers/staging/lustre/lustre/osc/osc_request.c b/drivers/staging/lustre/lustre/osc/osc_request.c
index d8aa3fb468c7..922d0cbe83dc 100644
--- a/drivers/staging/lustre/lustre/osc/osc_request.c
+++ b/drivers/staging/lustre/lustre/osc/osc_request.c
@@ -1227,8 +1227,7 @@ static int check_write_checksum(struct obdo *oa,
msg = "changed in transit AND doesn't match the original - likely false positive due to mmap IO (bug 11742)"
;
- LCONSOLE_ERROR_MSG(0x132, "BAD WRITE CHECKSUM: %s: from %s inode "DFID
- " object "DOSTID" extent [%llu-%llu]\n",
+ LCONSOLE_ERROR_MSG(0x132, "BAD WRITE CHECKSUM: %s: from %s inode " DFID " object " DOSTID " extent [%llu-%llu]\n",
msg, libcfs_nid2str(peer->nid),
oa->o_valid & OBD_MD_FLFID ? oa->o_parent_seq : (__u64)0,
oa->o_valid & OBD_MD_FLFID ? oa->o_parent_oid : 0,
diff --git a/drivers/staging/lustre/lustre/ptlrpc/client.c b/drivers/staging/lustre/lustre/ptlrpc/client.c
index 6466974a43e7..1c7779215eed 100644
--- a/drivers/staging/lustre/lustre/ptlrpc/client.c
+++ b/drivers/staging/lustre/lustre/ptlrpc/client.c
@@ -367,8 +367,8 @@ void ptlrpc_at_adj_net_latency(struct ptlrpc_request *req,
*/
CDEBUG((lustre_msg_get_flags(req->rq_reqmsg) & MSG_RESENT) ?
D_ADAPTTO : D_WARNING,
- "Reported service time %u > total measured time "
- CFS_DURATION_T"\n", service_time,
+ "Reported service time %u > total measured time " CFS_DURATION_T "\n",
+ service_time,
(long)(now - req->rq_sent));
return;
}
diff --git a/drivers/staging/lustre/lustre/ptlrpc/import.c b/drivers/staging/lustre/lustre/ptlrpc/import.c
index 93e172fe9ce4..52cb1f0c9c94 100644
--- a/drivers/staging/lustre/lustre/ptlrpc/import.c
+++ b/drivers/staging/lustre/lustre/ptlrpc/import.c
@@ -1182,17 +1182,15 @@ static int ptlrpc_connect_interpret(const struct lu_env *env,
}
/* Sanity checks for a reconnected import. */
- if (!(imp->imp_replayable) != !(msg_flags & MSG_CONNECT_REPLAYABLE)) {
+ if (!(imp->imp_replayable) != !(msg_flags & MSG_CONNECT_REPLAYABLE))
CERROR("imp_replayable flag does not match server after reconnect. We should LBUG right here.\n");
- }
if (lustre_msg_get_last_committed(request->rq_repmsg) > 0 &&
lustre_msg_get_last_committed(request->rq_repmsg) <
- aa->pcaa_peer_committed) {
+ aa->pcaa_peer_committed)
CERROR("%s went back in time (transno %lld was previously committed, server now claims %lld)! See https://bugzilla.lustre.org/show_bug.cgi?id=9646\n",
obd2cli_tgt(imp->imp_obd), aa->pcaa_peer_committed,
lustre_msg_get_last_committed(request->rq_repmsg));
- }
finish:
ptlrpc_prepare_replay(imp);
@@ -1437,20 +1435,17 @@ int ptlrpc_import_recovery_state_machine(struct obd_import *imp)
rc = 0;
}
- if (imp->imp_state == LUSTRE_IMP_REPLAY_LOCKS) {
+ if (imp->imp_state == LUSTRE_IMP_REPLAY_LOCKS)
if (atomic_read(&imp->imp_replay_inflight) == 0) {
IMPORT_SET_STATE(imp, LUSTRE_IMP_REPLAY_WAIT);
rc = signal_completed_replay(imp);
if (rc)
goto out;
}
- }
- if (imp->imp_state == LUSTRE_IMP_REPLAY_WAIT) {
- if (atomic_read(&imp->imp_replay_inflight) == 0) {
+ if (imp->imp_state == LUSTRE_IMP_REPLAY_WAIT)
+ if (atomic_read(&imp->imp_replay_inflight) == 0)
IMPORT_SET_STATE(imp, LUSTRE_IMP_RECOVER);
- }
- }
if (imp->imp_state == LUSTRE_IMP_RECOVER) {
CDEBUG(D_HA, "reconnected to %s@%s\n",
diff --git a/drivers/staging/lustre/lustre/ptlrpc/layout.c b/drivers/staging/lustre/lustre/ptlrpc/layout.c
index 8177e1a31ca9..5810bbab6585 100644
--- a/drivers/staging/lustre/lustre/ptlrpc/layout.c
+++ b/drivers/staging/lustre/lustre/ptlrpc/layout.c
@@ -1761,7 +1761,7 @@ static u32 __req_capsule_offset(const struct req_capsule *pill,
field->rmf_name, offset, loc);
offset--;
- LASSERT(0 <= offset && offset < REQ_MAX_FIELD_NR);
+ LASSERT(offset < REQ_MAX_FIELD_NR);
return offset;
}
diff --git a/drivers/staging/lustre/lustre/ptlrpc/pack_generic.c b/drivers/staging/lustre/lustre/ptlrpc/pack_generic.c
index 9456a1825918..55e8696e7d86 100644
--- a/drivers/staging/lustre/lustre/ptlrpc/pack_generic.c
+++ b/drivers/staging/lustre/lustre/ptlrpc/pack_generic.c
@@ -2089,7 +2089,7 @@ static void dump_obdo(struct obdo *oa)
CDEBUG(D_RPCTRACE, "obdo: o_valid = %08x\n", valid);
if (valid & OBD_MD_FLID)
- CDEBUG(D_RPCTRACE, "obdo: id = "DOSTID"\n", POSTID(&oa->o_oi));
+ CDEBUG(D_RPCTRACE, "obdo: id = " DOSTID "\n", POSTID(&oa->o_oi));
if (valid & OBD_MD_FLFID)
CDEBUG(D_RPCTRACE, "obdo: o_parent_seq = %#llx\n",
oa->o_parent_seq);
diff --git a/drivers/staging/lustre/lustre/ptlrpc/ptlrpc_internal.h b/drivers/staging/lustre/lustre/ptlrpc/ptlrpc_internal.h
index d2707a323c47..c38e166f1502 100644
--- a/drivers/staging/lustre/lustre/ptlrpc/ptlrpc_internal.h
+++ b/drivers/staging/lustre/lustre/ptlrpc/ptlrpc_internal.h
@@ -68,7 +68,7 @@ void ptlrpc_init_xid(void);
void ptlrpc_set_add_new_req(struct ptlrpcd_ctl *pc,
struct ptlrpc_request *req);
int ptlrpc_expired_set(void *data);
-int ptlrpc_set_next_timeout(struct ptlrpc_request_set *);
+int ptlrpc_set_next_timeout(struct ptlrpc_request_set *set);
void ptlrpc_resend_req(struct ptlrpc_request *request);
void ptlrpc_set_bulk_mbits(struct ptlrpc_request *req);
void ptlrpc_assign_next_xid_nolock(struct ptlrpc_request *req);
@@ -79,7 +79,7 @@ void ptlrpc_add_unreplied(struct ptlrpc_request *req);
int ptlrpc_init_portals(void);
void ptlrpc_exit_portals(void);
-void ptlrpc_request_handle_notconn(struct ptlrpc_request *);
+void ptlrpc_request_handle_notconn(struct ptlrpc_request *req);
void lustre_assert_wire_constants(void);
int ptlrpc_import_in_recovery(struct obd_import *imp);
int ptlrpc_set_import_discon(struct obd_import *imp, __u32 conn_cnt);
diff --git a/drivers/staging/lustre/lustre/ptlrpc/service.c b/drivers/staging/lustre/lustre/ptlrpc/service.c
index b8091c118302..759aa6c16e28 100644
--- a/drivers/staging/lustre/lustre/ptlrpc/service.c
+++ b/drivers/staging/lustre/lustre/ptlrpc/service.c
@@ -1565,7 +1565,7 @@ ptlrpc_server_handle_req_in(struct ptlrpc_service_part *svcpt,
/* req_in handling should/must be fast */
if (ktime_get_real_seconds() - req->rq_arrival_time.tv_sec > 5)
- DEBUG_REQ(D_WARNING, req, "Slow req_in handling "CFS_DURATION_T"s",
+ DEBUG_REQ(D_WARNING, req, "Slow req_in handling " CFS_DURATION_T "s",
(long)(ktime_get_real_seconds() -
req->rq_arrival_time.tv_sec));
diff --git a/drivers/staging/media/atomisp/i2c/Makefile b/drivers/staging/media/atomisp/i2c/Makefile
index 8ea01904c0ea..466517c7c8e6 100644
--- a/drivers/staging/media/atomisp/i2c/Makefile
+++ b/drivers/staging/media/atomisp/i2c/Makefile
@@ -19,5 +19,3 @@ obj-$(CONFIG_VIDEO_AP1302) += ap1302.o
obj-$(CONFIG_VIDEO_LM3554) += lm3554.o
-ccflags-y += -Werror
-
diff --git a/drivers/staging/media/atomisp/i2c/imx/Makefile b/drivers/staging/media/atomisp/i2c/imx/Makefile
index 1d7f7ab94cac..6b13a3a66e49 100644
--- a/drivers/staging/media/atomisp/i2c/imx/Makefile
+++ b/drivers/staging/media/atomisp/i2c/imx/Makefile
@@ -4,5 +4,3 @@ imx1x5-objs := imx.o drv201.o ad5816g.o dw9714.o dw9719.o dw9718.o vcm.o otp.o o
ov8858_driver-objs := ../ov8858.o dw9718.o vcm.o
obj-$(CONFIG_VIDEO_OV8858) += ov8858_driver.o
-
-ccflags-y += -Werror
diff --git a/drivers/staging/media/atomisp/i2c/ov5693/Makefile b/drivers/staging/media/atomisp/i2c/ov5693/Makefile
index fceb9e9b881b..c9c0e1245858 100644
--- a/drivers/staging/media/atomisp/i2c/ov5693/Makefile
+++ b/drivers/staging/media/atomisp/i2c/ov5693/Makefile
@@ -1,3 +1 @@
obj-$(CONFIG_VIDEO_OV5693) += ov5693.o
-
-ccflags-y += -Werror
diff --git a/drivers/staging/media/atomisp/pci/atomisp2/Makefile b/drivers/staging/media/atomisp/pci/atomisp2/Makefile
index 3fa7c1c1479f..f126a89a08e9 100644
--- a/drivers/staging/media/atomisp/pci/atomisp2/Makefile
+++ b/drivers/staging/media/atomisp/pci/atomisp2/Makefile
@@ -351,5 +351,5 @@ DEFINES := -DHRT_HW -DHRT_ISP_CSS_CUSTOM_HOST -DHRT_USE_VIR_ADDRS -D__HOST__
DEFINES += -DATOMISP_POSTFIX=\"css2400b0_v21\" -DISP2400B0
DEFINES += -DSYSTEM_hive_isp_css_2400_system -DISP2400
-ccflags-y += $(INCLUDES) $(DEFINES) -fno-common -Werror
+ccflags-y += $(INCLUDES) $(DEFINES) -fno-common
diff --git a/drivers/staging/most/aim-network/networking.c b/drivers/staging/most/aim-network/networking.c
index ce1764cba5f0..4c259c20048f 100644
--- a/drivers/staging/most/aim-network/networking.c
+++ b/drivers/staging/most/aim-network/networking.c
@@ -22,7 +22,6 @@
#include <linux/wait.h>
#include <linux/kobject.h>
#include "mostcore.h"
-#include "networking.h"
#define MEP_HDR_LEN 8
#define MDP_HDR_LEN 16
@@ -65,17 +64,16 @@ struct net_dev_channel {
struct net_dev_context {
struct most_interface *iface;
- bool channels_opened;
bool is_mamac;
struct net_device *dev;
struct net_dev_channel rx;
struct net_dev_channel tx;
- struct completion mac_compl;
struct list_head list;
};
static struct list_head net_devices = LIST_HEAD_INIT(net_devices);
-static struct spinlock list_lock;
+static struct mutex probe_disc_mt; /* ch->linked = true, most_nd_open */
+static struct spinlock list_lock; /* list_head, ch->linked = false, dev_hold */
static struct most_aim aim;
static int skb_to_mamac(const struct sk_buff *skb, struct mbo *mbo)
@@ -157,14 +155,12 @@ static int skb_to_mep(const struct sk_buff *skb, struct mbo *mbo)
static int most_nd_set_mac_address(struct net_device *dev, void *p)
{
- struct net_dev_context *nd = dev->ml_priv;
+ struct net_dev_context *nd = netdev_priv(dev);
int err = eth_mac_addr(dev, p);
if (err)
return err;
- BUG_ON(nd->dev != dev);
-
nd->is_mamac =
(dev->dev_addr[0] == 0 && dev->dev_addr[1] == 0 &&
dev->dev_addr[2] == 0 && dev->dev_addr[3] == 0);
@@ -178,71 +174,52 @@ static int most_nd_set_mac_address(struct net_device *dev, void *p)
return 0;
}
+static void on_netinfo(struct most_interface *iface,
+ unsigned char link_stat, unsigned char *mac_addr);
+
static int most_nd_open(struct net_device *dev)
{
- struct net_dev_context *nd = dev->ml_priv;
- long ret;
-
- netdev_info(dev, "open net device\n");
-
- BUG_ON(nd->dev != dev);
+ struct net_dev_context *nd = netdev_priv(dev);
+ int ret = 0;
- if (nd->channels_opened)
- return -EFAULT;
-
- BUG_ON(!nd->tx.linked || !nd->rx.linked);
+ mutex_lock(&probe_disc_mt);
if (most_start_channel(nd->iface, nd->rx.ch_id, &aim)) {
netdev_err(dev, "most_start_channel() failed\n");
- return -EBUSY;
+ ret = -EBUSY;
+ goto unlock;
}
if (most_start_channel(nd->iface, nd->tx.ch_id, &aim)) {
netdev_err(dev, "most_start_channel() failed\n");
most_stop_channel(nd->iface, nd->rx.ch_id, &aim);
- return -EBUSY;
+ ret = -EBUSY;
+ goto unlock;
}
- if (!is_valid_ether_addr(dev->dev_addr)) {
- nd->iface->request_netinfo(nd->iface, nd->tx.ch_id);
- ret = wait_for_completion_interruptible_timeout(
- &nd->mac_compl, msecs_to_jiffies(5000));
- if (!ret) {
- netdev_err(dev, "mac timeout\n");
- ret = -EBUSY;
- goto err;
- }
-
- if (ret < 0) {
- netdev_warn(dev, "mac waiting interrupted\n");
- goto err;
- }
- }
-
- nd->channels_opened = true;
+ netif_carrier_off(dev);
+ if (is_valid_ether_addr(dev->dev_addr))
+ netif_dormant_off(dev);
+ else
+ netif_dormant_on(dev);
netif_wake_queue(dev);
- return 0;
+ if (nd->iface->request_netinfo)
+ nd->iface->request_netinfo(nd->iface, nd->tx.ch_id, on_netinfo);
-err:
- most_stop_channel(nd->iface, nd->tx.ch_id, &aim);
- most_stop_channel(nd->iface, nd->rx.ch_id, &aim);
+unlock:
+ mutex_unlock(&probe_disc_mt);
return ret;
}
static int most_nd_stop(struct net_device *dev)
{
- struct net_dev_context *nd = dev->ml_priv;
-
- netdev_info(dev, "stop net device\n");
+ struct net_dev_context *nd = netdev_priv(dev);
- BUG_ON(nd->dev != dev);
netif_stop_queue(dev);
-
- if (nd->channels_opened) {
- most_stop_channel(nd->iface, nd->rx.ch_id, &aim);
- most_stop_channel(nd->iface, nd->tx.ch_id, &aim);
- nd->channels_opened = false;
- }
+ if (nd->iface->request_netinfo)
+ nd->iface->request_netinfo(nd->iface, nd->tx.ch_id, NULL);
+ most_stop_channel(nd->iface, nd->rx.ch_id, &aim);
+ most_stop_channel(nd->iface, nd->tx.ch_id, &aim);
return 0;
}
@@ -250,12 +227,10 @@ static int most_nd_stop(struct net_device *dev)
static netdev_tx_t most_nd_start_xmit(struct sk_buff *skb,
struct net_device *dev)
{
- struct net_dev_context *nd = dev->ml_priv;
+ struct net_dev_context *nd = netdev_priv(dev);
struct mbo *mbo;
int ret;
- BUG_ON(nd->dev != dev);
-
mbo = most_get_mbo(nd->iface, nd->tx.ch_id, &aim);
if (!mbo) {
@@ -296,33 +271,29 @@ static void most_nd_setup(struct net_device *dev)
dev->netdev_ops = &most_nd_ops;
}
-static void most_net_rm_netdev_safe(struct net_dev_context *nd)
+static struct net_dev_context *get_net_dev(struct most_interface *iface)
{
- if (!nd->dev)
- return;
-
- pr_info("remove net device %p\n", nd->dev);
+ struct net_dev_context *nd;
- unregister_netdev(nd->dev);
- free_netdev(nd->dev);
- nd->dev = NULL;
+ list_for_each_entry(nd, &net_devices, list)
+ if (nd->iface == iface)
+ return nd;
+ return NULL;
}
-static struct net_dev_context *get_net_dev_context(
- struct most_interface *iface)
+static struct net_dev_context *get_net_dev_hold(struct most_interface *iface)
{
- struct net_dev_context *nd, *tmp;
+ struct net_dev_context *nd;
unsigned long flags;
spin_lock_irqsave(&list_lock, flags);
- list_for_each_entry_safe(nd, tmp, &net_devices, list) {
- if (nd->iface == iface) {
- spin_unlock_irqrestore(&list_lock, flags);
- return nd;
- }
- }
+ nd = get_net_dev(iface);
+ if (nd && nd->rx.linked && nd->tx.linked)
+ dev_hold(nd->dev);
+ else
+ nd = NULL;
spin_unlock_irqrestore(&list_lock, flags);
- return NULL;
+ return nd;
}
static int aim_probe_channel(struct most_interface *iface, int channel_idx,
@@ -331,7 +302,9 @@ static int aim_probe_channel(struct most_interface *iface, int channel_idx,
{
struct net_dev_context *nd;
struct net_dev_channel *ch;
+ struct net_device *dev;
unsigned long flags;
+ int ret = 0;
if (!iface)
return -EINVAL;
@@ -339,54 +312,45 @@ static int aim_probe_channel(struct most_interface *iface, int channel_idx,
if (ccfg->data_type != MOST_CH_ASYNC)
return -EINVAL;
- nd = get_net_dev_context(iface);
-
+ mutex_lock(&probe_disc_mt);
+ nd = get_net_dev(iface);
if (!nd) {
- nd = kzalloc(sizeof(*nd), GFP_KERNEL);
- if (!nd)
- return -ENOMEM;
+ dev = alloc_netdev(sizeof(struct net_dev_context), "meth%d",
+ NET_NAME_UNKNOWN, most_nd_setup);
+ if (!dev) {
+ ret = -ENOMEM;
+ goto unlock;
+ }
- init_completion(&nd->mac_compl);
+ nd = netdev_priv(dev);
nd->iface = iface;
+ nd->dev = dev;
spin_lock_irqsave(&list_lock, flags);
list_add(&nd->list, &net_devices);
spin_unlock_irqrestore(&list_lock, flags);
- }
- ch = ccfg->direction == MOST_CH_TX ? &nd->tx : &nd->rx;
- if (ch->linked) {
- pr_err("only one channel per instance & direction allowed\n");
- return -EINVAL;
- }
-
- if (nd->tx.linked || nd->rx.linked) {
- struct net_device *dev =
- alloc_netdev(0, "meth%d", NET_NAME_UNKNOWN,
- most_nd_setup);
-
- if (!dev) {
- pr_err("no memory for net_device\n");
- return -ENOMEM;
+ ch = ccfg->direction == MOST_CH_TX ? &nd->tx : &nd->rx;
+ } else {
+ ch = ccfg->direction == MOST_CH_TX ? &nd->tx : &nd->rx;
+ if (ch->linked) {
+ pr_err("direction is allocated\n");
+ ret = -EINVAL;
+ goto unlock;
}
- nd->dev = dev;
- ch->ch_id = channel_idx;
- ch->linked = true;
-
- dev->ml_priv = nd;
- if (register_netdev(dev)) {
- pr_err("registering net device failed\n");
- ch->linked = false;
- free_netdev(dev);
- return -EINVAL;
+ if (register_netdev(nd->dev)) {
+ pr_err("register_netdev() failed\n");
+ ret = -EINVAL;
+ goto unlock;
}
}
-
ch->ch_id = channel_idx;
ch->linked = true;
- return 0;
+unlock:
+ mutex_unlock(&probe_disc_mt);
+ return ret;
}
static int aim_disconnect_channel(struct most_interface *iface,
@@ -395,34 +359,45 @@ static int aim_disconnect_channel(struct most_interface *iface,
struct net_dev_context *nd;
struct net_dev_channel *ch;
unsigned long flags;
+ int ret = 0;
- nd = get_net_dev_context(iface);
- if (!nd)
- return -EINVAL;
+ mutex_lock(&probe_disc_mt);
+ nd = get_net_dev(iface);
+ if (!nd) {
+ ret = -EINVAL;
+ goto unlock;
+ }
- if (nd->rx.linked && channel_idx == nd->rx.ch_id)
+ if (nd->rx.linked && channel_idx == nd->rx.ch_id) {
ch = &nd->rx;
- else if (nd->tx.linked && channel_idx == nd->tx.ch_id)
+ } else if (nd->tx.linked && channel_idx == nd->tx.ch_id) {
ch = &nd->tx;
- else
- return -EINVAL;
-
- ch->linked = false;
+ } else {
+ ret = -EINVAL;
+ goto unlock;
+ }
- /*
- * do not call most_stop_channel() here, because channels are
- * going to be closed in ndo_stop() after unregister_netdev()
- */
- most_net_rm_netdev_safe(nd);
+ if (nd->rx.linked && nd->tx.linked) {
+ spin_lock_irqsave(&list_lock, flags);
+ ch->linked = false;
+ spin_unlock_irqrestore(&list_lock, flags);
- if (!nd->rx.linked && !nd->tx.linked) {
+ /*
+ * do not call most_stop_channel() here, because channels are
+ * going to be closed in ndo_stop() after unregister_netdev()
+ */
+ unregister_netdev(nd->dev);
+ } else {
spin_lock_irqsave(&list_lock, flags);
list_del(&nd->list);
spin_unlock_irqrestore(&list_lock, flags);
- kfree(nd);
+
+ free_netdev(nd->dev);
}
- return 0;
+unlock:
+ mutex_unlock(&probe_disc_mt);
+ return ret;
}
static int aim_resume_tx_channel(struct most_interface *iface,
@@ -430,14 +405,17 @@ static int aim_resume_tx_channel(struct most_interface *iface,
{
struct net_dev_context *nd;
- nd = get_net_dev_context(iface);
- if (!nd || !nd->channels_opened || nd->tx.ch_id != channel_idx)
+ nd = get_net_dev_hold(iface);
+ if (!nd)
return 0;
- if (!nd->dev)
- return 0;
+ if (nd->tx.ch_id != channel_idx)
+ goto put_nd;
netif_wake_queue(nd->dev);
+
+put_nd:
+ dev_put(nd->dev);
return 0;
}
@@ -450,25 +428,31 @@ static int aim_rx_data(struct mbo *mbo)
struct sk_buff *skb;
struct net_device *dev;
unsigned int skb_len;
+ int ret = 0;
- nd = get_net_dev_context(mbo->ifp);
- if (!nd || !nd->channels_opened || nd->rx.ch_id != mbo->hdm_channel_id)
+ nd = get_net_dev_hold(mbo->ifp);
+ if (!nd)
return -EIO;
- dev = nd->dev;
- if (!dev) {
- pr_err_once("drop packet: missing net_device\n");
- return -EIO;
+ if (nd->rx.ch_id != mbo->hdm_channel_id) {
+ ret = -EIO;
+ goto put_nd;
}
+ dev = nd->dev;
+
if (nd->is_mamac) {
- if (!PMS_IS_MAMAC(buf, len))
- return -EIO;
+ if (!PMS_IS_MAMAC(buf, len)) {
+ ret = -EIO;
+ goto put_nd;
+ }
skb = dev_alloc_skb(len - MDP_HDR_LEN + 2 * ETH_ALEN + 2);
} else {
- if (!PMS_IS_MEP(buf, len))
- return -EIO;
+ if (!PMS_IS_MEP(buf, len)) {
+ ret = -EIO;
+ goto put_nd;
+ }
skb = dev_alloc_skb(len - MEP_HDR_LEN);
}
@@ -511,7 +495,10 @@ static int aim_rx_data(struct mbo *mbo)
out:
most_put_mbo(mbo);
- return 0;
+
+put_nd:
+ dev_put(nd->dev);
+ return ret;
}
static struct most_aim aim = {
@@ -524,68 +511,54 @@ static struct most_aim aim = {
static int __init most_net_init(void)
{
- pr_info("most_net_init()\n");
spin_lock_init(&list_lock);
+ mutex_init(&probe_disc_mt);
return most_register_aim(&aim);
}
static void __exit most_net_exit(void)
{
- struct net_dev_context *nd, *tmp;
- unsigned long flags;
-
- spin_lock_irqsave(&list_lock, flags);
- list_for_each_entry_safe(nd, tmp, &net_devices, list) {
- list_del(&nd->list);
- spin_unlock_irqrestore(&list_lock, flags);
- /*
- * do not call most_stop_channel() here, because channels are
- * going to be closed in ndo_stop() after unregister_netdev()
- */
- most_net_rm_netdev_safe(nd);
- kfree(nd);
- spin_lock_irqsave(&list_lock, flags);
- }
- spin_unlock_irqrestore(&list_lock, flags);
-
most_deregister_aim(&aim);
- pr_info("most_net_exit()\n");
}
/**
- * most_deliver_netinfo - callback for HDM to be informed about HW's MAC
+ * on_netinfo - callback for HDM to be informed about HW's MAC
* @param iface - most interface instance
* @param link_stat - link status
* @param mac_addr - MAC address
*/
-void most_deliver_netinfo(struct most_interface *iface,
- unsigned char link_stat, unsigned char *mac_addr)
+static void on_netinfo(struct most_interface *iface,
+ unsigned char link_stat, unsigned char *mac_addr)
{
struct net_dev_context *nd;
struct net_device *dev;
const u8 *m = mac_addr;
- nd = get_net_dev_context(iface);
+ nd = get_net_dev_hold(iface);
if (!nd)
return;
dev = nd->dev;
- if (!dev)
- return;
+
+ if (link_stat)
+ netif_carrier_on(dev);
+ else
+ netif_carrier_off(dev);
if (m && is_valid_ether_addr(m)) {
if (!is_valid_ether_addr(dev->dev_addr)) {
netdev_info(dev, "set mac %02x-%02x-%02x-%02x-%02x-%02x\n",
m[0], m[1], m[2], m[3], m[4], m[5]);
ether_addr_copy(dev->dev_addr, m);
- complete(&nd->mac_compl);
+ netif_dormant_off(dev);
} else if (!ether_addr_equal(dev->dev_addr, m)) {
netdev_warn(dev, "reject mac %02x-%02x-%02x-%02x-%02x-%02x\n",
m[0], m[1], m[2], m[3], m[4], m[5]);
}
}
+
+ dev_put(nd->dev);
}
-EXPORT_SYMBOL(most_deliver_netinfo);
module_init(most_net_init);
module_exit(most_net_exit);
diff --git a/drivers/staging/most/aim-network/networking.h b/drivers/staging/most/aim-network/networking.h
deleted file mode 100644
index 6f346d410525..000000000000
--- a/drivers/staging/most/aim-network/networking.h
+++ /dev/null
@@ -1,21 +0,0 @@
-/*
- * Networking AIM - Networking Application Interface Module for MostCore
- *
- * Copyright (C) 2015, Microchip Technology Germany II GmbH & Co. KG
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * This file is licensed under GPLv2.
- */
-#ifndef _NETWORKING_H_
-#define _NETWORKING_H_
-
-#include "mostcore.h"
-
-void most_deliver_netinfo(struct most_interface *iface,
- unsigned char link_stat, unsigned char *mac_addr);
-
-#endif
diff --git a/drivers/staging/most/hdm-dim2/Kconfig b/drivers/staging/most/hdm-dim2/Kconfig
index 28a0e1791600..663bfebff674 100644
--- a/drivers/staging/most/hdm-dim2/Kconfig
+++ b/drivers/staging/most/hdm-dim2/Kconfig
@@ -4,7 +4,6 @@
config HDM_DIM2
tristate "DIM2 HDM"
- depends on AIM_NETWORK
depends on HAS_IOMEM
---help---
diff --git a/drivers/staging/most/hdm-dim2/dim2_hal.c b/drivers/staging/most/hdm-dim2/dim2_hal.c
index d604ec09df28..91484643d289 100644
--- a/drivers/staging/most/hdm-dim2/dim2_hal.c
+++ b/drivers/staging/most/hdm-dim2/dim2_hal.c
@@ -217,12 +217,15 @@ static inline void dim2_clear_ctr(u32 ctr_addr)
}
static void dim2_configure_cat(u8 cat_base, u8 ch_addr, u8 ch_type,
- bool read_not_write, bool sync_mfe)
+ bool read_not_write)
{
+ bool isoc_fce = ch_type == CAT_CT_VAL_ISOC;
+ bool sync_mfe = ch_type == CAT_CT_VAL_SYNC;
u16 const cat =
(read_not_write << CAT_RNW_BIT) |
(ch_type << CAT_CT_SHIFT) |
(ch_addr << CAT_CL_SHIFT) |
+ (isoc_fce << CAT_FCE_BIT) |
(sync_mfe << CAT_MFE_BIT) |
(false << CAT_MT_BIT) |
(true << CAT_CE_BIT);
@@ -350,13 +353,13 @@ static void dim2_clear_ctram(void)
static void dim2_configure_channel(
u8 ch_addr, u8 type, u8 is_tx, u16 dbr_address, u16 hw_buffer_size,
- u16 packet_length, bool sync_mfe)
+ u16 packet_length)
{
dim2_configure_cdt(ch_addr, dbr_address, hw_buffer_size, packet_length);
- dim2_configure_cat(MLB_CAT, ch_addr, type, is_tx ? 1 : 0, sync_mfe);
+ dim2_configure_cat(MLB_CAT, ch_addr, type, is_tx ? 1 : 0);
dim2_configure_adt(ch_addr);
- dim2_configure_cat(AHB_CAT, ch_addr, type, is_tx ? 0 : 1, sync_mfe);
+ dim2_configure_cat(AHB_CAT, ch_addr, type, is_tx ? 0 : 1);
/* unmask interrupt for used channel, enable mlb_sys_int[0] interrupt */
dimcb_io_write(&g.dim2->ACMR0,
@@ -771,7 +774,7 @@ static u8 init_ctrl_async(struct dim_channel *ch, u8 type, u8 is_tx,
channel_init(ch, ch_address / 2);
dim2_configure_channel(ch->addr, type, is_tx,
- ch->dbr_addr, ch->dbr_size, 0, false);
+ ch->dbr_addr, ch->dbr_size, 0);
return DIM_NO_ERROR;
}
@@ -857,7 +860,7 @@ u8 dim_init_isoc(struct dim_channel *ch, u8 is_tx, u16 ch_address,
isoc_init(ch, ch_address / 2, packet_length);
dim2_configure_channel(ch->addr, CAT_CT_VAL_ISOC, is_tx, ch->dbr_addr,
- ch->dbr_size, packet_length, false);
+ ch->dbr_size, packet_length);
return DIM_NO_ERROR;
}
@@ -885,7 +888,7 @@ u8 dim_init_sync(struct dim_channel *ch, u8 is_tx, u16 ch_address,
dim2_clear_dbr(ch->dbr_addr, ch->dbr_size);
dim2_configure_channel(ch->addr, CAT_CT_VAL_SYNC, is_tx,
- ch->dbr_addr, ch->dbr_size, 0, true);
+ ch->dbr_addr, ch->dbr_size, 0);
return DIM_NO_ERROR;
}
diff --git a/drivers/staging/most/hdm-dim2/dim2_hdm.c b/drivers/staging/most/hdm-dim2/dim2_hdm.c
index 902824e728ea..4607d03c577b 100644
--- a/drivers/staging/most/hdm-dim2/dim2_hdm.c
+++ b/drivers/staging/most/hdm-dim2/dim2_hdm.c
@@ -26,7 +26,6 @@
#include <linux/kthread.h>
#include <mostcore.h>
-#include <networking.h>
#include "dim2_hal.h"
#include "dim2_hdm.h"
#include "dim2_errors.h"
@@ -107,6 +106,8 @@ struct dim2_hdm {
unsigned char link_state;
int atx_idx;
struct medialb_bus bus;
+ void (*on_netinfo)(struct most_interface *,
+ unsigned char, unsigned char *);
};
#define iface_to_hdm(iface) container_of(iface, struct dim2_hdm, most_iface)
@@ -287,8 +288,11 @@ static int deliver_netinfo_thread(void *data)
if (dev->deliver_netinfo) {
dev->deliver_netinfo--;
- most_deliver_netinfo(&dev->most_iface, dev->link_state,
- dev->mac_addrs);
+ if (dev->on_netinfo) {
+ dev->on_netinfo(&dev->most_iface,
+ dev->link_state,
+ dev->mac_addrs);
+ }
}
}
@@ -654,12 +658,18 @@ static int enqueue(struct most_interface *most_iface, int ch_idx,
* Send a command to INIC which triggers retrieving of network info by means of
* "Message exchange over MDP/MEP". Return 0 on success, negative on failure.
*/
-static void request_netinfo(struct most_interface *most_iface, int ch_idx)
+static void request_netinfo(struct most_interface *most_iface, int ch_idx,
+ void (*on_netinfo)(struct most_interface *,
+ unsigned char, unsigned char *))
{
struct dim2_hdm *dev = iface_to_hdm(most_iface);
struct mbo *mbo;
u8 *data;
+ dev->on_netinfo = on_netinfo;
+ if (!on_netinfo)
+ return;
+
if (dev->atx_idx < 0) {
pr_err("Async Tx Not initialized\n");
return;
diff --git a/drivers/staging/most/hdm-dim2/dim2_reg.h b/drivers/staging/most/hdm-dim2/dim2_reg.h
index 01fe499411ff..f7d9fbcd29f2 100644
--- a/drivers/staging/most/hdm-dim2/dim2_reg.h
+++ b/drivers/staging/most/hdm-dim2/dim2_reg.h
@@ -141,6 +141,7 @@ enum {
ADT1_CTRL_ASYNC_BD_MASK = DIM2_MASK(11),
ADT1_ISOC_SYNC_BD_MASK = DIM2_MASK(13),
+ CAT_FCE_BIT = 14,
CAT_MFE_BIT = 14,
CAT_MT_BIT = 13,
diff --git a/drivers/staging/most/hdm-i2c/hdm_i2c.c b/drivers/staging/most/hdm-i2c/hdm_i2c.c
index 1d5b22927bcd..2b4de404e46a 100644
--- a/drivers/staging/most/hdm-i2c/hdm_i2c.c
+++ b/drivers/staging/most/hdm-i2c/hdm_i2c.c
@@ -185,12 +185,6 @@ static int poison_channel(struct most_interface *most_iface,
return 0;
}
-static void request_netinfo(struct most_interface *most_iface,
- int ch_idx)
-{
- pr_info("request_netinfo()\n");
-}
-
static void do_rx_work(struct hdm_i2c *dev)
{
struct mbo *mbo;
@@ -343,7 +337,6 @@ static int i2c_probe(struct i2c_client *client, const struct i2c_device_id *id)
dev->most_iface.configure = configure_channel;
dev->most_iface.enqueue = enqueue;
dev->most_iface.poison_channel = poison_channel;
- dev->most_iface.request_netinfo = request_netinfo;
INIT_LIST_HEAD(&dev->rx.list);
mutex_init(&dev->rx.list_mutex);
diff --git a/drivers/staging/most/hdm-usb/Kconfig b/drivers/staging/most/hdm-usb/Kconfig
index ec1546312ee6..487f1f34776c 100644
--- a/drivers/staging/most/hdm-usb/Kconfig
+++ b/drivers/staging/most/hdm-usb/Kconfig
@@ -5,7 +5,7 @@
config HDM_USB
tristate "USB HDM"
depends on USB && NET
- select AIM_NETWORK
+
---help---
Say Y here if you want to connect via USB to network tranceiver.
This device driver depends on the networking AIM.
diff --git a/drivers/staging/most/hdm-usb/hdm_usb.c b/drivers/staging/most/hdm-usb/hdm_usb.c
index a95b5910d9fc..d0f68cb3c173 100644
--- a/drivers/staging/most/hdm-usb/hdm_usb.c
+++ b/drivers/staging/most/hdm-usb/hdm_usb.c
@@ -30,7 +30,6 @@
#include <linux/etherdevice.h>
#include <linux/uaccess.h>
#include "mostcore.h"
-#include "networking.h"
#define USB_MTU 512
#define NO_ISOCHRONOUS_URB 0
@@ -126,6 +125,8 @@ struct most_dev {
struct mutex io_mutex;
struct timer_list link_stat_timer;
struct work_struct poll_work_obj;
+ void (*on_netinfo)(struct most_interface *, unsigned char,
+ unsigned char *);
};
#define to_mdev(d) container_of(d, struct most_dev, iface)
@@ -719,12 +720,19 @@ exit:
* polls for the NI state of the INIC every 2 seconds.
*
*/
-static void hdm_request_netinfo(struct most_interface *iface, int channel)
+static void hdm_request_netinfo(struct most_interface *iface, int channel,
+ void (*on_netinfo)(struct most_interface *,
+ unsigned char,
+ unsigned char *))
{
struct most_dev *mdev;
BUG_ON(!iface);
mdev = to_mdev(iface);
+ mdev->on_netinfo = on_netinfo;
+ if (!on_netinfo)
+ return;
+
mdev->link_stat_timer.expires = jiffies + HZ;
mod_timer(&mdev->link_stat_timer, mdev->link_stat_timer.expires);
}
@@ -786,7 +794,8 @@ static void wq_netinfo(struct work_struct *wq_obj)
hw_addr[4] = lo >> 8;
hw_addr[5] = lo;
- most_deliver_netinfo(&mdev->iface, link, hw_addr);
+ if (mdev->on_netinfo)
+ mdev->on_netinfo(&mdev->iface, link, hw_addr);
}
/**
diff --git a/drivers/staging/most/mostcore/mostcore.h b/drivers/staging/most/mostcore/mostcore.h
index 5f8339bd046f..915e5159d1eb 100644
--- a/drivers/staging/most/mostcore/mostcore.h
+++ b/drivers/staging/most/mostcore/mostcore.h
@@ -233,6 +233,8 @@ struct mbo {
* The callback returns a negative value on error, otherwise 0.
* @request_netinfo: triggers retrieving of network info from the HDM by
* means of "Message exchange over MDP/MEP"
+ * The call of the function request_netinfo with the parameter on_netinfo as
+ * NULL prohibits use of the previously obtained function pointer.
* @priv Private field used by mostcore to store context information.
*/
struct most_interface {
@@ -246,7 +248,10 @@ struct most_interface {
int (*enqueue)(struct most_interface *iface, int channel_idx,
struct mbo *mbo);
int (*poison_channel)(struct most_interface *iface, int channel_idx);
- void (*request_netinfo)(struct most_interface *iface, int channel_idx);
+ void (*request_netinfo)(struct most_interface *iface, int channel_idx,
+ void (*on_netinfo)(struct most_interface *iface,
+ unsigned char link_stat,
+ unsigned char *mac_addr));
void *priv;
};
diff --git a/drivers/staging/octeon-usb/octeon-hcd.c b/drivers/staging/octeon-usb/octeon-hcd.c
index 9a7858a300fd..068aece25d37 100644
--- a/drivers/staging/octeon-usb/octeon-hcd.c
+++ b/drivers/staging/octeon-usb/octeon-hcd.c
@@ -3659,14 +3659,14 @@ static int octeon_usb_probe(struct platform_device *pdev)
status = cvmx_usb_initialize(dev, usb);
if (status) {
dev_dbg(dev, "USB initialization failed with %d\n", status);
- kfree(hcd);
+ usb_put_hcd(hcd);
return -1;
}
status = usb_add_hcd(hcd, irq, 0);
if (status) {
dev_dbg(dev, "USB add HCD failed with %d\n", status);
- kfree(hcd);
+ usb_put_hcd(hcd);
return -1;
}
device_wakeup_enable(hcd->self.controller);
@@ -3691,7 +3691,7 @@ static int octeon_usb_remove(struct platform_device *pdev)
if (status)
dev_dbg(dev, "USB shutdown failed with %d\n", status);
- kfree(hcd);
+ usb_put_hcd(hcd);
return 0;
}
diff --git a/drivers/staging/octeon/ethernet-util.h b/drivers/staging/octeon/ethernet-util.h
index 617da8037a4d..cb5540dc0e9d 100644
--- a/drivers/staging/octeon/ethernet-util.h
+++ b/drivers/staging/octeon/ethernet-util.h
@@ -39,7 +39,7 @@ static inline int INTERFACE(int ipd_port)
interface = cvmx_helper_get_interface_num(ipd_port);
if (interface >= 0)
return interface;
- panic("Illegal ipd_port %d passed to INTERFACE\n", ipd_port);
+ panic("Illegal ipd_port %d passed to %s\n", ipd_port, __func__);
}
/**
diff --git a/drivers/staging/rtl8188eu/core/rtw_ap.c b/drivers/staging/rtl8188eu/core/rtw_ap.c
index 519b4d3584a2..647a922d79d1 100644
--- a/drivers/staging/rtl8188eu/core/rtw_ap.c
+++ b/drivers/staging/rtl8188eu/core/rtw_ap.c
@@ -735,9 +735,11 @@ static void start_bss_network(struct adapter *padapter, u8 *pbuf)
cur_ch_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE;
- /* check if there is wps ie, */
- /* if there is wpsie in beacon, the hostapd will update beacon twice when stating hostapd, */
- /* and at first time the security ie (RSN/WPA IE) will not include in beacon. */
+ /* check if there is wps ie,
+ * if there is wpsie in beacon, the hostapd will update
+ * beacon twice when stating hostapd, and at first time the
+ * security ie (RSN/WPA IE) will not include in beacon.
+ */
if (!rtw_get_wps_ie(pnetwork->IEs + _FIXED_IE_LENGTH_, pnetwork->IELength - _FIXED_IE_LENGTH_, NULL, NULL))
pmlmeext->bstart_bss = true;
@@ -751,8 +753,11 @@ static void start_bss_network(struct adapter *padapter, u8 *pbuf)
update_hw_ht_param(padapter);
}
- if (pmlmepriv->cur_network.join_res != true) { /* setting only at first time */
- /* WEP Key will be set before this function, do not clear CAM. */
+ /* setting only at first time */
+ if (!(pmlmepriv->cur_network.join_res)) {
+ /* WEP Key will be set before this function, do not
+ * clear CAM.
+ */
if ((psecuritypriv->dot11PrivacyAlgrthm != _WEP40_) &&
(psecuritypriv->dot11PrivacyAlgrthm != _WEP104_))
flush_all_cam_entry(padapter); /* clear CAM */
@@ -809,7 +814,9 @@ static void start_bss_network(struct adapter *padapter, u8 *pbuf)
}
}
}
- /* TODO: need to judge the phy parameters on concurrent mode for single phy */
+ /* TODO: need to judge the phy parameters on concurrent
+ * mode for single phy
+ */
set_channel_bwmode(padapter, cur_channel, cur_ch_offset, cur_bwmode);
DBG_88E("CH =%d, BW =%d, offset =%d\n", cur_channel, cur_bwmode, cur_ch_offset);
@@ -991,7 +998,7 @@ int rtw_check_beacon_data(struct adapter *padapter, u8 *pbuf, int len)
}
break;
}
- if ((p == NULL) || (ie_len == 0))
+ if ((!p) || (ie_len == 0))
break;
}
@@ -1005,9 +1012,12 @@ int rtw_check_beacon_data(struct adapter *padapter, u8 *pbuf, int len)
if ((p) && !memcmp(p + 2, WMM_PARA_IE, 6)) {
pmlmepriv->qospriv.qos_option = 1;
- *(p + 8) |= BIT(7);/* QoS Info, support U-APSD */
+ /* QoS Info, support U-APSD */
+ *(p + 8) |= BIT(7);
- /* disable all ACM bits since the WMM admission control is not supported */
+ /* disable all ACM bits since the WMM
+ * admission control is not supported
+ */
*(p + 10) &= ~BIT(4); /* BE */
*(p + 14) &= ~BIT(4); /* BK */
*(p + 18) &= ~BIT(4); /* VI */
@@ -1015,7 +1025,7 @@ int rtw_check_beacon_data(struct adapter *padapter, u8 *pbuf, int len)
break;
}
- if ((p == NULL) || (ie_len == 0))
+ if ((!p) || (ie_len == 0))
break;
}
}
@@ -1097,7 +1107,7 @@ int rtw_check_beacon_data(struct adapter *padapter, u8 *pbuf, int len)
psta = rtw_get_stainfo(&padapter->stapriv, pbss_network->MacAddress);
if (!psta) {
psta = rtw_alloc_stainfo(&padapter->stapriv, pbss_network->MacAddress);
- if (psta == NULL)
+ if (!psta)
return _FAIL;
}
@@ -1268,12 +1278,12 @@ static void update_bcn_wps_ie(struct adapter *padapter)
DBG_88E("%s\n", __func__);
pwps_ie_src = pmlmepriv->wps_beacon_ie;
- if (pwps_ie_src == NULL)
+ if (!pwps_ie_src)
return;
pwps_ie = rtw_get_wps_ie(ie+_FIXED_IE_LENGTH_, ielen-_FIXED_IE_LENGTH_, NULL, &wps_ielen);
- if (pwps_ie == NULL || wps_ielen == 0)
+ if (!pwps_ie || wps_ielen == 0)
return;
wps_offset = (uint)(pwps_ie-ie);
@@ -1834,7 +1844,9 @@ void stop_ap_mode(struct adapter *padapter)
pmlmepriv->update_bcn = false;
pmlmeext->bstart_bss = false;
- /* reset and init security priv , this can refine with rtw_reset_securitypriv */
+ /* reset and init security priv , this can refine with
+ * rtw_reset_securitypriv
+ */
memset((unsigned char *)&padapter->securitypriv, 0, sizeof(struct security_priv));
padapter->securitypriv.ndisauthtype = Ndis802_11AuthModeOpen;
padapter->securitypriv.ndisencryptstatus = Ndis802_11WEPDisabled;
diff --git a/drivers/staging/rtl8188eu/core/rtw_cmd.c b/drivers/staging/rtl8188eu/core/rtw_cmd.c
index 9754322b506e..002d09159896 100644
--- a/drivers/staging/rtl8188eu/core/rtw_cmd.c
+++ b/drivers/staging/rtl8188eu/core/rtw_cmd.c
@@ -21,35 +21,33 @@
#include <rtw_mlme_ext.h>
/*
-Caller and the rtw_cmd_thread can protect cmd_q by spin_lock.
-No irqsave is necessary.
-*/
+ * Caller and the rtw_cmd_thread can protect cmd_q by spin_lock.
+ * No irqsave is necessary.
+ */
int rtw_init_cmd_priv(struct cmd_priv *pcmdpriv)
{
init_completion(&pcmdpriv->cmd_queue_comp);
init_completion(&pcmdpriv->terminate_cmdthread_comp);
- _rtw_init_queue(&(pcmdpriv->cmd_queue));
+ _rtw_init_queue(&pcmdpriv->cmd_queue);
return _SUCCESS;
}
/*
-Calling Context:
-
-rtw_enqueue_cmd can only be called between kernel thread,
-since only spin_lock is used.
-
-ISR/Call-Back functions can't call this sub-function.
-
-*/
+ * Calling Context:
+ *
+ * rtw_enqueue_cmd can only be called between kernel thread,
+ * since only spin_lock is used.
+ *
+ * ISR/Call-Back functions can't call this sub-function.
+ */
static int _rtw_enqueue_cmd(struct __queue *queue, struct cmd_obj *obj)
{
unsigned long irqL;
-
- if (obj == NULL)
+ if (!obj)
goto exit;
spin_lock_irqsave(&queue->lock, irqL);
@@ -60,7 +58,6 @@ static int _rtw_enqueue_cmd(struct __queue *queue, struct cmd_obj *obj)
exit:
-
return _SUCCESS;
}
@@ -107,8 +104,7 @@ u32 rtw_enqueue_cmd(struct cmd_priv *pcmdpriv, struct cmd_obj *cmd_obj)
int res = _FAIL;
struct adapter *padapter = pcmdpriv->padapter;
-
- if (cmd_obj == NULL)
+ if (!cmd_obj)
goto exit;
cmd_obj->padapter = padapter;
@@ -126,19 +122,17 @@ u32 rtw_enqueue_cmd(struct cmd_priv *pcmdpriv, struct cmd_obj *cmd_obj)
exit:
-
return res;
}
void rtw_free_cmd_obj(struct cmd_obj *pcmd)
{
-
if ((pcmd->cmdcode != _JoinBss_CMD_) && (pcmd->cmdcode != _CreateBss_CMD_)) {
/* free parmbuf in cmd_obj */
kfree(pcmd->parmbuf);
}
- if (pcmd->rsp != NULL) {
+ if (!pcmd->rsp) {
if (pcmd->rspsz != 0) {
/* free rsp in cmd_obj */
kfree(pcmd->rsp);
@@ -147,7 +141,6 @@ void rtw_free_cmd_obj(struct cmd_obj *pcmd)
/* free cmd_obj */
kfree(pcmd);
-
}
int rtw_cmd_thread(void *context)
@@ -157,14 +150,15 @@ int rtw_cmd_thread(void *context)
u8 (*cmd_hdl)(struct adapter *padapter, u8 *pbuf);
void (*pcmd_callback)(struct adapter *dev, struct cmd_obj *pcmd);
struct adapter *padapter = context;
- struct cmd_priv *pcmdpriv = &(padapter->cmdpriv);
+ struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
allow_signal(SIGTERM);
pcmdpriv->cmdthd_running = true;
complete(&pcmdpriv->terminate_cmdthread_comp);
- RT_TRACE(_module_rtl871x_cmd_c_, _drv_info_, ("start r871x rtw_cmd_thread !!!!\n"));
+ RT_TRACE(_module_rtl871x_cmd_c_, _drv_info_,
+ ("start r871x %s !!!!\n", __func__));
while (1) {
if (wait_for_completion_interruptible(&pcmdpriv->cmd_queue_comp))
@@ -208,7 +202,7 @@ _next:
/* call callback function for post-processed */
if (pcmd->cmdcode < ARRAY_SIZE(rtw_cmd_callback)) {
pcmd_callback = rtw_cmd_callback[pcmd->cmdcode].callback;
- if (pcmd_callback == NULL) {
+ if (!pcmd_callback) {
RT_TRACE(_module_rtl871x_cmd_c_, _drv_info_, ("mlme_cmd_hdl(): pcmd_callback = 0x%p, cmdcode = 0x%x\n", pcmd_callback, pcmd->cmdcode));
rtw_free_cmd_obj(pcmd);
} else {
@@ -236,15 +230,15 @@ _next:
complete(&pcmdpriv->terminate_cmdthread_comp);
-
complete_and_exit(NULL, 0);
}
/*
-rtw_sitesurvey_cmd(~)
- ### NOTE:#### (!!!!)
- MUST TAKE CARE THAT BEFORE CALLING THIS FUNC, YOU SHOULD HAVE LOCKED pmlmepriv->lock
-*/
+ * rtw_sitesurvey_cmd(~)
+ * ### NOTE:#### (!!!!)
+ * MUST TAKE CARE THAT BEFORE CALLING THIS FUNC, YOU SHOULD HAVE
+ * LOCKED pmlmepriv->lock
+ */
u8 rtw_sitesurvey_cmd(struct adapter *padapter, struct ndis_802_11_ssid *ssid, int ssid_num,
struct rtw_ieee80211_channel *ch, int ch_num)
{
@@ -315,13 +309,11 @@ u8 rtw_sitesurvey_cmd(struct adapter *padapter, struct ndis_802_11_ssid *ssid,
_clr_fwstate_(pmlmepriv, _FW_UNDER_SURVEY);
}
-
return res;
}
void rtw_readtssi_cmdrsp_callback(struct adapter *padapter, struct cmd_obj *pcmd)
{
-
kfree(pcmd->parmbuf);
kfree(pcmd);
}
@@ -334,7 +326,6 @@ u8 rtw_createbss_cmd(struct adapter *padapter)
struct wlan_bssid_ex *pdev_network = &padapter->registrypriv.dev_network;
u8 res = _SUCCESS;
-
LedControl8188eu(padapter, LED_CTL_START_TO_LINK);
if (pmlmepriv->assoc_ssid.SsidLength == 0)
@@ -358,7 +349,6 @@ u8 rtw_createbss_cmd(struct adapter *padapter)
res = rtw_enqueue_cmd(pcmdpriv, pcmd);
exit:
-
return res;
}
@@ -376,8 +366,7 @@ u8 rtw_joinbss_cmd(struct adapter *padapter, struct wlan_network *pnetwork)
struct ht_priv *phtpriv = &pmlmepriv->htpriv;
enum ndis_802_11_network_infra ndis_network_mode = pnetwork->network.InfrastructureMode;
struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
- struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
-
+ struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
LedControl8188eu(padapter, LED_CTL_START_TO_LINK);
@@ -394,9 +383,8 @@ u8 rtw_joinbss_cmd(struct adapter *padapter, struct wlan_network *pnetwork)
/* for IEs is fix buf size */
t_len = sizeof(struct wlan_bssid_ex);
-
/* for hidden ap to set fw_state here */
- if (!check_fwstate(pmlmepriv, WIFI_STATION_STATE|WIFI_ADHOC_STATE)) {
+ if (!check_fwstate(pmlmepriv, WIFI_STATION_STATE | WIFI_ADHOC_STATE)) {
switch (ndis_network_mode) {
case Ndis802_11IBSS:
set_fwstate(pmlmepriv, WIFI_ADHOC_STATE);
@@ -412,12 +400,13 @@ u8 rtw_joinbss_cmd(struct adapter *padapter, struct wlan_network *pnetwork)
}
psecnetwork = (struct wlan_bssid_ex *)&psecuritypriv->sec_bss;
- if (psecnetwork == NULL) {
+ if (!psecnetwork) {
kfree(pcmd);
res = _FAIL;
- RT_TRACE(_module_rtl871x_cmd_c_, _drv_err_, ("rtw_joinbss_cmd :psecnetwork == NULL!!!\n"));
+ RT_TRACE(_module_rtl871x_cmd_c_, _drv_err_,
+ ("%s :psecnetwork == NULL!!!\n", __func__));
goto exit;
}
@@ -444,7 +433,6 @@ u8 rtw_joinbss_cmd(struct adapter *padapter, struct wlan_network *pnetwork)
psecnetwork->IELength = rtw_restruct_sec_ie(padapter, &pnetwork->network.IEs[0], &psecnetwork->IEs[0], pnetwork->network.IELength);
-
pqospriv->qos_option = 0;
if (pregistrypriv->wmm_enable) {
@@ -498,7 +486,6 @@ u8 rtw_joinbss_cmd(struct adapter *padapter, struct wlan_network *pnetwork)
exit:
-
return res;
}
@@ -509,8 +496,7 @@ u8 rtw_disassoc_cmd(struct adapter *padapter, u32 deauth_timeout_ms, bool enqueu
struct cmd_priv *cmdpriv = &padapter->cmdpriv;
u8 res = _SUCCESS;
-
- RT_TRACE(_module_rtl871x_cmd_c_, _drv_notice_, ("+rtw_disassoc_cmd\n"));
+ RT_TRACE(_module_rtl871x_cmd_c_, _drv_notice_, ("+%s\n", __func__));
/* prepare cmd parameter */
param = kzalloc(sizeof(*param), GFP_KERNEL);
@@ -539,7 +525,6 @@ u8 rtw_disassoc_cmd(struct adapter *padapter, u32 deauth_timeout_ms, bool enqueu
exit:
-
return res;
}
@@ -617,7 +602,6 @@ u8 rtw_clearstakey_cmd(struct adapter *padapter, u8 *psta, u8 entry, u8 enqueue)
struct sta_info *sta = (struct sta_info *)psta;
u8 res = _SUCCESS;
-
if (!enqueue) {
clear_cam_entry(padapter, entry);
} else {
@@ -656,7 +640,6 @@ u8 rtw_clearstakey_cmd(struct adapter *padapter, u8 *psta, u8 entry, u8 enqueue)
}
exit:
-
return res;
}
@@ -667,7 +650,6 @@ u8 rtw_addbareq_cmd(struct adapter *padapter, u8 tid, u8 *addr)
struct addBaReq_parm *paddbareq_parm;
u8 res = _SUCCESS;
-
ph2c = kzalloc(sizeof(struct cmd_obj), GFP_ATOMIC);
if (!ph2c) {
res = _FAIL;
@@ -693,7 +675,6 @@ u8 rtw_addbareq_cmd(struct adapter *padapter, u8 tid, u8 *addr)
exit:
-
return res;
}
@@ -704,7 +685,6 @@ u8 rtw_dynamic_chk_wk_cmd(struct adapter *padapter)
struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
u8 res = _SUCCESS;
-
ph2c = kzalloc(sizeof(struct cmd_obj), GFP_ATOMIC);
if (!ph2c) {
res = _FAIL;
@@ -724,7 +704,6 @@ u8 rtw_dynamic_chk_wk_cmd(struct adapter *padapter)
init_h2fwcmd_w_parm_no_rsp(ph2c, pdrvextra_cmd_parm, _Set_Drv_Extra_CMD_);
-
/* rtw_enqueue_cmd(pcmdpriv, ph2c); */
res = rtw_enqueue_cmd(pcmdpriv, ph2c);
exit:
@@ -739,8 +718,7 @@ u8 rtw_set_chplan_cmd(struct adapter *padapter, u8 chplan, u8 enqueue)
u8 res = _SUCCESS;
-
- RT_TRACE(_module_rtl871x_cmd_c_, _drv_notice_, ("+rtw_set_chplan_cmd\n"));
+ RT_TRACE(_module_rtl871x_cmd_c_, _drv_notice_, ("+%s\n", __func__));
/* check input parameter */
if (!rtw_is_channel_plan_valid(chplan)) {
@@ -781,7 +759,6 @@ u8 rtw_set_chplan_cmd(struct adapter *padapter, u8 chplan, u8 enqueue)
exit:
-
return res;
}
@@ -790,7 +767,7 @@ static void traffic_status_watchdog(struct adapter *padapter)
u8 bEnterPS;
u8 bBusyTraffic = false, bTxBusyTraffic = false, bRxBusyTraffic = false;
u8 bHigherBusyTraffic = false, bHigherBusyRxTraffic = false, bHigherBusyTxTraffic = false;
- struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
+ struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
/* */
/* Determine if our traffic is busy now */
@@ -849,7 +826,7 @@ static void dynamic_chk_wk_hdl(struct adapter *padapter, u8 *pbuf, int sz)
struct mlme_priv *pmlmepriv;
padapter = (struct adapter *)pbuf;
- pmlmepriv = &(padapter->mlmepriv);
+ pmlmepriv = &padapter->mlmepriv;
#ifdef CONFIG_88EU_AP_MODE
if (check_fwstate(pmlmepriv, WIFI_AP_STATE) == true)
@@ -865,10 +842,9 @@ static void dynamic_chk_wk_hdl(struct adapter *padapter, u8 *pbuf, int sz)
static void lps_ctrl_wk_hdl(struct adapter *padapter, u8 lps_ctrl_type)
{
struct pwrctrl_priv *pwrpriv = &padapter->pwrctrlpriv;
- struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
+ struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
u8 mstatus;
-
if ((check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE) == true) ||
(check_fwstate(pmlmepriv, WIFI_ADHOC_STATE) == true))
return;
@@ -905,7 +881,6 @@ static void lps_ctrl_wk_hdl(struct adapter *padapter, u8 lps_ctrl_type)
default:
break;
}
-
}
u8 rtw_lps_ctrl_wk_cmd(struct adapter *padapter, u8 lps_ctrl_type, u8 enqueue)
@@ -943,7 +918,6 @@ u8 rtw_lps_ctrl_wk_cmd(struct adapter *padapter, u8 lps_ctrl_type, u8 enqueue)
exit:
-
return res;
}
@@ -980,7 +954,6 @@ u8 rtw_rpt_timer_cfg_cmd(struct adapter *padapter, u16 min_time)
res = rtw_enqueue_cmd(pcmdpriv, ph2c);
exit:
-
return res;
}
@@ -1026,7 +999,6 @@ u8 rtw_antenna_select_cmd(struct adapter *padapter, u8 antenna, u8 enqueue)
}
exit:
-
return res;
}
@@ -1169,7 +1141,6 @@ void rtw_survey_cmd_callback(struct adapter *padapter, struct cmd_obj *pcmd)
{
struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
-
if (pcmd->res == H2C_DROPPED) {
/* TODO: cancel timer and do timeout handler directly... */
/* need to make timeout handlerOS independent */
@@ -1183,13 +1154,12 @@ void rtw_survey_cmd_callback(struct adapter *padapter, struct cmd_obj *pcmd)
/* free cmd */
rtw_free_cmd_obj(pcmd);
-
}
+
void rtw_disassoc_cmd_callback(struct adapter *padapter, struct cmd_obj *pcmd)
{
struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
-
if (pcmd->res != H2C_SUCCESS) {
spin_lock_bh(&pmlmepriv->lock);
set_fwstate(pmlmepriv, _FW_LINKED);
@@ -1207,7 +1177,6 @@ void rtw_joinbss_cmd_callback(struct adapter *padapter, struct cmd_obj *pcmd)
{
struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
-
if (pcmd->res == H2C_DROPPED) {
/* TODO: cancel timer and do timeout handler directly... */
/* need to make timeout handlerOS independent */
@@ -1220,7 +1189,6 @@ void rtw_joinbss_cmd_callback(struct adapter *padapter, struct cmd_obj *pcmd)
}
rtw_free_cmd_obj(pcmd);
-
}
void rtw_createbss_cmd_callback(struct adapter *padapter, struct cmd_obj *pcmd)
@@ -1229,11 +1197,11 @@ void rtw_createbss_cmd_callback(struct adapter *padapter, struct cmd_obj *pcmd)
struct wlan_network *pwlan = NULL;
struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
struct wlan_bssid_ex *pnetwork = (struct wlan_bssid_ex *)pcmd->parmbuf;
- struct wlan_network *tgt_network = &(pmlmepriv->cur_network);
-
+ struct wlan_network *tgt_network = &pmlmepriv->cur_network;
if (pcmd->res != H2C_SUCCESS) {
- RT_TRACE(_module_rtl871x_cmd_c_, _drv_err_, ("\n ********Error: rtw_createbss_cmd_callback Fail ************\n\n."));
+ RT_TRACE(_module_rtl871x_cmd_c_, _drv_err_,
+ ("\n **** Error: %s Fail ****\n\n.", __func__));
mod_timer(&pmlmepriv->assoc_timer,
jiffies + msecs_to_jiffies(1));
}
@@ -1246,7 +1214,7 @@ void rtw_createbss_cmd_callback(struct adapter *padapter, struct cmd_obj *pcmd)
psta = rtw_get_stainfo(&padapter->stapriv, pnetwork->MacAddress);
if (!psta) {
psta = rtw_alloc_stainfo(&padapter->stapriv, pnetwork->MacAddress);
- if (psta == NULL) {
+ if (!psta) {
RT_TRACE(_module_rtl871x_cmd_c_, _drv_err_, ("\nCan't alloc sta_info when createbss_cmd_callback\n"));
goto createbss_cmd_fail;
}
@@ -1255,28 +1223,31 @@ void rtw_createbss_cmd_callback(struct adapter *padapter, struct cmd_obj *pcmd)
rtw_indicate_connect(padapter);
} else {
pwlan = _rtw_alloc_network(pmlmepriv);
- spin_lock_bh(&(pmlmepriv->scanned_queue.lock));
- if (pwlan == NULL) {
+ spin_lock_bh(&pmlmepriv->scanned_queue.lock);
+ if (!pwlan) {
pwlan = rtw_get_oldest_wlan_network(&pmlmepriv->scanned_queue);
- if (pwlan == NULL) {
+ if (!pwlan) {
RT_TRACE(_module_rtl871x_cmd_c_, _drv_err_, ("\n Error: can't get pwlan in rtw_joinbss_event_callback\n"));
spin_unlock_bh(&pmlmepriv->scanned_queue.lock);
goto createbss_cmd_fail;
}
pwlan->last_scanned = jiffies;
} else {
- list_add_tail(&(pwlan->list), &pmlmepriv->scanned_queue.queue);
+ list_add_tail(&pwlan->list,
+ &pmlmepriv->scanned_queue.queue);
}
pnetwork->Length = get_wlan_bssid_ex_sz(pnetwork);
- memcpy(&(pwlan->network), pnetwork, pnetwork->Length);
+ memcpy(&pwlan->network, pnetwork, pnetwork->Length);
memcpy(&tgt_network->network, pnetwork, (get_wlan_bssid_ex_sz(pnetwork)));
_clr_fwstate_(pmlmepriv, _FW_UNDER_LINKING);
spin_unlock_bh(&pmlmepriv->scanned_queue.lock);
- /* we will set _FW_LINKED when there is one more sat to join us (rtw_stassoc_event_callback) */
+ /* we will set _FW_LINKED when there is one more sat to
+ * join us (rtw_stassoc_event_callback)
+ */
}
createbss_cmd_fail:
@@ -1284,7 +1255,6 @@ createbss_cmd_fail:
spin_unlock_bh(&pmlmepriv->lock);
rtw_free_cmd_obj(pcmd);
-
}
void rtw_setstaKey_cmdrsp_callback(struct adapter *padapter, struct cmd_obj *pcmd)
@@ -1293,8 +1263,7 @@ void rtw_setstaKey_cmdrsp_callback(struct adapter *padapter, struct cmd_obj *pc
struct set_stakey_rsp *psetstakey_rsp = (struct set_stakey_rsp *)(pcmd->rsp);
struct sta_info *psta = rtw_get_stainfo(pstapriv, psetstakey_rsp->addr);
-
- if (psta == NULL) {
+ if (!psta) {
RT_TRACE(_module_rtl871x_cmd_c_, _drv_err_, ("\nERROR: %s => can't get sta_info\n\n", __func__));
goto exit;
}
@@ -1310,8 +1279,7 @@ void rtw_setassocsta_cmdrsp_callback(struct adapter *padapter, struct cmd_obj *
struct set_assocsta_rsp *passocsta_rsp = (struct set_assocsta_rsp *)(pcmd->rsp);
struct sta_info *psta = rtw_get_stainfo(pstapriv, passocsta_parm->addr);
-
- if (psta == NULL) {
+ if (!psta) {
RT_TRACE(_module_rtl871x_cmd_c_, _drv_err_, ("\nERROR: %s => can't get sta_info\n\n", __func__));
goto exit;
}
@@ -1326,5 +1294,4 @@ void rtw_setassocsta_cmdrsp_callback(struct adapter *padapter, struct cmd_obj *
exit:
rtw_free_cmd_obj(pcmd);
-
}
diff --git a/drivers/staging/rtl8188eu/core/rtw_ieee80211.c b/drivers/staging/rtl8188eu/core/rtw_ieee80211.c
index d1dafe0f20c6..bb867a987c2b 100644
--- a/drivers/staging/rtl8188eu/core/rtw_ieee80211.c
+++ b/drivers/staging/rtl8188eu/core/rtw_ieee80211.c
@@ -955,50 +955,6 @@ void rtw_macaddr_cfg(u8 *mac_addr)
DBG_88E("rtw_macaddr_cfg MAC Address = %pM\n", (mac_addr));
}
-/* Baron adds to avoid FreeBSD warning */
-int ieee80211_is_empty_essid(const char *essid, int essid_len)
-{
- /* Single white space is for Linksys APs */
- if (essid_len == 1 && essid[0] == ' ')
- return 1;
-
- /* Otherwise, if the entire essid is 0, we assume it is hidden */
- while (essid_len) {
- essid_len--;
- if (essid[essid_len] != '\0')
- return 0;
- }
-
- return 1;
-}
-
-int ieee80211_get_hdrlen(u16 fc)
-{
- int hdrlen = 24;
-
- switch (WLAN_FC_GET_TYPE(fc)) {
- case RTW_IEEE80211_FTYPE_DATA:
- if (fc & RTW_IEEE80211_STYPE_QOS_DATA)
- hdrlen += 2;
- if ((fc & RTW_IEEE80211_FCTL_FROMDS) && (fc & RTW_IEEE80211_FCTL_TODS))
- hdrlen += 6; /* Addr4 */
- break;
- case RTW_IEEE80211_FTYPE_CTL:
- switch (WLAN_FC_GET_STYPE(fc)) {
- case RTW_IEEE80211_STYPE_CTS:
- case RTW_IEEE80211_STYPE_ACK:
- hdrlen = 10;
- break;
- default:
- hdrlen = 16;
- break;
- }
- break;
- }
-
- return hdrlen;
-}
-
static int rtw_get_cipher_info(struct wlan_network *pnetwork)
{
uint wpa_ielen;
diff --git a/drivers/staging/rtl8188eu/core/rtw_mlme.c b/drivers/staging/rtl8188eu/core/rtw_mlme.c
index 301085a459c9..fde306087844 100644
--- a/drivers/staging/rtl8188eu/core/rtw_mlme.c
+++ b/drivers/staging/rtl8188eu/core/rtw_mlme.c
@@ -370,7 +370,7 @@ void update_network(struct wlan_bssid_ex *dst, struct wlan_bssid_ex *src,
sq_final = padapter->recvpriv.signal_qual;
/* the rssi value here is undecorated, and will be used for antenna diversity */
if (sq_smp != 101) /* from the right channel */
- rssi_final = (src->Rssi+dst->Rssi*4)/5;
+ rssi_final = (src->Rssi + dst->Rssi * 4) / 5;
else
rssi_final = rssi_ori;
} else {
@@ -1081,10 +1081,10 @@ void rtw_joinbss_event_prehandle(struct adapter *adapter, u8 *pbuf)
RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_, ("adhoc mode, fw_state:%x", get_fwstate(pmlmepriv)));
}
- /* s5. Cancle assoc_timer */
+ /* s5. Cancel assoc_timer */
del_timer_sync(&pmlmepriv->assoc_timer);
- RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_, ("Cancle assoc_timer\n"));
+ RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_, ("Cancel assoc_timer\n"));
} else {
RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_, ("rtw_joinbss_event_callback err: fw_state:%x", get_fwstate(pmlmepriv)));
@@ -1926,7 +1926,7 @@ unsigned int rtw_restructure_ht_ie(struct adapter *padapter, u8 *in_ie, u8 *out_
if (pqospriv->qos_option == 0) {
out_len = *pout_len;
- rtw_set_ie(out_ie+out_len, _VENDOR_SPECIFIC_IE_,
+ rtw_set_ie(out_ie + out_len, _VENDOR_SPECIFIC_IE_,
_WMM_IE_Length_, WMM_IE, pout_len);
pqospriv->qos_option = 1;
@@ -2058,8 +2058,8 @@ void rtw_issue_addbareq_cmd(struct adapter *padapter, struct xmit_frame *pxmitfr
phtpriv = &psta->htpriv;
if ((phtpriv->ht_option) && (phtpriv->ampdu_enable)) {
- issued = (phtpriv->agg_enable_bitmap>>priority)&0x1;
- issued |= (phtpriv->candidate_tid_bitmap>>priority)&0x1;
+ issued = (phtpriv->agg_enable_bitmap >> priority) & 0x1;
+ issued |= (phtpriv->candidate_tid_bitmap >> priority) & 0x1;
if (issued == 0) {
DBG_88E("rtw_issue_addbareq_cmd, p=%d\n", priority);
diff --git a/drivers/staging/rtl8188eu/core/rtw_recv.c b/drivers/staging/rtl8188eu/core/rtw_recv.c
index c6c4404e717b..2c37bb548c0f 100644
--- a/drivers/staging/rtl8188eu/core/rtw_recv.c
+++ b/drivers/staging/rtl8188eu/core/rtw_recv.c
@@ -259,12 +259,10 @@ static int recvframe_chkmic(struct adapter *adapter,
}
/* icv_len included the mic code */
- datalen = precvframe->pkt->len-prxattrib->hdrlen -
- prxattrib->iv_len-prxattrib->icv_len-8;
+ datalen = precvframe->pkt->len-prxattrib->hdrlen - 8;
pframe = precvframe->pkt->data;
- payload = pframe+prxattrib->hdrlen+prxattrib->iv_len;
+ payload = pframe+prxattrib->hdrlen;
- RT_TRACE(_module_rtl871x_recv_c_, _drv_info_, ("\n prxattrib->iv_len=%d prxattrib->icv_len=%d\n", prxattrib->iv_len, prxattrib->icv_len));
rtw_seccalctkipmic(mickey, pframe, payload, datalen, &miccode[0],
(unsigned char)prxattrib->priority); /* care the length of the data */
@@ -409,9 +407,15 @@ static struct recv_frame *decryptor(struct adapter *padapter,
default:
break;
}
+ if (res != _FAIL) {
+ memmove(precv_frame->pkt->data + precv_frame->attrib.iv_len, precv_frame->pkt->data, precv_frame->attrib.hdrlen);
+ skb_pull(precv_frame->pkt, precv_frame->attrib.iv_len);
+ skb_trim(precv_frame->pkt, precv_frame->pkt->len - precv_frame->attrib.icv_len);
+ }
} else if (prxattrib->bdecrypted == 1 && prxattrib->encrypt > 0 &&
- (psecuritypriv->busetkipkey == 1 || prxattrib->encrypt != _TKIP_))
- psecuritypriv->hw_decrypted = true;
+ (psecuritypriv->busetkipkey == 1 || prxattrib->encrypt != _TKIP_)) {
+ psecuritypriv->hw_decrypted = true;
+ }
if (res == _FAIL) {
rtw_free_recvframe(return_packet, &padapter->recvpriv.free_recv_queue);
@@ -452,7 +456,7 @@ static struct recv_frame *portctrl(struct adapter *adapter,
if (auth_alg == 2) {
/* get ether_type */
- ptr = ptr + pfhdr->attrib.hdrlen + LLC_HEADER_SIZE + pfhdr->attrib.iv_len;
+ ptr = ptr + pfhdr->attrib.hdrlen + LLC_HEADER_SIZE;
memcpy(&be_tmp, ptr, 2);
ether_type = ntohs(be_tmp);
@@ -1134,6 +1138,8 @@ static int validate_recv_data_frame(struct adapter *adapter,
}
if (pattrib->privacy) {
+ struct sk_buff *skb = precv_frame->pkt;
+
RT_TRACE(_module_rtl871x_recv_c_, _drv_info_, ("validate_recv_data_frame:pattrib->privacy=%x\n", pattrib->privacy));
RT_TRACE(_module_rtl871x_recv_c_, _drv_info_, ("\n ^^^^^^^^^^^IS_MCAST(pattrib->ra(0x%02x))=%d^^^^^^^^^^^^^^^6\n", pattrib->ra[0], IS_MCAST(pattrib->ra)));
@@ -1142,6 +1148,13 @@ static int validate_recv_data_frame(struct adapter *adapter,
RT_TRACE(_module_rtl871x_recv_c_, _drv_info_, ("\n pattrib->encrypt=%d\n", pattrib->encrypt));
SET_ICE_IV_LEN(pattrib->iv_len, pattrib->icv_len, pattrib->encrypt);
+
+ if (pattrib->bdecrypted == 1 && pattrib->encrypt > 0) {
+ memmove(skb->data + pattrib->iv_len,
+ skb->data, pattrib->hdrlen);
+ skb_pull(skb, pattrib->iv_len);
+ skb_trim(skb, skb->len - pattrib->icv_len);
+ }
} else {
pattrib->encrypt = 0;
pattrib->iv_len = 0;
@@ -1261,6 +1274,7 @@ static int validate_recv_frame(struct adapter *adapter,
* Hence forward the frame to the monitor anyway to preserve the order
* in which frames were received.
*/
+
rtl88eu_mon_recv_hook(adapter->pmondev, precv_frame);
exit:
@@ -1282,11 +1296,8 @@ static int wlanhdr_to_ethhdr(struct recv_frame *precvframe)
u8 *ptr = precvframe->pkt->data;
struct rx_pkt_attrib *pattrib = &precvframe->attrib;
- if (pattrib->encrypt)
- skb_trim(precvframe->pkt, precvframe->pkt->len - pattrib->icv_len);
-
- psnap = (struct ieee80211_snap_hdr *)(ptr+pattrib->hdrlen + pattrib->iv_len);
- psnap_type = ptr+pattrib->hdrlen + pattrib->iv_len+SNAP_SIZE;
+ psnap = (struct ieee80211_snap_hdr *)(ptr+pattrib->hdrlen);
+ psnap_type = ptr+pattrib->hdrlen + SNAP_SIZE;
/* convert hdr + possible LLC headers into Ethernet header */
if ((!memcmp(psnap, rtw_rfc1042_header, SNAP_SIZE) &&
(!memcmp(psnap_type, SNAP_ETH_TYPE_IPX, 2) == false) &&
@@ -1299,12 +1310,9 @@ static int wlanhdr_to_ethhdr(struct recv_frame *precvframe)
bsnaphdr = false;
}
- rmv_len = pattrib->hdrlen + pattrib->iv_len + (bsnaphdr ? SNAP_SIZE : 0);
+ rmv_len = pattrib->hdrlen + (bsnaphdr ? SNAP_SIZE : 0);
len = precvframe->pkt->len - rmv_len;
- RT_TRACE(_module_rtl871x_recv_c_, _drv_info_,
- ("\n===pattrib->hdrlen: %x, pattrib->iv_len:%x===\n\n", pattrib->hdrlen, pattrib->iv_len));
-
memcpy(&be_tmp, ptr+rmv_len, 2);
eth_type = ntohs(be_tmp); /* pattrib->ether_type */
pattrib->eth_type = eth_type;
@@ -1329,7 +1337,6 @@ static struct recv_frame *recvframe_defrag(struct adapter *adapter,
struct __queue *defrag_q)
{
struct list_head *plist, *phead;
- u8 wlanhdr_offset;
u8 curfragnum;
struct recv_frame *pfhdr, *pnfhdr;
struct recv_frame *prframe, *pnextrframe;
@@ -1378,12 +1385,7 @@ static struct recv_frame *recvframe_defrag(struct adapter *adapter,
/* copy the 2nd~n fragment frame's payload to the first fragment */
/* get the 2nd~last fragment frame's payload */
- wlanhdr_offset = pnfhdr->attrib.hdrlen + pnfhdr->attrib.iv_len;
-
- skb_pull(pnextrframe->pkt, wlanhdr_offset);
-
- /* append to first fragment frame's tail (if privacy frame, pull the ICV) */
- skb_trim(prframe->pkt, prframe->pkt->len - pfhdr->attrib.icv_len);
+ skb_pull(pnextrframe->pkt, pnfhdr->attrib.hdrlen);
/* memcpy */
memcpy(skb_tail_pointer(pfhdr->pkt), pnfhdr->pkt->data,
@@ -1391,7 +1393,7 @@ static struct recv_frame *recvframe_defrag(struct adapter *adapter,
skb_put(prframe->pkt, pnfhdr->pkt->len);
- pfhdr->attrib.icv_len = pnfhdr->attrib.icv_len;
+ pfhdr->attrib.icv_len = 0;
plist = plist->next;
}
@@ -1518,11 +1520,6 @@ static int amsdu_to_msdu(struct adapter *padapter, struct recv_frame *prframe)
nr_subframes = 0;
pattrib = &prframe->attrib;
- skb_pull(prframe->pkt, prframe->attrib.hdrlen);
-
- if (prframe->attrib.iv_len > 0)
- skb_pull(prframe->pkt, prframe->attrib.iv_len);
-
a_len = prframe->pkt->len;
pdata = prframe->pkt->data;
@@ -1892,24 +1889,6 @@ static int process_recv_indicatepkts(struct adapter *padapter,
return retval;
}
-static int recv_func_prehandle(struct adapter *padapter,
- struct recv_frame *rframe)
-{
- int ret = _SUCCESS;
- struct __queue *pfree_recv_queue = &padapter->recvpriv.free_recv_queue;
-
- /* check the frame crtl field and decache */
- ret = validate_recv_frame(padapter, rframe);
- if (ret != _SUCCESS) {
- RT_TRACE(_module_rtl871x_recv_c_, _drv_info_, ("recv_func: validate_recv_frame fail! drop pkt\n"));
- rtw_free_recvframe(rframe, pfree_recv_queue);/* free this recv_frame */
- goto exit;
- }
-
-exit:
- return ret;
-}
-
static int recv_func_posthandle(struct adapter *padapter,
struct recv_frame *prframe)
{
@@ -1962,6 +1941,7 @@ static int recv_func(struct adapter *padapter, struct recv_frame *rframe)
struct rx_pkt_attrib *prxattrib = &rframe->attrib;
struct security_priv *psecuritypriv = &padapter->securitypriv;
struct mlme_priv *mlmepriv = &padapter->mlmepriv;
+ struct __queue *pfree_recv_queue = &padapter->recvpriv.free_recv_queue;
/* check if need to handle uc_swdec_pending_queue*/
if (check_fwstate(mlmepriv, WIFI_STATION_STATE) && psecuritypriv->busetkipkey) {
@@ -1973,9 +1953,12 @@ static int recv_func(struct adapter *padapter, struct recv_frame *rframe)
}
}
- ret = recv_func_prehandle(padapter, rframe);
-
- if (ret == _SUCCESS) {
+ /* check the frame crtl field and decache */
+ ret = validate_recv_frame(padapter, rframe);
+ if (ret != _SUCCESS) {
+ RT_TRACE(_module_rtl871x_recv_c_, _drv_info_, ("recv_func: validate_recv_frame fail! drop pkt\n"));
+ rtw_free_recvframe(rframe, pfree_recv_queue);/* free this recv_frame */
+ } else {
/* check if need to enqueue into uc_swdec_pending_queue*/
if (check_fwstate(mlmepriv, WIFI_STATION_STATE) &&
!IS_MCAST(prxattrib->ra) && prxattrib->encrypt > 0 &&
diff --git a/drivers/staging/rtl8188eu/core/rtw_sta_mgt.c b/drivers/staging/rtl8188eu/core/rtw_sta_mgt.c
index 2ecfb117bf3f..22cf362b8528 100644
--- a/drivers/staging/rtl8188eu/core/rtw_sta_mgt.c
+++ b/drivers/staging/rtl8188eu/core/rtw_sta_mgt.c
@@ -61,7 +61,6 @@ static void _rtw_init_stainfo(struct sta_info *psta)
psta->keep_alive_trycnt = 0;
#endif /* CONFIG_88EU_AP_MODE */
-
}
u32 _rtw_init_sta_priv(struct sta_priv *pstapriv)
@@ -69,7 +68,6 @@ u32 _rtw_init_sta_priv(struct sta_priv *pstapriv)
struct sta_info *psta;
s32 i;
-
pstapriv->pallocated_stainfo_buf = vzalloc(sizeof(struct sta_info) * NUM_STA + 4);
if (!pstapriv->pallocated_stainfo_buf)
@@ -116,7 +114,6 @@ u32 _rtw_init_sta_priv(struct sta_priv *pstapriv)
pstapriv->max_num_sta = NUM_STA;
#endif
-
return _SUCCESS;
}
@@ -263,7 +260,6 @@ u32 rtw_free_stainfo(struct adapter *padapter, struct sta_info *psta)
struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
struct sta_priv *pstapriv = &padapter->stapriv;
-
if (!psta)
goto exit;
@@ -381,7 +377,6 @@ u32 rtw_free_stainfo(struct adapter *padapter, struct sta_info *psta)
exit:
-
return _SUCCESS;
}
@@ -394,7 +389,6 @@ void rtw_free_all_stainfo(struct adapter *padapter)
struct sta_priv *pstapriv = &padapter->stapriv;
struct sta_info *pbcmc_stainfo = rtw_get_bcmc_stainfo(padapter);
-
if (pstapriv->asoc_sta_count == 1)
return;
@@ -425,7 +419,6 @@ struct sta_info *rtw_get_stainfo(struct sta_priv *pstapriv, u8 *hwaddr)
u8 *addr;
u8 bc_addr[ETH_ALEN] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
-
if (!hwaddr)
return NULL;
@@ -463,7 +456,6 @@ u32 rtw_init_bcmc_stainfo(struct adapter *padapter)
unsigned char bcast_addr[ETH_ALEN] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
struct sta_priv *pstapriv = &padapter->stapriv;
-
psta = rtw_alloc_stainfo(pstapriv, bcast_addr);
if (!psta) {
diff --git a/drivers/staging/rtl8188eu/hal/phy.c b/drivers/staging/rtl8188eu/hal/phy.c
index 054f5996f60d..3039bbe44a25 100644
--- a/drivers/staging/rtl8188eu/hal/phy.c
+++ b/drivers/staging/rtl8188eu/hal/phy.c
@@ -1091,7 +1091,7 @@ static void phy_iq_calibrate(struct adapter *adapt, s32 result[][8],
}
}
- if (0x00 == path_a_ok) {
+ if (path_a_ok == 0x00) {
ODM_RT_TRACE(dm_odm, ODM_COMP_CALIBRATION, ODM_DBG_LOUD,
("Path A IQK failed!!\n"));
}
@@ -1122,7 +1122,7 @@ static void phy_iq_calibrate(struct adapter *adapt, s32 result[][8],
}
}
- if (0x00 == path_b_ok) {
+ if (path_b_ok == 0x00) {
ODM_RT_TRACE(dm_odm, ODM_COMP_CALIBRATION, ODM_DBG_LOUD,
("Path B IQK failed!!\n"));
}
diff --git a/drivers/staging/rtl8188eu/hal/rtl8188e_rxdesc.c b/drivers/staging/rtl8188eu/hal/rtl8188e_rxdesc.c
index d9fa290c5f78..9f51f54f866a 100644
--- a/drivers/staging/rtl8188eu/hal/rtl8188e_rxdesc.c
+++ b/drivers/staging/rtl8188eu/hal/rtl8188e_rxdesc.c
@@ -58,7 +58,7 @@ static void process_link_qual(struct adapter *padapter,
}
void rtl8188e_process_phy_info(struct adapter *padapter,
- struct recv_frame *precvframe)
+ struct recv_frame *precvframe)
{
/* Check RSSI */
process_rssi(padapter, precvframe);
diff --git a/drivers/staging/rtl8188eu/include/ieee80211.h b/drivers/staging/rtl8188eu/include/ieee80211.h
index 22ab0c43e376..284db7d00f50 100644
--- a/drivers/staging/rtl8188eu/include/ieee80211.h
+++ b/drivers/staging/rtl8188eu/include/ieee80211.h
@@ -306,68 +306,6 @@ enum eap_type {
#define MIN_FRAG_THRESHOLD 256U
#define MAX_FRAG_THRESHOLD 2346U
-/* Frame control field constants */
-#define RTW_IEEE80211_FCTL_VERS 0x0003
-#define RTW_IEEE80211_FCTL_FTYPE 0x000c
-#define RTW_IEEE80211_FCTL_STYPE 0x00f0
-#define RTW_IEEE80211_FCTL_TODS 0x0100
-#define RTW_IEEE80211_FCTL_FROMDS 0x0200
-#define RTW_IEEE80211_FCTL_MOREFRAGS 0x0400
-#define RTW_IEEE80211_FCTL_RETRY 0x0800
-#define RTW_IEEE80211_FCTL_PM 0x1000
-#define RTW_IEEE80211_FCTL_MOREDATA 0x2000
-#define RTW_IEEE80211_FCTL_PROTECTED 0x4000
-#define RTW_IEEE80211_FCTL_ORDER 0x8000
-#define RTW_IEEE80211_FCTL_CTL_EXT 0x0f00
-
-#define RTW_IEEE80211_FTYPE_MGMT 0x0000
-#define RTW_IEEE80211_FTYPE_CTL 0x0004
-#define RTW_IEEE80211_FTYPE_DATA 0x0008
-#define RTW_IEEE80211_FTYPE_EXT 0x000c
-
-/* management */
-#define RTW_IEEE80211_STYPE_ASSOC_REQ 0x0000
-#define RTW_IEEE80211_STYPE_ASSOC_RESP 0x0010
-#define RTW_IEEE80211_STYPE_REASSOC_REQ 0x0020
-#define RTW_IEEE80211_STYPE_REASSOC_RESP 0x0030
-#define RTW_IEEE80211_STYPE_PROBE_REQ 0x0040
-#define RTW_IEEE80211_STYPE_PROBE_RESP 0x0050
-#define RTW_IEEE80211_STYPE_BEACON 0x0080
-#define RTW_IEEE80211_STYPE_ATIM 0x0090
-#define RTW_IEEE80211_STYPE_DISASSOC 0x00A0
-#define RTW_IEEE80211_STYPE_AUTH 0x00B0
-#define RTW_IEEE80211_STYPE_DEAUTH 0x00C0
-#define RTW_IEEE80211_STYPE_ACTION 0x00D0
-
-/* control */
-#define RTW_IEEE80211_STYPE_CTL_EXT 0x0060
-#define RTW_IEEE80211_STYPE_BACK_REQ 0x0080
-#define RTW_IEEE80211_STYPE_BACK 0x0090
-#define RTW_IEEE80211_STYPE_PSPOLL 0x00A0
-#define RTW_IEEE80211_STYPE_RTS 0x00B0
-#define RTW_IEEE80211_STYPE_CTS 0x00C0
-#define RTW_IEEE80211_STYPE_ACK 0x00D0
-#define RTW_IEEE80211_STYPE_CFEND 0x00E0
-#define RTW_IEEE80211_STYPE_CFENDACK 0x00F0
-
-/* data */
-#define RTW_IEEE80211_STYPE_DATA 0x0000
-#define RTW_IEEE80211_STYPE_DATA_CFACK 0x0010
-#define RTW_IEEE80211_STYPE_DATA_CFPOLL 0x0020
-#define RTW_IEEE80211_STYPE_DATA_CFACKPOLL 0x0030
-#define RTW_IEEE80211_STYPE_NULLFUNC 0x0040
-#define RTW_IEEE80211_STYPE_CFACK 0x0050
-#define RTW_IEEE80211_STYPE_CFPOLL 0x0060
-#define RTW_IEEE80211_STYPE_CFACKPOLL 0x0070
-#define RTW_IEEE80211_STYPE_QOS_DATA 0x0080
-#define RTW_IEEE80211_STYPE_QOS_DATA_CFACK 0x0090
-#define RTW_IEEE80211_STYPE_QOS_DATA_CFPOLL 0x00A0
-#define RTW_IEEE80211_STYPE_QOS_DATA_CFACKPOLL 0x00B0
-#define RTW_IEEE80211_STYPE_QOS_NULLFUNC 0x00C0
-#define RTW_IEEE80211_STYPE_QOS_CFACK 0x00D0
-#define RTW_IEEE80211_STYPE_QOS_CFPOLL 0x00E0
-#define RTW_IEEE80211_STYPE_QOS_CFACKPOLL 0x00F0
-
/* sequence control field */
#define RTW_IEEE80211_SCTL_FRAG 0x000F
#define RTW_IEEE80211_SCTL_SEQ 0xFFF0
@@ -408,9 +346,6 @@ struct ieee80211_snap_hdr {
#define SNAP_SIZE sizeof(struct ieee80211_snap_hdr)
-#define WLAN_FC_GET_TYPE(fc) ((fc) & RTW_IEEE80211_FCTL_FTYPE)
-#define WLAN_FC_GET_STYPE(fc) ((fc) & RTW_IEEE80211_FCTL_STYPE)
-
#define WLAN_QC_GET_TID(qc) ((qc) & 0x0f)
#define WLAN_GET_SEQ_FRAG(seq) ((seq) & RTW_IEEE80211_SCTL_FRAG)
@@ -423,14 +358,6 @@ struct ieee80211_snap_hdr {
#define IEEE80211_DATA_HDR3_LEN 24
#define IEEE80211_DATA_HDR4_LEN 30
-
-#define IEEE80211_STATMASK_SIGNAL (1<<0)
-#define IEEE80211_STATMASK_RSSI (1<<1)
-#define IEEE80211_STATMASK_NOISE (1<<2)
-#define IEEE80211_STATMASK_RATE (1<<3)
-#define IEEE80211_STATMASK_WEMASK 0x7
-
-
#define IEEE80211_CCK_MODULATION (1<<0)
#define IEEE80211_OFDM_MODULATION (1<<1)
@@ -488,9 +415,6 @@ struct ieee80211_snap_hdr {
IEEE80211_OFDM_RATE_36MB_MASK | \
IEEE80211_OFDM_RATE_48MB_MASK | \
IEEE80211_OFDM_RATE_54MB_MASK)
-#define IEEE80211_DEFAULT_RATES_MASK \
- (IEEE80211_OFDM_DEFAULT_RATES_MASK | \
- IEEE80211_CCK_DEFAULT_RATES_MASK)
#define IEEE80211_NUM_OFDM_RATES 8
#define IEEE80211_NUM_CCK_RATES 4
@@ -521,25 +445,6 @@ struct ieee80211_snap_hdr {
#define WEP_KEYS 4
#define WEP_KEY_LEN 13
-#define BEACON_PROBE_SSID_ID_POSITION 12
-
-/* Management Frame Information Element Types */
-#define MFIE_TYPE_SSID 0
-#define MFIE_TYPE_RATES 1
-#define MFIE_TYPE_FH_SET 2
-#define MFIE_TYPE_DS_SET 3
-#define MFIE_TYPE_CF_SET 4
-#define MFIE_TYPE_TIM 5
-#define MFIE_TYPE_IBSS_SET 6
-#define MFIE_TYPE_CHALLENGE 16
-#define MFIE_TYPE_ERP 42
-#define MFIE_TYPE_RSN 48
-#define MFIE_TYPE_RATES_EX 50
-#define MFIE_TYPE_GENERIC 221
-
-#define IEEE80211_DEFAULT_TX_ESSID "Penguin"
-#define IEEE80211_DEFAULT_BASIC_RATE 10
-
/* SWEEP TABLE ENTRIES NUMBER*/
#define MAX_SWEEP_TAB_ENTRIES 42
#define MAX_SWEEP_TAB_ENTRIES_PER_PACKET 7
@@ -566,14 +471,6 @@ struct ieee80211_snap_hdr {
#define NETWORK_HAS_OFDM (1<<1)
#define NETWORK_HAS_CCK (1<<2)
-#define IEEE80211_DTIM_MBCAST 4
-#define IEEE80211_DTIM_UCAST 2
-#define IEEE80211_DTIM_VALID 1
-#define IEEE80211_DTIM_INVALID 0
-
-#define IEEE80211_PS_DISABLED 0
-#define IEEE80211_PS_UNICAST IEEE80211_DTIM_UCAST
-#define IEEE80211_PS_MBCAST IEEE80211_DTIM_MBCAST
#define IW_ESSID_MAX_SIZE 32
/*
join_res:
@@ -644,10 +541,6 @@ static inline int is_broadcast_mac_addr(const u8 *addr)
#define IEEE_G (1<<2)
#define IEEE_MODE_MASK (IEEE_A|IEEE_B|IEEE_G)
-/* Baron move to ieee80211.c */
-int ieee80211_is_empty_essid(const char *essid, int essid_len);
-int ieee80211_get_hdrlen(u16 fc);
-
/* Action category code */
enum rtw_ieee80211_category {
RTW_WLAN_CATEGORY_SPECTRUM_MGMT = 0,
diff --git a/drivers/staging/rtl8188eu/os_dep/mon.c b/drivers/staging/rtl8188eu/os_dep/mon.c
index cfe37eb026d6..7326d9b0fa7f 100644
--- a/drivers/staging/rtl8188eu/os_dep/mon.c
+++ b/drivers/staging/rtl8188eu/os_dep/mon.c
@@ -66,6 +66,34 @@ static void mon_recv_decrypted(struct net_device *dev, const u8 *data,
netif_rx(skb);
}
+static void mon_recv_decrypted_recv(struct net_device *dev, const u8 *data,
+ int data_len)
+{
+ struct sk_buff *skb;
+ struct ieee80211_hdr *hdr;
+ int hdr_len;
+
+ skb = netdev_alloc_skb(dev, data_len);
+ if (!skb)
+ return;
+ memcpy(skb_put(skb, data_len), data, data_len);
+
+ /*
+ * Frame data is not encrypted. Strip off protection so
+ * userspace doesn't think that it is.
+ */
+
+ hdr = (struct ieee80211_hdr *)skb->data;
+ hdr_len = ieee80211_hdrlen(hdr->frame_control);
+
+ if (ieee80211_has_protected(hdr->frame_control))
+ hdr->frame_control &= ~cpu_to_le16(IEEE80211_FCTL_PROTECTED);
+
+ skb->ip_summed = CHECKSUM_UNNECESSARY;
+ skb->protocol = eth_type_trans(skb, dev);
+ netif_rx(skb);
+}
+
static void mon_recv_encrypted(struct net_device *dev, const u8 *data,
int data_len)
{
@@ -82,7 +110,6 @@ static void mon_recv_encrypted(struct net_device *dev, const u8 *data,
void rtl88eu_mon_recv_hook(struct net_device *dev, struct recv_frame *frame)
{
struct rx_pkt_attrib *attr;
- int iv_len, icv_len;
int data_len;
u8 *data;
@@ -95,11 +122,8 @@ void rtl88eu_mon_recv_hook(struct net_device *dev, struct recv_frame *frame)
data = frame->pkt->data;
data_len = frame->pkt->len;
- /* Broadcast and multicast frames don't have attr->{iv,icv}_len set */
- SET_ICE_IV_LEN(iv_len, icv_len, attr->encrypt);
-
if (attr->bdecrypted)
- mon_recv_decrypted(dev, data, data_len, iv_len, icv_len);
+ mon_recv_decrypted_recv(dev, data, data_len);
else
mon_recv_encrypted(dev, data, data_len);
}
@@ -152,7 +176,7 @@ static const struct net_device_ops mon_netdev_ops = {
static void mon_setup(struct net_device *dev)
{
dev->netdev_ops = &mon_netdev_ops;
- dev->destructor = free_netdev;
+ dev->needs_free_netdev = true;
ether_setup(dev);
dev->priv_flags |= IFF_NO_QUEUE;
dev->type = ARPHRD_IEEE80211;
diff --git a/drivers/staging/rtl8192e/dot11d.h b/drivers/staging/rtl8192e/dot11d.h
index 623075cf0c05..7fa3c4d963c4 100644
--- a/drivers/staging/rtl8192e/dot11d.h
+++ b/drivers/staging/rtl8192e/dot11d.h
@@ -30,8 +30,8 @@ enum dot11d_state {
};
/**
- * struct rt_dot11d_info * @CountryIeLen: value greater than 0 if @CountryIeBuf contains
- * valid country information element.
+ * struct rt_dot11d_info * @CountryIeLen: value greater than 0 if
+ * @CountryIeBuf contains valid country information element.
* @channel_map: holds channel values
* 0 - invalid,
* 1 - valid (active scan),
diff --git a/drivers/staging/rtl8192e/rtl8192e/rtl_core.c b/drivers/staging/rtl8192e/rtl8192e/rtl_core.c
index a4d1bac4a844..aca52654825b 100644
--- a/drivers/staging/rtl8192e/rtl8192e/rtl_core.c
+++ b/drivers/staging/rtl8192e/rtl8192e/rtl_core.c
@@ -2275,131 +2275,6 @@ static int _rtl92e_set_mac_adr(struct net_device *dev, void *mac)
return 0;
}
-/* based on ipw2200 driver */
-static int _rtl92e_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
-{
- struct r8192_priv *priv = rtllib_priv(dev);
- struct iwreq *wrq = (struct iwreq *)rq;
- int ret = -1;
- struct rtllib_device *ieee = priv->rtllib;
- u32 key[4];
- const u8 broadcast_addr[ETH_ALEN] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
- struct iw_point *p = &wrq->u.data;
- struct ieee_param *ipw = NULL;
-
- mutex_lock(&priv->wx_mutex);
-
- switch (cmd) {
- case RTL_IOCTL_WPA_SUPPLICANT:
- if (p->length < sizeof(struct ieee_param) || !p->pointer) {
- ret = -EINVAL;
- goto out;
- }
-
- ipw = memdup_user(p->pointer, p->length);
- if (IS_ERR(ipw)) {
- ret = PTR_ERR(ipw);
- goto out;
- }
-
- if (ipw->cmd == IEEE_CMD_SET_ENCRYPTION) {
- if (ipw->u.crypt.set_tx) {
- if (strcmp(ipw->u.crypt.alg, "CCMP") == 0)
- ieee->pairwise_key_type = KEY_TYPE_CCMP;
- else if (strcmp(ipw->u.crypt.alg, "TKIP") == 0)
- ieee->pairwise_key_type = KEY_TYPE_TKIP;
- else if (strcmp(ipw->u.crypt.alg, "WEP") == 0) {
- if (ipw->u.crypt.key_len == 13)
- ieee->pairwise_key_type =
- KEY_TYPE_WEP104;
- else if (ipw->u.crypt.key_len == 5)
- ieee->pairwise_key_type =
- KEY_TYPE_WEP40;
- } else {
- ieee->pairwise_key_type = KEY_TYPE_NA;
- }
-
- if (ieee->pairwise_key_type) {
- if (is_zero_ether_addr(ieee->ap_mac_addr))
- ieee->iw_mode = IW_MODE_ADHOC;
- memcpy((u8 *)key, ipw->u.crypt.key, 16);
- rtl92e_enable_hw_security_config(dev);
- rtl92e_set_swcam(dev, 4,
- ipw->u.crypt.idx,
- ieee->pairwise_key_type,
- (u8 *)ieee->ap_mac_addr,
- 0, key, 0);
- rtl92e_set_key(dev, 4, ipw->u.crypt.idx,
- ieee->pairwise_key_type,
- (u8 *)ieee->ap_mac_addr,
- 0, key);
- if (ieee->iw_mode == IW_MODE_ADHOC) {
- rtl92e_set_swcam(dev,
- ipw->u.crypt.idx,
- ipw->u.crypt.idx,
- ieee->pairwise_key_type,
- (u8 *)ieee->ap_mac_addr,
- 0, key, 0);
- rtl92e_set_key(dev,
- ipw->u.crypt.idx,
- ipw->u.crypt.idx,
- ieee->pairwise_key_type,
- (u8 *)ieee->ap_mac_addr,
- 0, key);
- }
- }
- if ((ieee->pairwise_key_type ==
- KEY_TYPE_CCMP) &&
- ieee->pHTInfo->bCurrentHTSupport) {
- rtl92e_writeb(dev, 0x173, 1);
- }
-
- } else {
- memcpy((u8 *)key, ipw->u.crypt.key, 16);
- if (strcmp(ipw->u.crypt.alg, "CCMP") == 0)
- ieee->group_key_type = KEY_TYPE_CCMP;
- else if (strcmp(ipw->u.crypt.alg, "TKIP") == 0)
- ieee->group_key_type = KEY_TYPE_TKIP;
- else if (strcmp(ipw->u.crypt.alg, "WEP") == 0) {
- if (ipw->u.crypt.key_len == 13)
- ieee->group_key_type =
- KEY_TYPE_WEP104;
- else if (ipw->u.crypt.key_len == 5)
- ieee->group_key_type =
- KEY_TYPE_WEP40;
- } else
- ieee->group_key_type = KEY_TYPE_NA;
-
- if (ieee->group_key_type) {
- rtl92e_set_swcam(dev, ipw->u.crypt.idx,
- ipw->u.crypt.idx,
- ieee->group_key_type,
- broadcast_addr, 0, key,
- 0);
- rtl92e_set_key(dev, ipw->u.crypt.idx,
- ipw->u.crypt.idx,
- ieee->group_key_type,
- broadcast_addr, 0, key);
- }
- }
- }
-
- ret = rtllib_wpa_supplicant_ioctl(priv->rtllib, &wrq->u.data,
- 0);
- kfree(ipw);
- break;
- default:
- ret = -EOPNOTSUPP;
- break;
- }
-
-out:
- mutex_unlock(&priv->wx_mutex);
-
- return ret;
-}
-
-
static irqreturn_t _rtl92e_irq(int irq, void *netdev)
{
struct net_device *dev = netdev;
@@ -2542,7 +2417,6 @@ static const struct net_device_ops rtl8192_netdev_ops = {
.ndo_open = _rtl92e_open,
.ndo_stop = _rtl92e_close,
.ndo_tx_timeout = _rtl92e_tx_timeout,
- .ndo_do_ioctl = _rtl92e_ioctl,
.ndo_set_rx_mode = _rtl92e_set_multicast,
.ndo_set_mac_address = _rtl92e_set_mac_adr,
.ndo_validate_addr = eth_validate_addr,
diff --git a/drivers/staging/rtl8192e/rtl8192e/rtl_core.h b/drivers/staging/rtl8192e/rtl8192e/rtl_core.h
index 0335823e2766..9d3089cb6a5a 100644
--- a/drivers/staging/rtl8192e/rtl8192e/rtl_core.h
+++ b/drivers/staging/rtl8192e/rtl8192e/rtl_core.h
@@ -102,8 +102,6 @@
#define PHY_RSSI_SLID_WIN_MAX 100
-#define RTL_IOCTL_WPA_SUPPLICANT (SIOCIWFIRSTPRIV + 30)
-
#define TxBBGainTableLength 37
#define CCKTxBBGainTableLength 23
diff --git a/drivers/staging/rtl8192e/rtl8192e/rtl_dm.c b/drivers/staging/rtl8192e/rtl8192e/rtl_dm.c
index 1a43c684f9f3..b8205ebafd72 100644
--- a/drivers/staging/rtl8192e/rtl8192e/rtl_dm.c
+++ b/drivers/staging/rtl8192e/rtl8192e/rtl_dm.c
@@ -1693,22 +1693,6 @@ static void _rtl92e_dm_check_edca_turbo(struct net_device *dev)
if (priv->rtllib->pHTInfo->IOTAction & HT_IOT_ACT_DISABLE_EDCA_TURBO)
goto dm_CheckEdcaTurbo_EXIT;
- {
- u8 *peername[11] = {
- "unknown", "realtek_90", "realtek_92se", "broadcom",
- "ralink", "atheros", "cisco", "marvell", "92u_softap",
- "self_softap"
- };
- static int wb_tmp;
-
- if (wb_tmp == 0) {
- netdev_info(dev,
- "%s():iot peer is %s, bssid: %pM\n",
- __func__, peername[pHTInfo->IOTPeer],
- priv->rtllib->current_network.bssid);
- wb_tmp = 1;
- }
- }
if (!priv->rtllib->bis_any_nonbepkts) {
curTxOkCnt = priv->stats.txbytesunicast - lastTxOkCnt;
curRxOkCnt = priv->stats.rxbytesunicast - lastRxOkCnt;
diff --git a/drivers/staging/rtl8192e/rtl819x_HTProc.c b/drivers/staging/rtl8192e/rtl819x_HTProc.c
index 4ae1d382ac5c..f0e11726a72a 100644
--- a/drivers/staging/rtl8192e/rtl819x_HTProc.c
+++ b/drivers/staging/rtl8192e/rtl819x_HTProc.c
@@ -908,8 +908,8 @@ void HTSetConnectBwMode(struct rtllib_device *ieee,
pHTInfo->CurSTAExtChnlOffset = HT_EXTCHNL_OFFSET_NO_EXT;
}
- pr_info("%s():pHTInfo->bCurBW40MHz:%x\n", __func__,
- pHTInfo->bCurBW40MHz);
+ netdev_dbg(ieee->dev, "%s():pHTInfo->bCurBW40MHz:%x\n", __func__,
+ pHTInfo->bCurBW40MHz);
pHTInfo->bSwBwInProgress = true;
diff --git a/drivers/staging/rtl8192e/rtllib.h b/drivers/staging/rtl8192e/rtllib.h
index 827651b62791..0042a0f6cf79 100644
--- a/drivers/staging/rtl8192e/rtllib.h
+++ b/drivers/staging/rtl8192e/rtllib.h
@@ -335,60 +335,8 @@ enum rt_op_mode {
#define MGMT_QUEUE_NUM 5
-#define IEEE_CMD_SET_WPA_PARAM 1
-#define IEEE_CMD_SET_WPA_IE 2
-#define IEEE_CMD_SET_ENCRYPTION 3
-#define IEEE_CMD_MLME 4
-
-#define IEEE_PARAM_WPA_ENABLED 1
-#define IEEE_PARAM_TKIP_COUNTERMEASURES 2
-#define IEEE_PARAM_DROP_UNENCRYPTED 3
-#define IEEE_PARAM_PRIVACY_INVOKED 4
-#define IEEE_PARAM_AUTH_ALGS 5
-#define IEEE_PARAM_IEEE_802_1X 6
-#define IEEE_PARAM_WPAX_SELECT 7
-
-#define IEEE_MLME_STA_DEAUTH 1
-#define IEEE_MLME_STA_DISASSOC 2
-
-
-#define IEEE_CRYPT_ERR_UNKNOWN_ALG 2
-#define IEEE_CRYPT_ERR_CRYPT_INIT_FAILED 4
-#define IEEE_CRYPT_ERR_KEY_SET_FAILED 5
-#define IEEE_CRYPT_ERR_CARD_CONF_FAILED 7
-#define IEEE_CRYPT_ALG_NAME_LEN 16
-
#define MAX_IE_LEN 0xff
-struct ieee_param {
- u32 cmd;
- u8 sta_addr[ETH_ALEN];
- union {
- struct {
- u8 name;
- u32 value;
- } wpa_param;
- struct {
- u32 len;
- u8 reserved[32];
- u8 data[0];
- } wpa_ie;
- struct {
- int command;
- int reason_code;
- } mlme;
- struct {
- u8 alg[IEEE_CRYPT_ALG_NAME_LEN];
- u8 set_tx;
- u32 err;
- u8 idx;
- u8 seq[8]; /* sequence counter (set: RX, get: TX) */
- u16 key_len;
- u8 key[0];
- } crypt;
- } u;
-};
-
#define msleep_interruptible_rsl msleep_interruptible
/* Maximum size for the MA-UNITDATA primitive, 802.11 standard section
@@ -2066,8 +2014,6 @@ void rtllib_stop_all_queues(struct rtllib_device *ieee);
struct sk_buff *rtllib_get_beacon(struct rtllib_device *ieee);
void rtllib_start_send_beacons(struct rtllib_device *ieee);
void rtllib_stop_send_beacons(struct rtllib_device *ieee);
-int rtllib_wpa_supplicant_ioctl(struct rtllib_device *ieee,
- struct iw_point *p, u8 is_mesh);
void notify_wx_assoc_event(struct rtllib_device *ieee);
void rtllib_ps_tx_ack(struct rtllib_device *ieee, short success);
diff --git a/drivers/staging/rtl8192e/rtllib_rx.c b/drivers/staging/rtl8192e/rtllib_rx.c
index 43a77745e6fb..0033dc6979e7 100644
--- a/drivers/staging/rtl8192e/rtllib_rx.c
+++ b/drivers/staging/rtl8192e/rtllib_rx.c
@@ -1214,9 +1214,6 @@ static int rtllib_rx_decrypt(struct rtllib_device *ieee, struct sk_buff *skb,
return -1;
}
- if (rtllib_is_eapol_frame(ieee, skb, hdrlen))
- netdev_warn(ieee->dev, "RX: IEEE802.1X EAPOL frame!\n");
-
return 0;
}
diff --git a/drivers/staging/rtl8192e/rtllib_softmac.c b/drivers/staging/rtl8192e/rtllib_softmac.c
index eeda17d6409b..64b0034c9c37 100644
--- a/drivers/staging/rtl8192e/rtllib_softmac.c
+++ b/drivers/staging/rtl8192e/rtllib_softmac.c
@@ -1525,7 +1525,8 @@ static void rtllib_associate_complete_wq(void *data)
associate_complete_wq);
struct rt_pwr_save_ctrl *pPSC = &(ieee->PowerSaveControl);
- netdev_info(ieee->dev, "Associated successfully\n");
+ netdev_info(ieee->dev, "Associated successfully with %pM\n",
+ ieee->current_network.bssid);
if (!ieee->is_silent_reset) {
netdev_info(ieee->dev, "normal associate\n");
notify_wx_assoc_event(ieee);
@@ -2309,7 +2310,8 @@ static void rtllib_rx_auth_resp(struct rtllib_device *ieee, struct sk_buff *skb)
if (errcode) {
ieee->softmac_stats.rx_auth_rs_err++;
netdev_info(ieee->dev,
- "Authentication respose status code 0x%x", errcode);
+ "Authentication response status code 0x%x",
+ errcode);
rtllib_associate_abort(ieee);
return;
}
@@ -3076,333 +3078,6 @@ void rtllib_softmac_free(struct rtllib_device *ieee)
tasklet_kill(&ieee->ps_task);
}
-/********************************************************
- * Start of WPA code. *
- * this is stolen from the ipw2200 driver *
- ********************************************************/
-
-
-static int rtllib_wpa_enable(struct rtllib_device *ieee, int value)
-{
- /* This is called when wpa_supplicant loads and closes the driver
- * interface.
- */
- netdev_info(ieee->dev, "%s WPA\n", value ? "enabling" : "disabling");
- ieee->wpa_enabled = value;
- eth_zero_addr(ieee->ap_mac_addr);
- return 0;
-}
-
-
-static void rtllib_wpa_assoc_frame(struct rtllib_device *ieee, char *wpa_ie,
- int wpa_ie_len)
-{
- /* make sure WPA is enabled */
- rtllib_wpa_enable(ieee, 1);
-
- rtllib_disassociate(ieee);
-}
-
-
-static int rtllib_wpa_mlme(struct rtllib_device *ieee, int command, int reason)
-{
-
- int ret = 0;
-
- switch (command) {
- case IEEE_MLME_STA_DEAUTH:
- break;
-
- case IEEE_MLME_STA_DISASSOC:
- rtllib_disassociate(ieee);
- break;
-
- default:
- netdev_info(ieee->dev, "Unknown MLME request: %d\n", command);
- ret = -EOPNOTSUPP;
- }
-
- return ret;
-}
-
-
-static int rtllib_wpa_set_wpa_ie(struct rtllib_device *ieee,
- struct ieee_param *param, int plen)
-{
- u8 *buf;
-
- if (param->u.wpa_ie.len > MAX_WPA_IE_LEN ||
- (param->u.wpa_ie.len && param->u.wpa_ie.data == NULL))
- return -EINVAL;
-
- if (param->u.wpa_ie.len) {
- buf = kmemdup(param->u.wpa_ie.data, param->u.wpa_ie.len,
- GFP_KERNEL);
- if (buf == NULL)
- return -ENOMEM;
-
- kfree(ieee->wpa_ie);
- ieee->wpa_ie = buf;
- ieee->wpa_ie_len = param->u.wpa_ie.len;
- } else {
- kfree(ieee->wpa_ie);
- ieee->wpa_ie = NULL;
- ieee->wpa_ie_len = 0;
- }
-
- rtllib_wpa_assoc_frame(ieee, ieee->wpa_ie, ieee->wpa_ie_len);
- return 0;
-}
-
-#define AUTH_ALG_OPEN_SYSTEM 0x1
-#define AUTH_ALG_SHARED_KEY 0x2
-#define AUTH_ALG_LEAP 0x4
-static int rtllib_wpa_set_auth_algs(struct rtllib_device *ieee, int value)
-{
-
- struct rtllib_security sec = {
- .flags = SEC_AUTH_MODE,
- };
-
- if (value & AUTH_ALG_SHARED_KEY) {
- sec.auth_mode = WLAN_AUTH_SHARED_KEY;
- ieee->open_wep = 0;
- ieee->auth_mode = 1;
- } else if (value & AUTH_ALG_OPEN_SYSTEM) {
- sec.auth_mode = WLAN_AUTH_OPEN;
- ieee->open_wep = 1;
- ieee->auth_mode = 0;
- } else if (value & AUTH_ALG_LEAP) {
- sec.auth_mode = WLAN_AUTH_LEAP >> 6;
- ieee->open_wep = 1;
- ieee->auth_mode = 2;
- }
-
-
- if (ieee->set_security)
- ieee->set_security(ieee->dev, &sec);
-
- return 0;
-}
-
-static int rtllib_wpa_set_param(struct rtllib_device *ieee, u8 name, u32 value)
-{
- int ret = 0;
- unsigned long flags;
-
- switch (name) {
- case IEEE_PARAM_WPA_ENABLED:
- ret = rtllib_wpa_enable(ieee, value);
- break;
-
- case IEEE_PARAM_TKIP_COUNTERMEASURES:
- ieee->tkip_countermeasures = value;
- break;
-
- case IEEE_PARAM_DROP_UNENCRYPTED:
- {
- /* HACK:
- *
- * wpa_supplicant calls set_wpa_enabled when the driver
- * is loaded and unloaded, regardless of if WPA is being
- * used. No other calls are made which can be used to
- * determine if encryption will be used or not prior to
- * association being expected. If encryption is not being
- * used, drop_unencrypted is set to false, else true -- we
- * can use this to determine if the CAP_PRIVACY_ON bit should
- * be set.
- */
- struct rtllib_security sec = {
- .flags = SEC_ENABLED,
- .enabled = value,
- };
- ieee->drop_unencrypted = value;
- /* We only change SEC_LEVEL for open mode. Others
- * are set by ipw_wpa_set_encryption.
- */
- if (!value) {
- sec.flags |= SEC_LEVEL;
- sec.level = SEC_LEVEL_0;
- } else {
- sec.flags |= SEC_LEVEL;
- sec.level = SEC_LEVEL_1;
- }
- if (ieee->set_security)
- ieee->set_security(ieee->dev, &sec);
- break;
- }
-
- case IEEE_PARAM_PRIVACY_INVOKED:
- ieee->privacy_invoked = value;
- break;
-
- case IEEE_PARAM_AUTH_ALGS:
- ret = rtllib_wpa_set_auth_algs(ieee, value);
- break;
-
- case IEEE_PARAM_IEEE_802_1X:
- ieee->ieee802_1x = value;
- break;
- case IEEE_PARAM_WPAX_SELECT:
- spin_lock_irqsave(&ieee->wpax_suitlist_lock, flags);
- spin_unlock_irqrestore(&ieee->wpax_suitlist_lock, flags);
- break;
-
- default:
- netdev_info(ieee->dev, "Unknown WPA param: %d\n", name);
- ret = -EOPNOTSUPP;
- }
-
- return ret;
-}
-
-/* implementation borrowed from hostap driver */
-static int rtllib_wpa_set_encryption(struct rtllib_device *ieee,
- struct ieee_param *param, int param_len,
- u8 is_mesh)
-{
- int ret = 0;
- struct lib80211_crypto_ops *ops;
- struct lib80211_crypt_data **crypt;
-
- struct rtllib_security sec = {
- .flags = 0,
- };
-
- param->u.crypt.err = 0;
- param->u.crypt.alg[IEEE_CRYPT_ALG_NAME_LEN - 1] = '\0';
-
- if (param_len !=
- (int) ((char *) param->u.crypt.key - (char *) param) +
- param->u.crypt.key_len) {
- netdev_info(ieee->dev, "Len mismatch %d, %d\n", param_len,
- param->u.crypt.key_len);
- return -EINVAL;
- }
- if (is_broadcast_ether_addr(param->sta_addr)) {
- if (param->u.crypt.idx >= NUM_WEP_KEYS)
- return -EINVAL;
- crypt = &ieee->crypt_info.crypt[param->u.crypt.idx];
- } else {
- return -EINVAL;
- }
-
- if (strcmp(param->u.crypt.alg, "none") == 0) {
- if (crypt) {
- sec.enabled = 0;
- sec.level = SEC_LEVEL_0;
- sec.flags |= SEC_ENABLED | SEC_LEVEL;
- lib80211_crypt_delayed_deinit(&ieee->crypt_info, crypt);
- }
- goto done;
- }
- sec.enabled = 1;
- sec.flags |= SEC_ENABLED;
-
- /* IPW HW cannot build TKIP MIC, host decryption still needed. */
- if (!(ieee->host_encrypt || ieee->host_decrypt) &&
- strcmp(param->u.crypt.alg, "R-TKIP"))
- goto skip_host_crypt;
-
- ops = lib80211_get_crypto_ops(param->u.crypt.alg);
- if (ops == NULL && strcmp(param->u.crypt.alg, "R-WEP") == 0) {
- request_module("rtllib_crypt_wep");
- ops = lib80211_get_crypto_ops(param->u.crypt.alg);
- } else if (ops == NULL && strcmp(param->u.crypt.alg, "R-TKIP") == 0) {
- request_module("rtllib_crypt_tkip");
- ops = lib80211_get_crypto_ops(param->u.crypt.alg);
- } else if (ops == NULL && strcmp(param->u.crypt.alg, "R-CCMP") == 0) {
- request_module("rtllib_crypt_ccmp");
- ops = lib80211_get_crypto_ops(param->u.crypt.alg);
- }
- if (ops == NULL) {
- netdev_info(ieee->dev, "unknown crypto alg '%s'\n",
- param->u.crypt.alg);
- param->u.crypt.err = IEEE_CRYPT_ERR_UNKNOWN_ALG;
- ret = -EINVAL;
- goto done;
- }
- if (*crypt == NULL || (*crypt)->ops != ops) {
- struct lib80211_crypt_data *new_crypt;
-
- lib80211_crypt_delayed_deinit(&ieee->crypt_info, crypt);
-
- new_crypt = kzalloc(sizeof(*new_crypt), GFP_KERNEL);
- if (new_crypt == NULL) {
- ret = -ENOMEM;
- goto done;
- }
- new_crypt->ops = ops;
- if (new_crypt->ops && try_module_get(new_crypt->ops->owner))
- new_crypt->priv =
- new_crypt->ops->init(param->u.crypt.idx);
-
- if (new_crypt->priv == NULL) {
- kfree(new_crypt);
- param->u.crypt.err = IEEE_CRYPT_ERR_CRYPT_INIT_FAILED;
- ret = -EINVAL;
- goto done;
- }
-
- *crypt = new_crypt;
- }
-
- if (param->u.crypt.key_len > 0 && (*crypt)->ops->set_key &&
- (*crypt)->ops->set_key(param->u.crypt.key,
- param->u.crypt.key_len, param->u.crypt.seq,
- (*crypt)->priv) < 0) {
- netdev_info(ieee->dev, "key setting failed\n");
- param->u.crypt.err = IEEE_CRYPT_ERR_KEY_SET_FAILED;
- ret = -EINVAL;
- goto done;
- }
-
- skip_host_crypt:
- if (param->u.crypt.set_tx) {
- ieee->crypt_info.tx_keyidx = param->u.crypt.idx;
- sec.active_key = param->u.crypt.idx;
- sec.flags |= SEC_ACTIVE_KEY;
- } else
- sec.flags &= ~SEC_ACTIVE_KEY;
-
- memcpy(sec.keys[param->u.crypt.idx],
- param->u.crypt.key,
- param->u.crypt.key_len);
- sec.key_sizes[param->u.crypt.idx] = param->u.crypt.key_len;
- sec.flags |= (1 << param->u.crypt.idx);
-
- if (strcmp(param->u.crypt.alg, "R-WEP") == 0) {
- sec.flags |= SEC_LEVEL;
- sec.level = SEC_LEVEL_1;
- } else if (strcmp(param->u.crypt.alg, "R-TKIP") == 0) {
- sec.flags |= SEC_LEVEL;
- sec.level = SEC_LEVEL_2;
- } else if (strcmp(param->u.crypt.alg, "R-CCMP") == 0) {
- sec.flags |= SEC_LEVEL;
- sec.level = SEC_LEVEL_3;
- }
- done:
- if (ieee->set_security)
- ieee->set_security(ieee->dev, &sec);
-
- /* Do not reset port if card is in Managed mode since resetting will
- * generate new IEEE 802.11 authentication which may end up in looping
- * with IEEE 802.1X. If your hardware requires a reset after WEP
- * configuration (for example... Prism2), implement the reset_port in
- * the callbacks structures used to initialize the 802.11 stack.
- */
- if (ieee->reset_on_keychange &&
- ieee->iw_mode != IW_MODE_INFRA &&
- ieee->reset_port &&
- ieee->reset_port(ieee->dev)) {
- netdev_info(ieee->dev, "reset_port failed\n");
- param->u.crypt.err = IEEE_CRYPT_ERR_CARD_CONF_FAILED;
- return -EINVAL;
- }
-
- return ret;
-}
-
static inline struct sk_buff *
rtllib_disauth_skb(struct rtllib_network *beacon,
struct rtllib_device *ieee, u16 asRsn)
@@ -3501,62 +3176,6 @@ u8 rtllib_ap_sec_type(struct rtllib_device *ieee)
}
}
-int rtllib_wpa_supplicant_ioctl(struct rtllib_device *ieee, struct iw_point *p,
- u8 is_mesh)
-{
- struct ieee_param *param;
- int ret = 0;
-
- mutex_lock(&ieee->wx_mutex);
-
- if (p->length < sizeof(struct ieee_param) || !p->pointer) {
- ret = -EINVAL;
- goto out;
- }
-
- param = memdup_user(p->pointer, p->length);
- if (IS_ERR(param)) {
- ret = PTR_ERR(param);
- goto out;
- }
-
- switch (param->cmd) {
- case IEEE_CMD_SET_WPA_PARAM:
- ret = rtllib_wpa_set_param(ieee, param->u.wpa_param.name,
- param->u.wpa_param.value);
- break;
-
- case IEEE_CMD_SET_WPA_IE:
- ret = rtllib_wpa_set_wpa_ie(ieee, param, p->length);
- break;
-
- case IEEE_CMD_SET_ENCRYPTION:
- ret = rtllib_wpa_set_encryption(ieee, param, p->length, 0);
- break;
-
- case IEEE_CMD_MLME:
- ret = rtllib_wpa_mlme(ieee, param->u.mlme.command,
- param->u.mlme.reason_code);
- break;
-
- default:
- netdev_info(ieee->dev, "Unknown WPA supplicant request: %d\n",
- param->cmd);
- ret = -EOPNOTSUPP;
- break;
- }
-
- if (ret == 0 && copy_to_user(p->pointer, param, p->length))
- ret = -EFAULT;
-
- kfree(param);
-out:
- mutex_unlock(&ieee->wx_mutex);
-
- return ret;
-}
-EXPORT_SYMBOL(rtllib_wpa_supplicant_ioctl);
-
static void rtllib_MgntDisconnectIBSS(struct rtllib_device *rtllib)
{
u8 OpMode;
diff --git a/drivers/staging/rtl8192e/rtllib_wx.c b/drivers/staging/rtl8192e/rtllib_wx.c
index c5c0d9676dc8..f7eba01b5d15 100644
--- a/drivers/staging/rtl8192e/rtllib_wx.c
+++ b/drivers/staging/rtl8192e/rtllib_wx.c
@@ -595,7 +595,7 @@ int rtllib_wx_set_encode_ext(struct rtllib_device *ieee,
ret = -EINVAL;
goto done;
}
- netdev_info(dev, "alg name:%s\n", alg);
+ netdev_dbg(dev, "alg name:%s\n", alg);
ops = lib80211_get_crypto_ops(alg);
if (ops == NULL) {
diff --git a/drivers/staging/rtl8192u/ieee80211/ieee80211.h b/drivers/staging/rtl8192u/ieee80211/ieee80211.h
index 899c77ed2a43..b062cad052b9 100644
--- a/drivers/staging/rtl8192u/ieee80211/ieee80211.h
+++ b/drivers/staging/rtl8192u/ieee80211/ieee80211.h
@@ -2187,7 +2187,7 @@ int ieee80211_encrypt_fragment(struct ieee80211_device *ieee,
struct sk_buff *frag, int hdr_len);
int ieee80211_xmit(struct sk_buff *skb, struct net_device *dev);
-void ieee80211_txb_free(struct ieee80211_txb *);
+void ieee80211_txb_free(struct ieee80211_txb *txb);
/* ieee80211_rx.c */
diff --git a/drivers/staging/rtl8192u/ieee80211/ieee80211_crypt.h b/drivers/staging/rtl8192u/ieee80211/ieee80211_crypt.h
index 005bf89aae65..a0aa0f5be63a 100644
--- a/drivers/staging/rtl8192u/ieee80211/ieee80211_crypt.h
+++ b/drivers/staging/rtl8192u/ieee80211/ieee80211_crypt.h
@@ -82,8 +82,8 @@ struct ieee80211_crypt_data {
int ieee80211_register_crypto_ops(struct ieee80211_crypto_ops *ops);
int ieee80211_unregister_crypto_ops(struct ieee80211_crypto_ops *ops);
struct ieee80211_crypto_ops *ieee80211_get_crypto_ops(const char *name);
-void ieee80211_crypt_deinit_entries(struct ieee80211_device *, int);
-void ieee80211_crypt_deinit_handler(unsigned long);
+void ieee80211_crypt_deinit_entries(struct ieee80211_device *ieee, int force);
+void ieee80211_crypt_deinit_handler(unsigned long data);
void ieee80211_crypt_delayed_deinit(struct ieee80211_device *ieee,
struct ieee80211_crypt_data **crypt);
diff --git a/drivers/staging/rtl8192u/ieee80211/ieee80211_crypt_tkip.c b/drivers/staging/rtl8192u/ieee80211/ieee80211_crypt_tkip.c
index 5039172409e3..60ecfec71112 100644
--- a/drivers/staging/rtl8192u/ieee80211/ieee80211_crypt_tkip.c
+++ b/drivers/staging/rtl8192u/ieee80211/ieee80211_crypt_tkip.c
@@ -171,13 +171,6 @@ static inline u16 Mk16(u8 hi, u8 lo)
return lo | (((u16) hi) << 8);
}
-
-static inline u16 Mk16_le(u16 *v)
-{
- return le16_to_cpu(*v);
-}
-
-
static const u16 Sbox[256] = {
0xC6A5, 0xF884, 0xEE99, 0xF68D, 0xFF0D, 0xD6BD, 0xDEB1, 0x9154,
0x6050, 0x0203, 0xCEA9, 0x567D, 0xE719, 0xB562, 0x4DE6, 0xEC9A,
@@ -264,15 +257,15 @@ static void tkip_mixing_phase2(u8 *WEPSeed, const u8 *TK, const u16 *TTAK,
PPK[5] = TTAK[4] + IV16;
/* Step 2 - 96-bit bijective mixing using S-box */
- PPK[0] += _S_(PPK[5] ^ Mk16_le((u16 *) &TK[0]));
- PPK[1] += _S_(PPK[0] ^ Mk16_le((u16 *) &TK[2]));
- PPK[2] += _S_(PPK[1] ^ Mk16_le((u16 *) &TK[4]));
- PPK[3] += _S_(PPK[2] ^ Mk16_le((u16 *) &TK[6]));
- PPK[4] += _S_(PPK[3] ^ Mk16_le((u16 *) &TK[8]));
- PPK[5] += _S_(PPK[4] ^ Mk16_le((u16 *) &TK[10]));
-
- PPK[0] += RotR1(PPK[5] ^ Mk16_le((u16 *) &TK[12]));
- PPK[1] += RotR1(PPK[0] ^ Mk16_le((u16 *) &TK[14]));
+ PPK[0] += _S_(PPK[5] ^ le16_to_cpu(*(__le16 *)(&TK[0])));
+ PPK[1] += _S_(PPK[0] ^ le16_to_cpu(*(__le16 *)(&TK[2])));
+ PPK[2] += _S_(PPK[1] ^ le16_to_cpu(*(__le16 *)(&TK[4])));
+ PPK[3] += _S_(PPK[2] ^ le16_to_cpu(*(__le16 *)(&TK[6])));
+ PPK[4] += _S_(PPK[3] ^ le16_to_cpu(*(__le16 *)(&TK[8])));
+ PPK[5] += _S_(PPK[4] ^ le16_to_cpu(*(__le16 *)(&TK[10])));
+
+ PPK[0] += RotR1(PPK[5] ^ le16_to_cpu(*(__le16 *)(&TK[12])));
+ PPK[1] += RotR1(PPK[0] ^ le16_to_cpu(*(__le16 *)(&TK[14])));
PPK[2] += RotR1(PPK[1]);
PPK[3] += RotR1(PPK[2]);
PPK[4] += RotR1(PPK[3]);
@@ -285,7 +278,7 @@ static void tkip_mixing_phase2(u8 *WEPSeed, const u8 *TK, const u16 *TTAK,
WEPSeed[0] = Hi8(IV16);
WEPSeed[1] = (Hi8(IV16) | 0x20) & 0x7F;
WEPSeed[2] = Lo8(IV16);
- WEPSeed[3] = Lo8((PPK[5] ^ Mk16_le((u16 *) &TK[0])) >> 1);
+ WEPSeed[3] = Lo8((PPK[5] ^ le16_to_cpu(*(__le16 *)(&TK[0]))) >> 1);
#ifdef __BIG_ENDIAN
{
diff --git a/drivers/staging/rtl8192u/ieee80211/ieee80211_module.c b/drivers/staging/rtl8192u/ieee80211/ieee80211_module.c
index a791175b86f5..8f236b332a47 100644
--- a/drivers/staging/rtl8192u/ieee80211/ieee80211_module.c
+++ b/drivers/staging/rtl8192u/ieee80211/ieee80211_module.c
@@ -157,8 +157,7 @@ struct net_device *alloc_ieee80211(int sizeof_priv)
ieee80211_softmac_init(ieee);
ieee->pHTInfo = kzalloc(sizeof(RT_HIGH_THROUGHPUT), GFP_KERNEL);
- if (ieee->pHTInfo == NULL)
- {
+ if (ieee->pHTInfo == NULL) {
IEEE80211_DEBUG(IEEE80211_DL_ERR, "can't alloc memory for HTInfo\n");
goto failed;
}
diff --git a/drivers/staging/rtl8192u/ieee80211/rtl819x_TSProc.c b/drivers/staging/rtl8192u/ieee80211/rtl819x_TSProc.c
index b4c13fff2c65..f98bb03aa293 100644
--- a/drivers/staging/rtl8192u/ieee80211/rtl819x_TSProc.c
+++ b/drivers/staging/rtl8192u/ieee80211/rtl819x_TSProc.c
@@ -36,18 +36,15 @@ static void RxPktPendingTimeout(unsigned long data)
spin_lock_irqsave(&(ieee->reorder_spinlock), flags);
IEEE80211_DEBUG(IEEE80211_DL_REORDER,"==================>%s()\n",__func__);
- if(pRxTs->RxTimeoutIndicateSeq != 0xffff)
- {
+ if(pRxTs->RxTimeoutIndicateSeq != 0xffff) {
// Indicate the pending packets sequentially according to SeqNum until meet the gap.
- while(!list_empty(&pRxTs->RxPendingPktList))
- {
+ while(!list_empty(&pRxTs->RxPendingPktList)) {
pReorderEntry = (PRX_REORDER_ENTRY)list_entry(pRxTs->RxPendingPktList.prev,RX_REORDER_ENTRY,List);
if(index == 0)
pRxTs->RxIndicateSeq = pReorderEntry->SeqNum;
if( SN_LESS(pReorderEntry->SeqNum, pRxTs->RxIndicateSeq) ||
- SN_EQUAL(pReorderEntry->SeqNum, pRxTs->RxIndicateSeq) )
- {
+ SN_EQUAL(pReorderEntry->SeqNum, pRxTs->RxIndicateSeq) ) {
list_del_init(&pReorderEntry->List);
if(SN_EQUAL(pReorderEntry->SeqNum, pRxTs->RxIndicateSeq))
@@ -58,22 +55,19 @@ static void RxPktPendingTimeout(unsigned long data)
index++;
list_add_tail(&pReorderEntry->List, &ieee->RxReorder_Unused_List);
- }
- else
- {
+ } else {
bPktInBuf = true;
break;
}
}
}
- if(index>0)
- {
+ if(index>0) {
// Set RxTimeoutIndicateSeq to 0xffff to indicate no pending packets in buffer now.
pRxTs->RxTimeoutIndicateSeq = 0xffff;
// Indicate packets
- if(index > REORDER_WIN_SIZE){
+ if(index > REORDER_WIN_SIZE) {
IEEE80211_DEBUG(IEEE80211_DL_ERR, "RxReorderIndicatePacket(): Rx Reorder buffer full!! \n");
spin_unlock_irqrestore(&(ieee->reorder_spinlock), flags);
return;
@@ -81,8 +75,7 @@ static void RxPktPendingTimeout(unsigned long data)
ieee80211_indicate_packets(ieee, ieee->stats_IndicateArray, index);
}
- if(bPktInBuf && (pRxTs->RxTimeoutIndicateSeq==0xffff))
- {
+ if(bPktInBuf && (pRxTs->RxTimeoutIndicateSeq==0xffff)) {
pRxTs->RxTimeoutIndicateSeq = pRxTs->RxIndicateSeq;
mod_timer(&pRxTs->RxPktPendingTimer,
jiffies + msecs_to_jiffies(ieee->pHTInfo->RxReorderPendingTime));
@@ -147,8 +140,7 @@ void TSInitialize(struct ieee80211_device *ieee)
INIT_LIST_HEAD(&ieee->Tx_TS_Pending_List);
INIT_LIST_HEAD(&ieee->Tx_TS_Unused_List);
- for(count = 0; count < TOTAL_TS_NUM; count++)
- {
+ for(count = 0; count < TOTAL_TS_NUM; count++) {
//
pTxTS->num = count;
// The timers for the operation of Traffic Stream and Block Ack.
@@ -172,8 +164,7 @@ void TSInitialize(struct ieee80211_device *ieee)
INIT_LIST_HEAD(&ieee->Rx_TS_Admit_List);
INIT_LIST_HEAD(&ieee->Rx_TS_Pending_List);
INIT_LIST_HEAD(&ieee->Rx_TS_Unused_List);
- for(count = 0; count < TOTAL_TS_NUM; count++)
- {
+ for(count = 0; count < TOTAL_TS_NUM; count++) {
pRxTS->num = count;
INIT_LIST_HEAD(&pRxTS->RxPendingPktList);
setup_timer(&pRxTS->TsCommonInfo.SetupTimer, TsSetupTimeOut,
@@ -191,15 +182,13 @@ void TSInitialize(struct ieee80211_device *ieee)
// Initialize unused Rx Reorder List.
INIT_LIST_HEAD(&ieee->RxReorder_Unused_List);
//#ifdef TO_DO_LIST
- for(count = 0; count < REORDER_ENTRY_NUM; count++)
- {
+ for(count = 0; count < REORDER_ENTRY_NUM; count++) {
list_add_tail( &pRxReorderEntry->List,&ieee->RxReorder_Unused_List);
if(count == (REORDER_ENTRY_NUM-1))
break;
pRxReorderEntry = &ieee->RxReorderEntry[count+1];
}
//#endif
-
}
static void AdmitTS(struct ieee80211_device *ieee,
@@ -223,36 +212,25 @@ static PTS_COMMON_INFO SearchAdmitTRStream(struct ieee80211_device *ieee,
bool search_dir[4] = {0};
struct list_head *psearch_list; //FIXME
PTS_COMMON_INFO pRet = NULL;
- if(ieee->iw_mode == IW_MODE_MASTER) //ap mode
- {
- if(TxRxSelect == TX_DIR)
- {
+ if(ieee->iw_mode == IW_MODE_MASTER) { //ap mode
+ if(TxRxSelect == TX_DIR) {
search_dir[DIR_DOWN] = true;
search_dir[DIR_BI_DIR]= true;
- }
- else
- {
+ } else {
search_dir[DIR_UP] = true;
search_dir[DIR_BI_DIR]= true;
}
- }
- else if(ieee->iw_mode == IW_MODE_ADHOC)
- {
+ } else if(ieee->iw_mode == IW_MODE_ADHOC) {
if(TxRxSelect == TX_DIR)
search_dir[DIR_UP] = true;
else
search_dir[DIR_DOWN] = true;
- }
- else
- {
- if(TxRxSelect == TX_DIR)
- {
+ } else {
+ if(TxRxSelect == TX_DIR) {
search_dir[DIR_UP] = true;
search_dir[DIR_BI_DIR]= true;
search_dir[DIR_DIRECT]= true;
- }
- else
- {
+ } else {
search_dir[DIR_DOWN] = true;
search_dir[DIR_BI_DIR]= true;
search_dir[DIR_DIRECT]= true;
@@ -265,28 +243,24 @@ static PTS_COMMON_INFO SearchAdmitTRStream(struct ieee80211_device *ieee,
psearch_list = &ieee->Rx_TS_Admit_List;
//for(dir = DIR_UP; dir <= DIR_BI_DIR; dir++)
- for(dir = 0; dir <= DIR_BI_DIR; dir++)
- {
+ for(dir = 0; dir <= DIR_BI_DIR; dir++) {
if (!search_dir[dir])
continue;
list_for_each_entry(pRet, psearch_list, List){
// IEEE80211_DEBUG(IEEE80211_DL_TS, "ADD:%pM, TID:%d, dir:%d\n", pRet->Addr, pRet->TSpec.f.TSInfo.field.ucTSID, pRet->TSpec.f.TSInfo.field.ucDirection);
if (memcmp(pRet->Addr, Addr, 6) == 0)
if (pRet->TSpec.f.TSInfo.field.ucTSID == TID)
- if(pRet->TSpec.f.TSInfo.field.ucDirection == dir)
- {
+ if(pRet->TSpec.f.TSInfo.field.ucDirection == dir) {
// printk("Bingo! got it\n");
break;
}
-
}
if(&pRet->List != psearch_list)
break;
}
- if(&pRet->List != psearch_list){
+ if(&pRet->List != psearch_list)
return pRet ;
- }
else
return NULL;
}
@@ -327,25 +301,21 @@ bool GetTs(
// We do not build any TS for Broadcast or Multicast stream.
// So reject these kinds of search here.
//
- if (is_multicast_ether_addr(Addr))
- {
+ if (is_multicast_ether_addr(Addr)) {
IEEE80211_DEBUG(IEEE80211_DL_ERR, "get TS for Broadcast or Multicast\n");
return false;
}
- if (ieee->current_network.qos_data.supported == 0)
+ if (ieee->current_network.qos_data.supported == 0) {
UP = 0;
- else
- {
+ } else {
// In WMM case: we use 4 TID only
- if (!IsACValid(TID))
- {
+ if (!IsACValid(TID)) {
IEEE80211_DEBUG(IEEE80211_DL_ERR, " in %s(), TID(%d) is not valid\n", __func__, TID);
return false;
}
- switch (TID)
- {
+ switch (TID) {
case 0:
case 3:
UP = 0;
@@ -373,18 +343,13 @@ bool GetTs(
Addr,
UP,
TxRxSelect);
- if(*ppTS != NULL)
- {
+ if(*ppTS != NULL) {
return true;
- }
- else
- {
+ } else {
if (!bAddNewTs) {
IEEE80211_DEBUG(IEEE80211_DL_TS, "add new TS failed(tid:%d)\n", UP);
return false;
- }
- else
- {
+ } else {
//
// Create a new Traffic stream for current Tx/Rx
// This is for EDCA and WMM to add a new TS.
@@ -406,16 +371,13 @@ bool GetTs(
((TxRxSelect==TX_DIR)?DIR_DOWN:DIR_UP):
((TxRxSelect==TX_DIR)?DIR_UP:DIR_DOWN);
IEEE80211_DEBUG(IEEE80211_DL_TS, "to add Ts\n");
- if(!list_empty(pUnusedList))
- {
+ if(!list_empty(pUnusedList)) {
(*ppTS) = list_entry(pUnusedList->next, TS_COMMON_INFO, List);
list_del_init(&(*ppTS)->List);
- if(TxRxSelect==TX_DIR)
- {
+ if(TxRxSelect==TX_DIR) {
PTX_TS_RECORD tmp = container_of(*ppTS, TX_TS_RECORD, TsCommonInfo);
ResetTxTsEntry(tmp);
- }
- else{
+ } else {
PRX_TS_RECORD tmp = container_of(*ppTS, RX_TS_RECORD, TsCommonInfo);
ResetRxTsEntry(tmp);
}
@@ -438,9 +400,7 @@ bool GetTs(
// if there is DirectLink, we need to do additional operation here!!
return true;
- }
- else
- {
+ } else {
IEEE80211_DEBUG(IEEE80211_DL_ERR, "in function %s() There is not enough TS record to be used!!", __func__);
return false;
}
@@ -457,16 +417,14 @@ static void RemoveTsEntry(struct ieee80211_device *ieee, PTS_COMMON_INFO pTs,
del_timer_sync(&pTs->InactTimer);
TsInitDelBA(ieee, pTs, TxRxSelect);
- if(TxRxSelect == RX_DIR)
- {
+ if(TxRxSelect == RX_DIR) {
//#ifdef TO_DO_LIST
PRX_REORDER_ENTRY pRxReorderEntry;
PRX_TS_RECORD pRxTS = (PRX_TS_RECORD)pTs;
if(timer_pending(&pRxTS->RxPktPendingTimer))
del_timer_sync(&pRxTS->RxPktPendingTimer);
- while(!list_empty(&pRxTS->RxPendingPktList))
- {
+ while(!list_empty(&pRxTS->RxPendingPktList)) {
spin_lock_irqsave(&(ieee->reorder_spinlock), flags);
//pRxReorderEntry = list_entry(&pRxTS->RxPendingPktList.prev,RX_REORDER_ENTRY,List);
pRxReorderEntry = (PRX_REORDER_ENTRY)list_entry(pRxTS->RxPendingPktList.prev,RX_REORDER_ENTRY,List);
@@ -474,14 +432,13 @@ static void RemoveTsEntry(struct ieee80211_device *ieee, PTS_COMMON_INFO pTs,
{
int i = 0;
struct ieee80211_rxb *prxb = pRxReorderEntry->prxb;
- if (unlikely(!prxb))
- {
+ if (unlikely(!prxb)) {
spin_unlock_irqrestore(&(ieee->reorder_spinlock), flags);
return;
}
- for(i =0; i < prxb->nr_subframes; i++) {
+ for(i =0; i < prxb->nr_subframes; i++)
dev_kfree_skb(prxb->subframes[i]);
- }
+
kfree(prxb);
prxb = NULL;
}
@@ -490,9 +447,7 @@ static void RemoveTsEntry(struct ieee80211_device *ieee, PTS_COMMON_INFO pTs,
}
//#endif
- }
- else
- {
+ } else {
PTX_TS_RECORD pTxTS = (PTX_TS_RECORD)pTs;
del_timer_sync(&pTxTS->TsAddBaTimer);
}
@@ -503,20 +458,16 @@ void RemovePeerTS(struct ieee80211_device *ieee, u8 *Addr)
PTS_COMMON_INFO pTS, pTmpTS;
printk("===========>RemovePeerTS,%pM\n", Addr);
- list_for_each_entry_safe(pTS, pTmpTS, &ieee->Tx_TS_Pending_List, List)
- {
- if (memcmp(pTS->Addr, Addr, 6) == 0)
- {
+ list_for_each_entry_safe(pTS, pTmpTS, &ieee->Tx_TS_Pending_List, List) {
+ if (memcmp(pTS->Addr, Addr, 6) == 0) {
RemoveTsEntry(ieee, pTS, TX_DIR);
list_del_init(&pTS->List);
list_add_tail(&pTS->List, &ieee->Tx_TS_Unused_List);
}
}
- list_for_each_entry_safe(pTS, pTmpTS, &ieee->Tx_TS_Admit_List, List)
- {
- if (memcmp(pTS->Addr, Addr, 6) == 0)
- {
+ list_for_each_entry_safe(pTS, pTmpTS, &ieee->Tx_TS_Admit_List, List) {
+ if (memcmp(pTS->Addr, Addr, 6) == 0) {
printk("====>remove Tx_TS_admin_list\n");
RemoveTsEntry(ieee, pTS, TX_DIR);
list_del_init(&pTS->List);
@@ -524,20 +475,16 @@ void RemovePeerTS(struct ieee80211_device *ieee, u8 *Addr)
}
}
- list_for_each_entry_safe(pTS, pTmpTS, &ieee->Rx_TS_Pending_List, List)
- {
- if (memcmp(pTS->Addr, Addr, 6) == 0)
- {
+ list_for_each_entry_safe(pTS, pTmpTS, &ieee->Rx_TS_Pending_List, List) {
+ if (memcmp(pTS->Addr, Addr, 6) == 0) {
RemoveTsEntry(ieee, pTS, RX_DIR);
list_del_init(&pTS->List);
list_add_tail(&pTS->List, &ieee->Rx_TS_Unused_List);
}
}
- list_for_each_entry_safe(pTS, pTmpTS, &ieee->Rx_TS_Admit_List, List)
- {
- if (memcmp(pTS->Addr, Addr, 6) == 0)
- {
+ list_for_each_entry_safe(pTS, pTmpTS, &ieee->Rx_TS_Admit_List, List) {
+ if (memcmp(pTS->Addr, Addr, 6) == 0) {
RemoveTsEntry(ieee, pTS, RX_DIR);
list_del_init(&pTS->List);
list_add_tail(&pTS->List, &ieee->Rx_TS_Unused_List);
@@ -549,29 +496,25 @@ void RemoveAllTS(struct ieee80211_device *ieee)
{
PTS_COMMON_INFO pTS, pTmpTS;
- list_for_each_entry_safe(pTS, pTmpTS, &ieee->Tx_TS_Pending_List, List)
- {
+ list_for_each_entry_safe(pTS, pTmpTS, &ieee->Tx_TS_Pending_List, List) {
RemoveTsEntry(ieee, pTS, TX_DIR);
list_del_init(&pTS->List);
list_add_tail(&pTS->List, &ieee->Tx_TS_Unused_List);
}
- list_for_each_entry_safe(pTS, pTmpTS, &ieee->Tx_TS_Admit_List, List)
- {
+ list_for_each_entry_safe(pTS, pTmpTS, &ieee->Tx_TS_Admit_List, List) {
RemoveTsEntry(ieee, pTS, TX_DIR);
list_del_init(&pTS->List);
list_add_tail(&pTS->List, &ieee->Tx_TS_Unused_List);
}
- list_for_each_entry_safe(pTS, pTmpTS, &ieee->Rx_TS_Pending_List, List)
- {
+ list_for_each_entry_safe(pTS, pTmpTS, &ieee->Rx_TS_Pending_List, List) {
RemoveTsEntry(ieee, pTS, RX_DIR);
list_del_init(&pTS->List);
list_add_tail(&pTS->List, &ieee->Rx_TS_Unused_List);
}
- list_for_each_entry_safe(pTS, pTmpTS, &ieee->Rx_TS_Admit_List, List)
- {
+ list_for_each_entry_safe(pTS, pTmpTS, &ieee->Rx_TS_Admit_List, List) {
RemoveTsEntry(ieee, pTS, RX_DIR);
list_del_init(&pTS->List);
list_add_tail(&pTS->List, &ieee->Rx_TS_Unused_List);
@@ -580,21 +523,17 @@ void RemoveAllTS(struct ieee80211_device *ieee)
void TsStartAddBaProcess(struct ieee80211_device *ieee, PTX_TS_RECORD pTxTS)
{
- if(!pTxTS->bAddBaReqInProgress)
- {
+ if(!pTxTS->bAddBaReqInProgress) {
pTxTS->bAddBaReqInProgress = true;
- if(pTxTS->bAddBaReqDelayed)
- {
+ if(pTxTS->bAddBaReqDelayed) {
IEEE80211_DEBUG(IEEE80211_DL_BA, "TsStartAddBaProcess(): Delayed Start ADDBA after 60 sec!!\n");
mod_timer(&pTxTS->TsAddBaTimer,
jiffies + msecs_to_jiffies(TS_ADDBA_DELAY));
- }
- else
- {
+ } else {
IEEE80211_DEBUG(IEEE80211_DL_BA,"TsStartAddBaProcess(): Immediately Start ADDBA now!!\n");
mod_timer(&pTxTS->TsAddBaTimer, jiffies+10); //set 10 ticks
}
- }
- else
+ } else {
IEEE80211_DEBUG(IEEE80211_DL_ERR, "%s()==>BA timer is already added\n", __func__);
+ }
}
diff --git a/drivers/staging/rtl8192u/r8192U.h b/drivers/staging/rtl8192u/r8192U.h
index e702afb5a70e..51c150a39fc2 100644
--- a/drivers/staging/rtl8192u/r8192U.h
+++ b/drivers/staging/rtl8192u/r8192U.h
@@ -34,7 +34,7 @@
#include <linux/proc_fs.h>
#include <linux/if_arp.h>
#include <linux/random.h>
-#include <asm/io.h>
+#include <linux/io.h>
#include "ieee80211/ieee80211.h"
#define RTL8192U
@@ -1147,9 +1147,9 @@ int write_nic_word(struct net_device *dev, int x, u16 y);
int write_nic_dword(struct net_device *dev, int x, u32 y);
void force_pci_posting(struct net_device *dev);
-void rtl8192_rtx_disable(struct net_device *);
-void rtl8192_rx_enable(struct net_device *);
-void rtl8192_tx_enable(struct net_device *);
+void rtl8192_rtx_disable(struct net_device *dev);
+void rtl8192_rx_enable(struct net_device *dev);
+void rtl8192_tx_enable(struct net_device *dev);
void rtl8192_disassociate(struct net_device *dev);
void rtl8185_set_rf_pins_enable(struct net_device *dev, u32 a);
diff --git a/drivers/staging/rtl8192u/r8192U_core.c b/drivers/staging/rtl8192u/r8192U_core.c
index 9f370e8d84d3..779ecdbc4e17 100644
--- a/drivers/staging/rtl8192u/r8192U_core.c
+++ b/drivers/staging/rtl8192u/r8192U_core.c
@@ -1797,8 +1797,8 @@ static void rtl8192_link_change(struct net_device *dev)
* way, but there is no chance to set this as wep will not set
* group key in wext.
*/
- if (KEY_TYPE_WEP40 == ieee->pairwise_key_type ||
- KEY_TYPE_WEP104 == ieee->pairwise_key_type)
+ if (ieee->pairwise_key_type == KEY_TYPE_WEP40 ||
+ ieee->pairwise_key_type == KEY_TYPE_WEP104)
EnableHWSecurityConfig8192(dev);
}
/*update timing params*/
@@ -2071,7 +2071,7 @@ static bool GetNmodeSupportBySecCfg8192(struct net_device *dev)
*/
encrypt = (network->capability & WLAN_CAPABILITY_PRIVACY) ||
(ieee->host_encrypt && crypt && crypt->ops &&
- (0 == strcmp(crypt->ops->name, "WEP")));
+ (strcmp(crypt->ops->name, "WEP") == 0));
/* simply judge */
if (encrypt && (wpa_ie_len == 0)) {
@@ -4498,7 +4498,7 @@ static void TranslateRxSignalStuff819xUsb(struct sk_buff *skb,
praddr = hdr->addr1;
/* Check if the received packet is acceptable. */
- bpacket_match_bssid = (IEEE80211_FTYPE_CTL != type) &&
+ bpacket_match_bssid = (type != IEEE80211_FTYPE_CTL) &&
(eqMacAddr(priv->ieee80211->current_network.bssid, (fc & IEEE80211_FCTL_TODS) ? hdr->addr1 : (fc & IEEE80211_FCTL_FROMDS) ? hdr->addr2 : hdr->addr3))
&& (!pstats->bHwError) && (!pstats->bCRC) && (!pstats->bICV);
bpacket_toself = bpacket_match_bssid &
@@ -5098,7 +5098,7 @@ void EnableHWSecurityConfig8192(struct net_device *dev)
struct ieee80211_device *ieee = priv->ieee80211;
SECR_value = SCR_TxEncEnable | SCR_RxDecEnable;
- if (((KEY_TYPE_WEP40 == ieee->pairwise_key_type) || (KEY_TYPE_WEP104 == ieee->pairwise_key_type)) && (priv->ieee80211->auth_mode != 2)) {
+ if (((ieee->pairwise_key_type == KEY_TYPE_WEP40) || (ieee->pairwise_key_type == KEY_TYPE_WEP104)) && (priv->ieee80211->auth_mode != 2)) {
SECR_value |= SCR_RxUseDK;
SECR_value |= SCR_TxUseDK;
} else if ((ieee->iw_mode == IW_MODE_ADHOC) && (ieee->pairwise_key_type & (KEY_TYPE_CCMP | KEY_TYPE_TKIP))) {
diff --git a/drivers/staging/rtl8192u/r8192U_dm.c b/drivers/staging/rtl8192u/r8192U_dm.c
index 975f707827e1..e6f8d1da65d9 100644
--- a/drivers/staging/rtl8192u/r8192U_dm.c
+++ b/drivers/staging/rtl8192u/r8192U_dm.c
@@ -2300,43 +2300,52 @@ static void dm_check_edca_turbo(
* Restore original EDCA according to the declaration of AP.
*/
if (priv->bcurrent_turbo_EDCA) {
+ u8 u1bAIFS;
+ u32 u4bAcParam, op_limit, cw_max, cw_min;
+
+ struct ieee80211_qos_parameters *qos_parameters = &priv->ieee80211->current_network.qos_data.parameters;
+ u8 mode = priv->ieee80211->mode;
+
+ /* For Each time updating EDCA parameter, reset EDCA turbo mode status. */
+ dm_init_edca_turbo(dev);
+
+ u1bAIFS = qos_parameters->aifs[0] * ((mode & (IEEE_G | IEEE_N_24G)) ? 9 : 20) + aSifsTime;
+
+ op_limit = (u32)le16_to_cpu(qos_parameters->tx_op_limit[0]);
+ cw_max = (u32)le16_to_cpu(qos_parameters->cw_max[0]);
+ cw_min = (u32)le16_to_cpu(qos_parameters->cw_min[0]);
+
+ op_limit <<= AC_PARAM_TXOP_LIMIT_OFFSET;
+ cw_max <<= AC_PARAM_ECW_MAX_OFFSET;
+ cw_min <<= AC_PARAM_ECW_MIN_OFFSET;
+ u1bAIFS <<= AC_PARAM_AIFS_OFFSET;
+
+ u4bAcParam = op_limit | cw_max | cw_min | u1bAIFS;
+ cpu_to_le32s(&u4bAcParam);
+
+ write_nic_dword(dev, EDCAPARA_BE, u4bAcParam);
+
+
+ /*
+ * Check ACM bit.
+ * If it is set, immediately set ACM control bit to downgrading AC for passing WMM testplan. Annie, 2005-12-13.
+ */
{
- u8 u1bAIFS;
- u32 u4bAcParam;
- struct ieee80211_qos_parameters *qos_parameters = &priv->ieee80211->current_network.qos_data.parameters;
- u8 mode = priv->ieee80211->mode;
-
- /* For Each time updating EDCA parameter, reset EDCA turbo mode status. */
- dm_init_edca_turbo(dev);
- u1bAIFS = qos_parameters->aifs[0] * ((mode&(IEEE_G|IEEE_N_24G)) ? 9 : 20) + aSifsTime;
- u4bAcParam = (((le16_to_cpu(qos_parameters->tx_op_limit[0])) << AC_PARAM_TXOP_LIMIT_OFFSET)|
- ((le16_to_cpu(qos_parameters->cw_max[0])) << AC_PARAM_ECW_MAX_OFFSET)|
- ((le16_to_cpu(qos_parameters->cw_min[0])) << AC_PARAM_ECW_MIN_OFFSET)|
- ((u32)u1bAIFS << AC_PARAM_AIFS_OFFSET));
- /*write_nic_dword(dev, WDCAPARA_ADD[i], u4bAcParam);*/
- write_nic_dword(dev, EDCAPARA_BE, u4bAcParam);
-
- /*
- * Check ACM bit.
- * If it is set, immediately set ACM control bit to downgrading AC for passing WMM testplan. Annie, 2005-12-13.
- */
- {
- /* TODO: Modified this part and try to set acm control in only 1 IO processing!! */
-
- PACI_AIFSN pAciAifsn = (PACI_AIFSN)&(qos_parameters->aifs[0]);
- u8 AcmCtrl;
-
- read_nic_byte(dev, AcmHwCtrl, &AcmCtrl);
-
- if (pAciAifsn->f.ACM) { /* ACM bit is 1. */
- AcmCtrl |= AcmHw_BeqEn;
- } else { /* ACM bit is 0. */
- AcmCtrl &= (~AcmHw_BeqEn);
- }
+ /* TODO: Modified this part and try to set acm control in only 1 IO processing!! */
- RT_TRACE(COMP_QOS, "SetHwReg8190pci(): [HW_VAR_ACM_CTRL] Write 0x%X\n", AcmCtrl);
- write_nic_byte(dev, AcmHwCtrl, AcmCtrl);
+ PACI_AIFSN pAciAifsn = (PACI_AIFSN)&(qos_parameters->aifs[0]);
+ u8 AcmCtrl;
+
+ read_nic_byte(dev, AcmHwCtrl, &AcmCtrl);
+
+ if (pAciAifsn->f.ACM) { /* ACM bit is 1. */
+ AcmCtrl |= AcmHw_BeqEn;
+ } else { /* ACM bit is 0. */
+ AcmCtrl &= (~AcmHw_BeqEn);
}
+
+ RT_TRACE(COMP_QOS, "SetHwReg8190pci(): [HW_VAR_ACM_CTRL] Write 0x%X\n", AcmCtrl);
+ write_nic_byte(dev, AcmHwCtrl, AcmCtrl);
}
priv->bcurrent_turbo_EDCA = false;
}
diff --git a/drivers/staging/rtl8712/ieee80211.c b/drivers/staging/rtl8712/ieee80211.c
index f35121eedac6..33e82a9dd462 100644
--- a/drivers/staging/rtl8712/ieee80211.c
+++ b/drivers/staging/rtl8712/ieee80211.c
@@ -166,7 +166,7 @@ static uint r8712_get_rateset_len(u8 *rateset)
int r8712_generate_ie(struct registry_priv *pregistrypriv)
{
- int sz = 0, rateLen;
+ int sz = 0, rate_len;
struct wlan_bssid_ex *pdev_network = &pregistrypriv->dev_network;
u8 *ie = pdev_network->IEs;
@@ -191,15 +191,16 @@ int r8712_generate_ie(struct registry_priv *pregistrypriv)
pdev_network->Ssid.Ssid, &sz);
/*supported rates*/
set_supported_rate(pdev_network->rates, pregistrypriv->wireless_mode);
- rateLen = r8712_get_rateset_len(pdev_network->rates);
- if (rateLen > 8) {
+ rate_len = r8712_get_rateset_len(pdev_network->rates);
+ if (rate_len > 8) {
ie = r8712_set_ie(ie, _SUPPORTEDRATES_IE_, 8,
pdev_network->rates, &sz);
- ie = r8712_set_ie(ie, _EXT_SUPPORTEDRATES_IE_, (rateLen - 8),
+ ie = r8712_set_ie(ie, _EXT_SUPPORTEDRATES_IE_, (rate_len - 8),
(pdev_network->rates + 8), &sz);
- } else
+ } else {
ie = r8712_set_ie(ie, _SUPPORTEDRATES_IE_,
- rateLen, pdev_network->rates, &sz);
+ rate_len, pdev_network->rates, &sz);
+ }
/*DS parameter set*/
ie = r8712_set_ie(ie, _DSSET_IE_, 1,
(u8 *)&pdev_network->Configuration.DSConfig, &sz);
diff --git a/drivers/staging/rtl8712/os_intfs.c b/drivers/staging/rtl8712/os_intfs.c
index 8836b31b4ef8..e698f6ede449 100644
--- a/drivers/staging/rtl8712/os_intfs.c
+++ b/drivers/staging/rtl8712/os_intfs.c
@@ -93,7 +93,7 @@ static char *initmac;
*/
static int wifi_test;
-module_param_string(ifname, ifname, sizeof(ifname), S_IRUGO | S_IWUSR);
+module_param_string(ifname, ifname, sizeof(ifname), 0644);
module_param(wifi_test, int, 0644);
module_param(initmac, charp, 0644);
module_param(video_mode, int, 0644);
diff --git a/drivers/staging/rtl8712/wifi.h b/drivers/staging/rtl8712/wifi.h
index 556367bfbe8a..0ed2f44ab4e9 100644
--- a/drivers/staging/rtl8712/wifi.h
+++ b/drivers/staging/rtl8712/wifi.h
@@ -170,8 +170,10 @@ enum WIFI_REG_DOMAIN {
*(__le16 *)(pbuf) &= (~cpu_to_le16(_FROM_DS_)); \
})
-#define get_tofr_ds(pframe) ((GetToDs(pframe) << 1) | GetFrDs(pframe))
-
+static inline unsigned char get_tofr_ds(unsigned char *pframe)
+{
+ return ((GetToDs(pframe) << 1) | GetFrDs(pframe));
+}
#define SetMFrag(pbuf) ({ \
*(__le16 *)(pbuf) |= cpu_to_le16(_MORE_FRAG_); \
diff --git a/drivers/staging/rtl8723bs/core/rtw_mlme.c b/drivers/staging/rtl8723bs/core/rtw_mlme.c
index 9e355734f0c0..d5ab12305e59 100644
--- a/drivers/staging/rtl8723bs/core/rtw_mlme.c
+++ b/drivers/staging/rtl8723bs/core/rtw_mlme.c
@@ -249,7 +249,7 @@ void _rtw_free_network_nolock(struct mlme_priv *pmlmepriv, struct wlan_network *
/*
return the wlan_network with the matching addr
- Shall be calle under atomic context... to avoid possible racing condition...
+ Shall be called under atomic context... to avoid possible racing condition...
*/
struct wlan_network *_rtw_find_network(struct __queue *scanned_queue, u8 *addr)
{
@@ -412,7 +412,7 @@ void rtw_free_network_queue(struct adapter *dev, u8 isfreeall)
/*
return the wlan_network with the matching addr
- Shall be calle under atomic context... to avoid possible racing condition...
+ Shall be called under atomic context... to avoid possible racing condition...
*/
struct wlan_network *rtw_find_network(struct __queue *scanned_queue, u8 *addr)
{
@@ -564,7 +564,7 @@ void update_network(struct wlan_bssid_ex *dst, struct wlan_bssid_ex *src,
sq_final = ((u32)(src->PhyInfo.SignalQuality)+(u32)(dst->PhyInfo.SignalQuality)*4)/5;
rssi_final = (src->Rssi+dst->Rssi*4)/5;
} else {
- /* bss info not receving from the right channel, use the original RX signal infos */
+ /* bss info not receiving from the right channel, use the original RX signal infos */
ss_final = dst->PhyInfo.SignalStrength;
sq_final = dst->PhyInfo.SignalQuality;
rssi_final = dst->Rssi;
@@ -680,7 +680,7 @@ void rtw_update_scanned_network(struct adapter *adapter, struct wlan_bssid_ex *t
pnetwork->aid = 0;
pnetwork->join_res = 0;
- /* bss info not receving from the right channel */
+ /* bss info not receiving from the right channel */
if (pnetwork->network.PhyInfo.SignalQuality == 101)
pnetwork->network.PhyInfo.SignalQuality = 0;
} else {
@@ -699,7 +699,7 @@ void rtw_update_scanned_network(struct adapter *adapter, struct wlan_bssid_ex *t
pnetwork->last_scanned = jiffies;
- /* bss info not receving from the right channel */
+ /* bss info not receiving from the right channel */
if (pnetwork->network.PhyInfo.SignalQuality == 101)
pnetwork->network.PhyInfo.SignalQuality = 0;
@@ -715,7 +715,7 @@ void rtw_update_scanned_network(struct adapter *adapter, struct wlan_bssid_ex *t
pnetwork->last_scanned = jiffies;
- /* target.Reserved[0]== 1, means that scaned network is a bcn frame. */
+ /* target.Reserved[0]== 1, means that scanned network is a bcn frame. */
if ((pnetwork->network.IELength > target->IELength) && (target->Reserved[0] == 1))
update_ie = false;
@@ -1264,7 +1264,7 @@ static struct sta_info *rtw_joinbss_update_stainfo(struct adapter *padapter, str
/* Commented by Albert 2012/07/21 */
/* When doing the WPS, the wps_ie_len won't equal to 0 */
- /* And the Wi-Fi driver shouldn't allow the data packet to be tramsmitted. */
+ /* And the Wi-Fi driver shouldn't allow the data packet to be transmitted. */
if (padapter->securitypriv.wps_ie_len != 0) {
psta->ieee8021x_blocked = true;
padapter->securitypriv.wps_ie_len = 0;
@@ -1272,7 +1272,7 @@ static struct sta_info *rtw_joinbss_update_stainfo(struct adapter *padapter, str
/* for A-MPDU Rx reordering buffer control for bmc_sta & sta_info */
- /* if A-MPDU Rx is enabled, reseting rx_ordering_ctrl wstart_b(indicate_seq) to default value = 0xffff */
+ /* if A-MPDU Rx is enabled, resetting rx_ordering_ctrl wstart_b(indicate_seq) to default value = 0xffff */
/* todo: check if AP can send A-MPDU packets */
for (i = 0; i < 16 ; i++) {
/* preorder_ctrl = &precvpriv->recvreorder_ctrl[i]; */
@@ -1374,7 +1374,7 @@ static void rtw_joinbss_update_network(struct adapter *padapter, struct wlan_net
rtw_update_ht_cap(padapter, cur_network->network.IEs, cur_network->network.IELength, (u8) cur_network->network.Configuration.DSConfig);
}
-/* Notes: the fucntion could be > passive_level (the same context as Rx tasklet) */
+/* Notes: the function could be > passive_level (the same context as Rx tasklet) */
/* pnetwork : returns from rtw_joinbss_event_callback */
/* ptarget_wlan: found from scanned_queue */
/* if join_res > 0, for (fw_state ==WIFI_STATION_STATE), we check if "ptarget_sta" & "ptarget_wlan" exist. */
@@ -1482,10 +1482,10 @@ void rtw_joinbss_event_prehandle(struct adapter *adapter, u8 *pbuf)
}
- /* s5. Cancle assoc_timer */
+ /* s5. Cancel assoc_timer */
_cancel_timer(&pmlmepriv->assoc_timer, &timer_cancelled);
- RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_, ("Cancle assoc_timer\n"));
+ RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_, ("Cancel assoc_timer\n"));
} else{
RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_, ("rtw_joinbss_event_callback err: fw_state:%x", get_fwstate(pmlmepriv)));
@@ -1817,7 +1817,7 @@ void rtw_wmm_event_callback(struct adapter *padapter, u8 *pbuf)
}
/*
-* _rtw_join_timeout_handler - Timeout/faliure handler for CMD JoinBss
+* _rtw_join_timeout_handler - Timeout/failure handler for CMD JoinBss
* @adapter: pointer to struct adapter structure
*/
void _rtw_join_timeout_handler (struct adapter *adapter)
@@ -1870,7 +1870,7 @@ void _rtw_join_timeout_handler (struct adapter *adapter)
}
/*
-* rtw_scan_timeout_handler - Timeout/Faliure handler for CMD SiteSurvey
+* rtw_scan_timeout_handler - Timeout/Failure handler for CMD SiteSurvey
* @adapter: pointer to struct adapter structure
*/
void rtw_scan_timeout_handler (struct adapter *adapter)
@@ -2622,7 +2622,7 @@ void rtw_get_encrypt_decrypt_from_registrypriv(struct adapter *adapter)
{
}
-/* the fucntion is at passive_level */
+/* the function is at passive_level */
void rtw_joinbss_reset(struct adapter *padapter)
{
u8 threshold;
@@ -2727,7 +2727,7 @@ void rtw_build_wmm_ie_ht(struct adapter *padapter, u8 *out_ie, uint *pout_len)
}
}
-/* the fucntion is >= passive_level */
+/* the function is >= passive_level */
unsigned int rtw_restructure_ht_ie(struct adapter *padapter, u8 *in_ie, u8 *out_ie, uint in_len, uint *pout_len, u8 channel)
{
u32 ielen, out_len;
@@ -2879,7 +2879,7 @@ unsigned int rtw_restructure_ht_ie(struct adapter *padapter, u8 *in_ie, u8 *out_
}
-/* the fucntion is > passive_level (in critical_section) */
+/* the function is > passive_level (in critical_section) */
void rtw_update_ht_cap(struct adapter *padapter, u8 *pie, uint ie_len, u8 channel)
{
u8 *p, max_ampdu_sz;
diff --git a/drivers/staging/rtl8723bs/hal/HalBtc8723b1Ant.c b/drivers/staging/rtl8723bs/hal/HalBtc8723b1Ant.c
index 86040adb436c..37f42bfc55ed 100644
--- a/drivers/staging/rtl8723bs/hal/HalBtc8723b1Ant.c
+++ b/drivers/staging/rtl8723bs/hal/HalBtc8723b1Ant.c
@@ -404,7 +404,7 @@ static void halbtc8723b1ant_MonitorWiFiCtr(PBTC_COEXIST pBtCoexist)
{
s32 wifiRssi = 0;
bool bWifiBusy = false, bWifiUnderBMode = false;
- static u8 nCCKLockCounter = 0;
+ static u8 nCCKLockCounter;
pBtCoexist->fBtcGet(pBtCoexist, BTC_GET_BL_WIFI_BUSY, &bWifiBusy);
pBtCoexist->fBtcGet(pBtCoexist, BTC_GET_S4_WIFI_RSSI, &wifiRssi);
@@ -488,7 +488,7 @@ static void halbtc8723b1ant_MonitorWiFiCtr(PBTC_COEXIST pBtCoexist)
static bool halbtc8723b1ant_IsWifiStatusChanged(PBTC_COEXIST pBtCoexist)
{
- static bool bPreWifiBusy = false, bPreUnder4way = false, bPreBtHsOn = false;
+ static bool bPreWifiBusy, bPreUnder4way, bPreBtHsOn;
bool bWifiBusy = false, bUnder4way = false, bBtHsOn = false;
bool bWifiConnected = false;
@@ -2754,7 +2754,7 @@ void EXhalbtc8723b1ant_DisplayCoexInfo(PBTC_COEXIST pBtCoexist)
u32 wifiBw, wifiTrafficDir, faOfdm, faCck, wifiLinkStatus;
u8 wifiDot11Chnl, wifiHsChnl;
u32 fwVer = 0, btPatchVer = 0;
- static u8 PopReportIn10s = 0;
+ static u8 PopReportIn10s;
CL_SPRINTF(
cliBuf,
@@ -3751,7 +3751,7 @@ void EXhalbtc8723b1ant_PnpNotify(PBTC_COEXIST pBtCoexist, u8 pnpState)
void EXhalbtc8723b1ant_Periodical(PBTC_COEXIST pBtCoexist)
{
- static u8 disVerInfoCnt = 0;
+ static u8 disVerInfoCnt;
u32 fwVer = 0, btPatchVer = 0;
BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, ("[BTCoex], ==========================Periodical ===========================\n"));
diff --git a/drivers/staging/rtl8723bs/hal/HalBtc8723b2Ant.c b/drivers/staging/rtl8723bs/hal/HalBtc8723b2Ant.c
index f5bc511d02f2..33610d39333f 100644
--- a/drivers/staging/rtl8723bs/hal/HalBtc8723b2Ant.c
+++ b/drivers/staging/rtl8723bs/hal/HalBtc8723b2Ant.c
@@ -282,7 +282,7 @@ static void halbtc8723b2ant_QueryBtInfo(PBTC_COEXIST pBtCoexist)
static bool halbtc8723b2ant_IsWifiStatusChanged(PBTC_COEXIST pBtCoexist)
{
- static bool bPreWifiBusy = false, bPreUnder4way = false, bPreBtHsOn = false;
+ static bool bPreWifiBusy, bPreUnder4way, bPreBtHsOn;
bool bWifiBusy = false, bUnder4way = false, bBtHsOn = false;
bool bWifiConnected = false;
@@ -3706,7 +3706,7 @@ void EXhalbtc8723b2ant_PnpNotify(PBTC_COEXIST pBtCoexist, u8 pnpState)
void EXhalbtc8723b2ant_Periodical(PBTC_COEXIST pBtCoexist)
{
- static u8 disVerInfoCnt = 0;
+ static u8 disVerInfoCnt;
u32 fwVer = 0, btPatchVer = 0;
BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, ("[BTCoex], ==========================Periodical ===========================\n"));
diff --git a/drivers/staging/rtl8723bs/hal/hal_btcoex.c b/drivers/staging/rtl8723bs/hal/hal_btcoex.c
index cc7e0903ee9d..9e08a4de4895 100644
--- a/drivers/staging/rtl8723bs/hal/hal_btcoex.c
+++ b/drivers/staging/rtl8723bs/hal/hal_btcoex.c
@@ -385,7 +385,7 @@ static s32 halbtcoutsrc_GetWifiRssi(struct adapter *padapter)
static u8 halbtcoutsrc_GetWifiScanAPNum(struct adapter *padapter)
{
struct mlme_ext_priv *pmlmeext;
- static u8 scan_AP_num = 0;
+ static u8 scan_AP_num;
pmlmeext = &padapter->mlmeextpriv;
diff --git a/drivers/staging/rtl8723bs/hal/hal_com.c b/drivers/staging/rtl8723bs/hal/hal_com.c
index 1880d4140bee..e3a98322f475 100644
--- a/drivers/staging/rtl8723bs/hal/hal_com.c
+++ b/drivers/staging/rtl8723bs/hal/hal_com.c
@@ -26,7 +26,7 @@ u8 rtw_hal_data_init(struct adapter *padapter)
padapter->hal_data_sz = sizeof(struct hal_com_data);
padapter->HalData = vzalloc(padapter->hal_data_sz);
if (padapter->HalData == NULL) {
- DBG_8192C("cant not alloc memory for HAL DATA\n");
+ DBG_8192C("cannot alloc memory for HAL DATA\n");
return _FAIL;
}
}
@@ -1415,7 +1415,8 @@ bool GetHexValueFromString(char *szStr, u32 *pu4bVal, u32 *pu4bMove)
/* Check input parameter. */
if (szStr == NULL || pu4bVal == NULL || pu4bMove == NULL) {
- DBG_871X("GetHexValueFromString(): Invalid inpur argumetns! szStr: %p, pu4bVal: %p, pu4bMove: %p\n", szStr, pu4bVal, pu4bMove);
+ DBG_871X("GetHexValueFromString(): Invalid input arguments! szStr: %p, pu4bVal: %p, pu4bMove: %p\n",
+ szStr, pu4bVal, pu4bMove);
return false;
}
diff --git a/drivers/staging/rtl8723bs/hal/odm.h b/drivers/staging/rtl8723bs/hal/odm.h
index 0b3541a91548..87a76bafecb3 100644
--- a/drivers/staging/rtl8723bs/hal/odm.h
+++ b/drivers/staging/rtl8723bs/hal/odm.h
@@ -209,7 +209,10 @@ typedef struct _ODM_RATE_ADAPTIVE {
#define AVG_THERMAL_NUM 8
#define IQK_Matrix_REG_NUM 8
-#define IQK_Matrix_Settings_NUM 14+24+21 /* Channels_2_4G_NUM + Channels_5G_20M_NUM + Channels_5G */
+#define IQK_Matrix_Settings_NUM (14 + 24 + 21) /* Channels_2_4G_NUM
+ * + Channels_5G_20M_NUM
+ * + Channels_5G
+ */
#define DM_Type_ByFW 0
#define DM_Type_ByDriver 1
diff --git a/drivers/staging/rtl8723bs/hal/odm_DIG.c b/drivers/staging/rtl8723bs/hal/odm_DIG.c
index ba8e8eb534ef..0bde9444471d 100644
--- a/drivers/staging/rtl8723bs/hal/odm_DIG.c
+++ b/drivers/staging/rtl8723bs/hal/odm_DIG.c
@@ -278,11 +278,11 @@ void odm_Adaptivity(void *pDM_VOID, u8 IGI)
if (!pDM_Odm->ForceEDCCA) {
if (pDM_Odm->RSSI_Min > pDM_Odm->AdapEn_RSSI)
- EDCCA_State = 1;
+ EDCCA_State = true;
else if (pDM_Odm->RSSI_Min < (pDM_Odm->AdapEn_RSSI - 5))
- EDCCA_State = 0;
+ EDCCA_State = false;
} else
- EDCCA_State = 1;
+ EDCCA_State = true;
if (
pDM_Odm->bLinked &&
@@ -305,7 +305,7 @@ void odm_Adaptivity(void *pDM_VOID, u8 IGI)
)
);
- if (EDCCA_State == 1) {
+ if (EDCCA_State) {
Diff = IGI_target-(s8)IGI;
TH_L2H_dmc = pDM_Odm->TH_L2H_ini + Diff;
if (TH_L2H_dmc > 10)
@@ -372,7 +372,7 @@ void odm_PauseDIG(
{
PDM_ODM_T pDM_Odm = (PDM_ODM_T)pDM_VOID;
pDIG_T pDM_DigTable = &pDM_Odm->DM_DigTable;
- static bool bPaused = false;
+ static bool bPaused;
ODM_RT_TRACE(pDM_Odm, ODM_COMP_DIG, ODM_DBG_LOUD, ("odm_PauseDIG() =========>\n"));
diff --git a/drivers/staging/rtl8723bs/hal/odm_debug.h b/drivers/staging/rtl8723bs/hal/odm_debug.h
index 2ec4baf57464..ff131361248c 100644
--- a/drivers/staging/rtl8723bs/hal/odm_debug.h
+++ b/drivers/staging/rtl8723bs/hal/odm_debug.h
@@ -105,51 +105,60 @@
#if DBG
#define ODM_RT_TRACE(pDM_Odm, comp, level, fmt)\
- if (\
- (comp & pDM_Odm->DebugComponents) &&\
- (level <= pDM_Odm->DebugLevel || level == ODM_DBG_SERIOUS)\
- ) {\
- RT_PRINTK fmt;\
- }
+ do {\
+ if (\
+ (comp & pDM_Odm->DebugComponents) &&\
+ (level <= pDM_Odm->DebugLevel ||\
+ level == ODM_DBG_SERIOUS)\
+ ) {\
+ RT_PRINTK fmt;\
+ } \
+ } while (0)
#define ODM_RT_TRACE_F(pDM_Odm, comp, level, fmt)\
- if (\
- (comp & pDM_Odm->DebugComponents) &&\
- (level <= pDM_Odm->DebugLevel)\
- ) {\
- RT_PRINTK fmt;\
- }
+ do {\
+ if (\
+ (comp & pDM_Odm->DebugComponents) &&\
+ (level <= pDM_Odm->DebugLevel)\
+ ) {\
+ RT_PRINTK fmt;\
+ } \
+ } while (0)
#define ODM_RT_ASSERT(pDM_Odm, expr, fmt)\
- if (!expr) {\
- DbgPrint("Assertion failed! %s at ......\n", #expr);\
- DbgPrint(\
- " ......%s,%s, line =%d\n",\
- __FILE__,\
- __func__,\
- __LINE__\
- );\
- RT_PRINTK fmt;\
- ASSERT(false);\
- }
+ do {\
+ if (!expr) {\
+ DbgPrint("Assertion failed! %s at ......\n", #expr);\
+ DbgPrint(\
+ " ......%s,%s, line =%d\n",\
+ __FILE__,\
+ __func__,\
+ __LINE__\
+ );\
+ RT_PRINTK fmt;\
+ ASSERT(false);\
+ } \
+ } while (0)
#define ODM_dbg_enter() { DbgPrint("==> %s\n", __func__); }
#define ODM_dbg_exit() { DbgPrint("<== %s\n", __func__); }
#define ODM_dbg_trace(str) { DbgPrint("%s:%s\n", __func__, str); }
#define ODM_PRINT_ADDR(pDM_Odm, comp, level, title_str, ptr)\
- if (\
- (comp & pDM_Odm->DebugComponents) &&\
- (level <= pDM_Odm->DebugLevel)\
- ) {\
- int __i;\
- u8 *__ptr = (u8 *)ptr;\
- DbgPrint("[ODM] ");\
- DbgPrint(title_str);\
- DbgPrint(" ");\
- for (__i = 0; __i < 6; __i++)\
- DbgPrint("%02X%s", __ptr[__i], (__i == 5) ? "" : "-");\
- DbgPrint("\n");\
- }
+ do {\
+ if (\
+ (comp & pDM_Odm->DebugComponents) &&\
+ (level <= pDM_Odm->DebugLevel)\
+ ) {\
+ int __i;\
+ u8 *__ptr = (u8 *)ptr;\
+ DbgPrint("[ODM] ");\
+ DbgPrint(title_str);\
+ DbgPrint(" ");\
+ for (__i = 0; __i < 6; __i++)\
+ DbgPrint("%02X%s", __ptr[__i], (__i == 5) ? "" : "-");\
+ DbgPrint("\n");\
+ } \
+ } while (0)
#else
#define ODM_RT_TRACE(pDM_Odm, comp, level, fmt) no_printk fmt
#define ODM_RT_TRACE_F(pDM_Odm, comp, level, fmt) no_printk fmt
diff --git a/drivers/staging/rtl8723bs/hal/rtl8723b_hal_init.c b/drivers/staging/rtl8723bs/hal/rtl8723b_hal_init.c
index 163537faefd9..84a89ef74169 100644
--- a/drivers/staging/rtl8723bs/hal/rtl8723b_hal_init.c
+++ b/drivers/staging/rtl8723bs/hal/rtl8723b_hal_init.c
@@ -1741,7 +1741,8 @@ static u8 hal_EfusePgPacketWrite2ByteHeader(
efuse_addr = *pAddr;
if (efuse_addr >= efuse_max_available_len) {
- DBG_8192C("%s: addr(%d) over avaliable(%d)!!\n", __func__, efuse_addr, efuse_max_available_len);
+ DBG_8192C("%s: addr(%d) over available (%d)!!\n", __func__,
+ efuse_addr, efuse_max_available_len);
return false;
}
diff --git a/drivers/staging/rtl8723bs/hal/rtl8723b_phycfg.c b/drivers/staging/rtl8723bs/hal/rtl8723b_phycfg.c
index 28d1a229c3a6..21ec890fd60c 100644
--- a/drivers/staging/rtl8723bs/hal/rtl8723b_phycfg.c
+++ b/drivers/staging/rtl8723bs/hal/rtl8723b_phycfg.c
@@ -385,8 +385,7 @@ s32 PHY_MACConfig8723B(struct adapter *Adapter)
/* Config MAC */
/* */
rtStatus = phy_ConfigMACWithParaFile(Adapter, pszMACRegFile);
- if (rtStatus == _FAIL)
- {
+ if (rtStatus == _FAIL) {
ODM_ConfigMACWithHeaderFile(&pHalData->odmpriv);
rtStatus = _SUCCESS;
}
@@ -459,8 +458,7 @@ static int phy_BB8723b_Config_ParaFile(struct adapter *Adapter)
Adapter->registrypriv.RegEnableTxPowerLimit == 1 ||
(Adapter->registrypriv.RegEnableTxPowerLimit == 2 && pHalData->EEPROMRegulatory == 1)
) {
- if (PHY_ConfigRFWithPowerLimitTableParaFile(Adapter, pszRFTxPwrLmtFile) == _FAIL)
- {
+ if (PHY_ConfigRFWithPowerLimitTableParaFile(Adapter, pszRFTxPwrLmtFile) == _FAIL) {
if (HAL_STATUS_SUCCESS != ODM_ConfigRFWithHeaderFile(&pHalData->odmpriv, CONFIG_RF_TXPWR_LMT, (ODM_RF_RADIO_PATH_E)0))
rtStatus = _FAIL;
}
@@ -474,8 +472,8 @@ static int phy_BB8723b_Config_ParaFile(struct adapter *Adapter)
/* */
/* 1. Read PHY_REG.TXT BB INIT!! */
/* */
- if (phy_ConfigBBWithParaFile(Adapter, pszBBRegFile, CONFIG_BB_PHY_REG) == _FAIL)
- {
+ if (phy_ConfigBBWithParaFile(Adapter, pszBBRegFile, CONFIG_BB_PHY_REG) ==
+ _FAIL) {
if (HAL_STATUS_SUCCESS != ODM_ConfigBBWithHeaderFile(&pHalData->odmpriv, CONFIG_BB_PHY_REG))
rtStatus = _FAIL;
}
@@ -491,8 +489,8 @@ static int phy_BB8723b_Config_ParaFile(struct adapter *Adapter)
Adapter->registrypriv.RegEnableTxPowerByRate == 1 ||
(Adapter->registrypriv.RegEnableTxPowerByRate == 2 && pHalData->EEPROMRegulatory != 2)
) {
- if (phy_ConfigBBWithPgParaFile(Adapter, pszBBRegPgFile) == _FAIL)
- {
+ if (phy_ConfigBBWithPgParaFile(Adapter, pszBBRegPgFile) ==
+ _FAIL) {
if (HAL_STATUS_SUCCESS != ODM_ConfigBBWithHeaderFile(&pHalData->odmpriv, CONFIG_BB_PHY_REG_PG))
rtStatus = _FAIL;
}
@@ -514,8 +512,8 @@ static int phy_BB8723b_Config_ParaFile(struct adapter *Adapter)
/* */
/* 2. Read BB AGC table Initialization */
/* */
- if (phy_ConfigBBWithParaFile(Adapter, pszAGCTableFile, CONFIG_BB_AGC_TAB) == _FAIL)
- {
+ if (phy_ConfigBBWithParaFile(Adapter, pszAGCTableFile,
+ CONFIG_BB_AGC_TAB) == _FAIL) {
if (HAL_STATUS_SUCCESS != ODM_ConfigBBWithHeaderFile(&pHalData->odmpriv, CONFIG_BB_AGC_TAB))
rtStatus = _FAIL;
}
diff --git a/drivers/staging/rtl8723bs/hal/rtl8723b_rf6052.c b/drivers/staging/rtl8723bs/hal/rtl8723b_rf6052.c
index 3a85d0cddfda..a71b552eca9a 100644
--- a/drivers/staging/rtl8723bs/hal/rtl8723b_rf6052.c
+++ b/drivers/staging/rtl8723bs/hal/rtl8723b_rf6052.c
@@ -144,15 +144,15 @@ static int phy_RF6052_Config_ParaFile(struct adapter *Adapter)
/*----Initialize RF fom connfiguration file----*/
switch (eRFPath) {
case RF_PATH_A:
- if (PHY_ConfigRFWithParaFile(Adapter, pszRadioAFile, eRFPath) == _FAIL)
- {
+ if (PHY_ConfigRFWithParaFile(Adapter, pszRadioAFile,
+ eRFPath) == _FAIL) {
if (HAL_STATUS_FAILURE == ODM_ConfigRFWithHeaderFile(&pHalData->odmpriv, CONFIG_RF_RADIO, (ODM_RF_RADIO_PATH_E)eRFPath))
rtStatus = _FAIL;
}
break;
case RF_PATH_B:
- if (PHY_ConfigRFWithParaFile(Adapter, pszRadioBFile, eRFPath) == _FAIL)
- {
+ if (PHY_ConfigRFWithParaFile(Adapter, pszRadioBFile,
+ eRFPath) == _FAIL) {
if (HAL_STATUS_FAILURE == ODM_ConfigRFWithHeaderFile(&pHalData->odmpriv, CONFIG_RF_RADIO, (ODM_RF_RADIO_PATH_E)eRFPath))
rtStatus = _FAIL;
}
@@ -186,8 +186,8 @@ static int phy_RF6052_Config_ParaFile(struct adapter *Adapter)
/* 3 Configuration of Tx Power Tracking */
/* 3 ----------------------------------------------------------------- */
- if (PHY_ConfigRFWithTxPwrTrackParaFile(Adapter, pszTxPwrTrackFile) == _FAIL)
- {
+ if (PHY_ConfigRFWithTxPwrTrackParaFile(Adapter, pszTxPwrTrackFile) ==
+ _FAIL) {
ODM_ConfigRFWithTxPwrTrackHeaderFile(&pHalData->odmpriv);
}
diff --git a/drivers/staging/rtl8723bs/hal/rtl8723bs_xmit.c b/drivers/staging/rtl8723bs/hal/rtl8723bs_xmit.c
index ca6ad9659b09..9bee2e40be32 100644
--- a/drivers/staging/rtl8723bs/hal/rtl8723bs_xmit.c
+++ b/drivers/staging/rtl8723bs/hal/rtl8723bs_xmit.c
@@ -23,8 +23,7 @@ static u8 rtw_sdio_wait_enough_TxOQT_space(struct adapter *padapter, u8 agg_num)
u32 n = 0;
struct hal_com_data *pHalData = GET_HAL_DATA(padapter);
- while (pHalData->SdioTxOQTFreeSpace < agg_num)
- {
+ while (pHalData->SdioTxOQTFreeSpace < agg_num) {
if (
(padapter->bSurpriseRemoved == true) ||
(padapter->bDriverStopped == true)
@@ -59,7 +58,7 @@ static s32 rtl8723_dequeue_writeport(struct adapter *padapter)
struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
struct dvobj_priv *pdvobjpriv = adapter_to_dvobj(padapter);
struct xmit_buf *pxmitbuf;
- struct adapter * pri_padapter = padapter;
+ struct adapter *pri_padapter = padapter;
s32 ret = 0;
u8 PageIdx = 0;
u32 deviceId;
@@ -231,7 +230,7 @@ static s32 xmit_xmitframes(struct adapter *padapter, struct xmit_priv *pxmitpriv
pxmitbuf = NULL;
if (padapter->registrypriv.wifi_spec == 1) {
- for (idx = 0; idx<4; idx++)
+ for (idx = 0; idx < 4; idx++)
inx[idx] = pxmitpriv->wmm_para_seq[idx];
} else {
inx[0] = 0;
@@ -299,9 +298,10 @@ static s32 xmit_xmitframes(struct adapter *padapter, struct xmit_priv *pxmitpriv
) {
if (pxmitbuf) {
/* pxmitbuf->priv_data will be NULL, and will crash here */
- if (pxmitbuf->len > 0 && pxmitbuf->priv_data) {
+ if (pxmitbuf->len > 0 &&
+ pxmitbuf->priv_data) {
struct xmit_frame *pframe;
- pframe = (struct xmit_frame*)pxmitbuf->priv_data;
+ pframe = (struct xmit_frame *)pxmitbuf->priv_data;
pframe->agg_num = k;
pxmitbuf->agg_num = k;
rtl8723b_update_txdesc(pframe, pframe->buf_addr);
@@ -392,7 +392,7 @@ static s32 xmit_xmitframes(struct adapter *padapter, struct xmit_priv *pxmitpriv
if (pxmitbuf->len > 0) {
struct xmit_frame *pframe;
- pframe = (struct xmit_frame*)pxmitbuf->priv_data;
+ pframe = (struct xmit_frame *)pxmitbuf->priv_data;
pframe->agg_num = k;
pxmitbuf->agg_num = k;
rtl8723b_update_txdesc(pframe, pframe->buf_addr);
@@ -400,8 +400,7 @@ static s32 xmit_xmitframes(struct adapter *padapter, struct xmit_priv *pxmitpriv
pxmitbuf->priv_data = NULL;
enqueue_pending_xmitbuf(pxmitpriv, pxmitbuf);
yield();
- }
- else
+ } else
rtw_free_xmitbuf(pxmitpriv, pxmitbuf);
pxmitbuf = NULL;
}
@@ -611,7 +610,8 @@ s32 rtl8723bs_hal_xmitframe_enqueue(
struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
s32 err;
- if ((err = rtw_xmitframe_enqueue(padapter, pxmitframe)) != _SUCCESS) {
+ err = rtw_xmitframe_enqueue(padapter, pxmitframe);
+ if (err != _SUCCESS) {
rtw_free_xmitframe(pxmitpriv, pxmitframe);
pxmitpriv->tx_drop++;
diff --git a/drivers/staging/rtl8723bs/include/ieee80211.h b/drivers/staging/rtl8723bs/include/ieee80211.h
index 6dc6dc73d72f..73ce63770c3c 100644
--- a/drivers/staging/rtl8723bs/include/ieee80211.h
+++ b/drivers/staging/rtl8723bs/include/ieee80211.h
@@ -1003,10 +1003,10 @@ enum ieee80211_state {
#define DEFAULT_MAX_SCAN_AGE (15 * HZ)
#define DEFAULT_FTS 2346
-#define MAC_FMT "%02x:%02x:%02x:%02x:%02x:%02x"
-#define MAC_ARG(x) ((u8 *)(x))[0], ((u8 *)(x))[1], ((u8 *)(x))[2], ((u8 *)(x))[3], ((u8 *)(x))[4], ((u8 *)(x))[5]
-#define IP_FMT "%d.%d.%d.%d"
-#define IP_ARG(x) ((u8 *)(x))[0], ((u8 *)(x))[1], ((u8 *)(x))[2], ((u8 *)(x))[3]
+#define MAC_FMT "%pM"
+#define MAC_ARG(x) (x)
+#define IP_FMT "%pI4"
+#define IP_ARG(x) (x)
extern __inline int is_multicast_mac_addr(const u8 *addr)
{
diff --git a/drivers/staging/rtl8723bs/include/osdep_service.h b/drivers/staging/rtl8723bs/include/osdep_service.h
index fdeabc1daeca..ac9ffe0e3b84 100644
--- a/drivers/staging/rtl8723bs/include/osdep_service.h
+++ b/drivers/staging/rtl8723bs/include/osdep_service.h
@@ -169,10 +169,10 @@ __inline static u32 _RND8(u32 sz)
}
#ifndef MAC_FMT
-#define MAC_FMT "%02x:%02x:%02x:%02x:%02x:%02x"
+#define MAC_FMT "%pM"
#endif
#ifndef MAC_ARG
-#define MAC_ARG(x) ((u8 *)(x))[0], ((u8 *)(x))[1], ((u8 *)(x))[2], ((u8 *)(x))[3], ((u8 *)(x))[4], ((u8 *)(x))[5]
+#define MAC_ARG(x) (x)
#endif
diff --git a/drivers/staging/rtl8723bs/include/osdep_service_linux.h b/drivers/staging/rtl8723bs/include/osdep_service_linux.h
index 486e8184b0b2..0c9b4f622fee 100644
--- a/drivers/staging/rtl8723bs/include/osdep_service_linux.h
+++ b/drivers/staging/rtl8723bs/include/osdep_service_linux.h
@@ -26,10 +26,10 @@
/* include <linux/smp_lock.h> */
#include <linux/netdevice.h>
#include <linux/skbuff.h>
- #include <asm/uaccess.h>
+ #include <linux/uaccess.h>
#include <asm/byteorder.h>
- #include <asm/atomic.h>
- #include <asm/io.h>
+ #include <linux/atomic.h>
+ #include <linux/io.h>
#include <linux/semaphore.h>
#include <linux/sem.h>
#include <linux/sched.h>
diff --git a/drivers/staging/rtl8723bs/include/rtl8192c_rf.h b/drivers/staging/rtl8723bs/include/rtl8192c_rf.h
index 0dbee562d19b..97900a31b326 100644
--- a/drivers/staging/rtl8723bs/include/rtl8192c_rf.h
+++ b/drivers/staging/rtl8723bs/include/rtl8192c_rf.h
@@ -19,19 +19,16 @@
/* */
/* RF RL6052 Series API */
/* */
-void rtl8192c_RF_ChangeTxPath(struct adapter *Adapter,
- u16 DataRate);
-void rtl8192c_PHY_RF6052SetBandwidth(
- struct adapter * Adapter,
- enum CHANNEL_WIDTH Bandwidth);
-void rtl8192c_PHY_RF6052SetCckTxPower(
- struct adapter *Adapter,
- u8* pPowerlevel);
-void rtl8192c_PHY_RF6052SetOFDMTxPower(
- struct adapter *Adapter,
- u8* pPowerLevel,
- u8 Channel);
-int PHY_RF6052_Config8192C(struct adapter * Adapter );
+void rtl8192c_RF_ChangeTxPath(struct adapter *Adapter,
+ u16 DataRate);
+void rtl8192c_PHY_RF6052SetBandwidth(struct adapter *Adapter,
+ enum CHANNEL_WIDTH Bandwidth);
+void rtl8192c_PHY_RF6052SetCckTxPower(struct adapter *Adapter,
+ u8 *pPowerlevel);
+void rtl8192c_PHY_RF6052SetOFDMTxPower(struct adapter *Adapter,
+ u8 *pPowerLevel,
+ u8 Channel);
+int PHY_RF6052_Config8192C(struct adapter *Adapter);
/*--------------------------Exported Function prototype---------------------*/
diff --git a/drivers/staging/rtl8723bs/include/rtl8723b_spec.h b/drivers/staging/rtl8723bs/include/rtl8723b_spec.h
index 8d78f4ef5438..1906ff2038f5 100644
--- a/drivers/staging/rtl8723bs/include/rtl8723b_spec.h
+++ b/drivers/staging/rtl8723bs/include/rtl8723b_spec.h
@@ -17,12 +17,11 @@
#include <autoconf.h>
-
#define HAL_NAV_UPPER_UNIT_8723B 128 /* micro-second */
/* */
/* */
-/* 0x0000h ~ 0x00FFh System Configuration */
+/* 0x0000h ~ 0x00FFh System Configuration */
/* */
/* */
#define REG_RSV_CTRL_8723B 0x001C /* 3 Byte */
@@ -42,7 +41,7 @@
/* */
/* */
-/* 0x0100h ~ 0x01FFh MACTOP General Configuration */
+/* 0x0100h ~ 0x01FFh MACTOP General Configuration */
/* */
/* */
#define REG_C2HEVT_CMD_ID_8723B 0x01A0
@@ -58,13 +57,13 @@
/* */
/* */
-/* 0x0200h ~ 0x027Fh TXDMA Configuration */
+/* 0x0200h ~ 0x027Fh TXDMA Configuration */
/* */
/* */
/* */
/* */
-/* 0x0280h ~ 0x02FFh RXDMA Configuration */
+/* 0x0280h ~ 0x02FFh RXDMA Configuration */
/* */
/* */
#define REG_RXDMA_CONTROL_8723B 0x0286 /* Control the RX DMA. */
@@ -72,7 +71,7 @@
/* */
/* */
-/* 0x0300h ~ 0x03FFh PCIe */
+/* 0x0300h ~ 0x03FFh PCIe */
/* */
/* */
#define REG_PCIE_CTRL_REG_8723B 0x0300
@@ -99,7 +98,7 @@
/* */
/* */
-/* 0x0400h ~ 0x047Fh Protocol Configuration */
+/* 0x0400h ~ 0x047Fh Protocol Configuration */
/* */
/* */
#define REG_TXPKTBUF_BCNQ_BDNY_8723B 0x0424
@@ -113,18 +112,17 @@
/* */
/* */
-/* 0x0500h ~ 0x05FFh EDCA Configuration */
+/* 0x0500h ~ 0x05FFh EDCA Configuration */
/* */
/* */
#define REG_SECONDARY_CCA_CTRL_8723B 0x0577
/* */
/* */
-/* 0x0600h ~ 0x07FFh WMAC Configuration */
+/* 0x0600h ~ 0x07FFh WMAC Configuration */
/* */
/* */
-
/* */
/* SDIO Bus Specification */
/* */
@@ -142,9 +140,8 @@
/* */
#define SDIO_REG_HCPWM1_8723B 0x025 /* HCI Current Power Mode 1 */
-
/* */
-/* 8723 Regsiter Bit and Content definition */
+/* 8723 Register Bit and Content definition */
/* */
/* 2 HSISR */
@@ -157,20 +154,19 @@
/* */
/* */
-/* 0x0100h ~ 0x01FFh MACTOP General Configuration */
+/* 0x0100h ~ 0x01FFh MACTOP General Configuration */
/* */
/* */
-
/* */
/* */
-/* 0x0200h ~ 0x027Fh TXDMA Configuration */
+/* 0x0200h ~ 0x027Fh TXDMA Configuration */
/* */
/* */
/* */
/* */
-/* 0x0280h ~ 0x02FFh RXDMA Configuration */
+/* 0x0280h ~ 0x02FFh RXDMA Configuration */
/* */
/* */
#define BIT_USB_RXDMA_AGG_EN BIT(31)
@@ -184,7 +180,7 @@
/* */
/* */
-/* 0x0400h ~ 0x047Fh Protocol Configuration */
+/* 0x0400h ~ 0x047Fh Protocol Configuration */
/* */
/* */
@@ -195,19 +191,18 @@
/* */
/* */
-/* 0x0500h ~ 0x05FFh EDCA Configuration */
+/* 0x0500h ~ 0x05FFh EDCA Configuration */
/* */
/* */
/* */
/* */
-/* 0x0600h ~ 0x07FFh WMAC Configuration */
+/* 0x0600h ~ 0x07FFh WMAC Configuration */
/* */
/* */
#define EEPROM_RF_GAIN_OFFSET 0xC1
#define EEPROM_RF_GAIN_VAL 0x1F6
-
/* */
/* 8195 IMR/ISR bits (offset 0xB0, 8bits) */
/* */
@@ -246,13 +241,13 @@
#define IMR_BCNDMAINT3_8723B BIT23 /* Beacon DMA Interrupt 3 */
#define IMR_BCNDMAINT2_8723B BIT22 /* Beacon DMA Interrupt 2 */
#define IMR_BCNDMAINT1_8723B BIT21 /* Beacon DMA Interrupt 1 */
-#define IMR_BCNDOK7_8723B BIT20 /* Beacon Queue DMA OK Interrup 7 */
-#define IMR_BCNDOK6_8723B BIT19 /* Beacon Queue DMA OK Interrup 6 */
-#define IMR_BCNDOK5_8723B BIT18 /* Beacon Queue DMA OK Interrup 5 */
-#define IMR_BCNDOK4_8723B BIT17 /* Beacon Queue DMA OK Interrup 4 */
-#define IMR_BCNDOK3_8723B BIT16 /* Beacon Queue DMA OK Interrup 3 */
-#define IMR_BCNDOK2_8723B BIT15 /* Beacon Queue DMA OK Interrup 2 */
-#define IMR_BCNDOK1_8723B BIT14 /* Beacon Queue DMA OK Interrup 1 */
+#define IMR_BCNDOK7_8723B BIT20 /* Beacon Queue DMA OK Interrupt 7 */
+#define IMR_BCNDOK6_8723B BIT19 /* Beacon Queue DMA OK Interrupt 6 */
+#define IMR_BCNDOK5_8723B BIT18 /* Beacon Queue DMA OK Interrupt 5 */
+#define IMR_BCNDOK4_8723B BIT17 /* Beacon Queue DMA OK Interrupt 4 */
+#define IMR_BCNDOK3_8723B BIT16 /* Beacon Queue DMA OK Interrupt 3 */
+#define IMR_BCNDOK2_8723B BIT15 /* Beacon Queue DMA OK Interrupt 2 */
+#define IMR_BCNDOK1_8723B BIT14 /* Beacon Queue DMA OK Interrupt 1 */
#define IMR_ATIMEND_E_8723B BIT13 /* ATIM Window End Extension for Win7 */
#define IMR_TXERR_8723B BIT11 /* Tx Error Flag Interrupt Status, write 1 clear. */
#define IMR_RXERR_8723B BIT10 /* Rx Error Flag INT Status, Write 1 clear */
diff --git a/drivers/staging/rtl8723bs/os_dep/ioctl_cfg80211.c b/drivers/staging/rtl8723bs/os_dep/ioctl_cfg80211.c
index 36c3189fc4b7..bd4352fe2de3 100644
--- a/drivers/staging/rtl8723bs/os_dep/ioctl_cfg80211.c
+++ b/drivers/staging/rtl8723bs/os_dep/ioctl_cfg80211.c
@@ -2667,7 +2667,8 @@ static int rtw_cfg80211_add_monitor_if (struct adapter *padapter, char *name, st
mon_ndev->type = ARPHRD_IEEE80211_RADIOTAP;
strncpy(mon_ndev->name, name, IFNAMSIZ);
mon_ndev->name[IFNAMSIZ - 1] = 0;
- mon_ndev->destructor = rtw_ndev_destructor;
+ mon_ndev->needs_free_netdev = true;
+ mon_ndev->priv_destructor = rtw_ndev_destructor;
mon_ndev->netdev_ops = &rtw_cfg80211_monitor_if_ops;
diff --git a/drivers/staging/rtl8723bs/os_dep/ioctl_linux.c b/drivers/staging/rtl8723bs/os_dep/ioctl_linux.c
index 916741371bee..79d8383d4b9b 100644
--- a/drivers/staging/rtl8723bs/os_dep/ioctl_linux.c
+++ b/drivers/staging/rtl8723bs/os_dep/ioctl_linux.c
@@ -766,7 +766,7 @@ static int wpa_set_encryption(struct net_device *dev, struct ieee_param *param,
exit:
- kfree((u8 *)pwep);
+ kfree(pwep);
return ret;
}
@@ -2500,7 +2500,7 @@ static int rtw_wx_set_enc_ext(struct net_device *dev,
ret = wpa_set_encryption(dev, param, param_len);
exit:
- kfree((u8 *)param);
+ kfree(param);
return ret;
}
@@ -3767,7 +3767,7 @@ static int wpa_supplicant_ioctl(struct net_device *dev, struct iw_point *p)
if (copy_from_user(param, p->pointer, p->length))
{
- kfree((u8 *)param);
+ kfree(param);
ret = -EFAULT;
goto out;
}
@@ -3801,7 +3801,7 @@ static int wpa_supplicant_ioctl(struct net_device *dev, struct iw_point *p)
if (ret == 0 && copy_to_user(p->pointer, param, p->length))
ret = -EFAULT;
- kfree((u8 *)param);
+ kfree(param);
out:
@@ -4130,7 +4130,7 @@ static int rtw_set_encryption(struct net_device *dev, struct ieee_param *param,
}
exit:
- kfree((u8 *)pwep);
+ kfree(pwep);
return ret;
@@ -4713,7 +4713,7 @@ static int rtw_hostapd_ioctl(struct net_device *dev, struct iw_point *p)
if (copy_from_user(param, p->pointer, p->length))
{
- kfree((u8 *)param);
+ kfree(param);
ret = -EFAULT;
goto out;
}
@@ -4817,7 +4817,7 @@ static int rtw_hostapd_ioctl(struct net_device *dev, struct iw_point *p)
ret = -EFAULT;
- kfree((u8 *)param);
+ kfree(param);
out:
diff --git a/drivers/staging/rtl8723bs/os_dep/os_intfs.c b/drivers/staging/rtl8723bs/os_dep/os_intfs.c
index f83cfc76505c..021589913681 100644
--- a/drivers/staging/rtl8723bs/os_dep/os_intfs.c
+++ b/drivers/staging/rtl8723bs/os_dep/os_intfs.c
@@ -1207,8 +1207,6 @@ void rtw_ndev_destructor(struct net_device *ndev)
if (ndev->ieee80211_ptr)
kfree((u8 *)ndev->ieee80211_ptr);
-
- free_netdev(ndev);
}
void rtw_dev_unload(struct adapter *padapter)
diff --git a/drivers/staging/rtl8723bs/os_dep/osdep_service.c b/drivers/staging/rtl8723bs/os_dep/osdep_service.c
index 02db59e8b593..aa16d1ab955b 100644
--- a/drivers/staging/rtl8723bs/os_dep/osdep_service.c
+++ b/drivers/staging/rtl8723bs/os_dep/osdep_service.c
@@ -160,7 +160,7 @@ static int isFileReadable(char *path)
oldfs = get_fs(); set_fs(get_ds());
if (1!=readFile(fp, &buf, 1))
- ret = PTR_ERR(fp);
+ ret = -EINVAL;
set_fs(oldfs);
filp_close(fp, NULL);
diff --git a/drivers/staging/rtl8723bs/os_dep/sdio_ops_linux.c b/drivers/staging/rtl8723bs/os_dep/sdio_ops_linux.c
index 33f0f83b002d..3aa3e6548fd5 100644
--- a/drivers/staging/rtl8723bs/os_dep/sdio_ops_linux.c
+++ b/drivers/staging/rtl8723bs/os_dep/sdio_ops_linux.c
@@ -272,7 +272,7 @@ u32 sd_read32(struct intf_hdl *pintfhdl, u32 addr, s32 *err)
DBG_871X(KERN_ERR "%s: (%d) addr = 0x%05x, val = 0x%x\n", __func__, *err, addr, v);
*err = 0;
- for (i = 0; i<SD_IO_TRY_CNT; i++)
+ for (i = 0; i < SD_IO_TRY_CNT; i++)
{
if (claim_needed) sdio_claim_host(func);
v = sdio_readl(func, addr, err);
@@ -294,7 +294,7 @@ u32 sd_read32(struct intf_hdl *pintfhdl, u32 addr, s32 *err)
}
}
- if (i ==SD_IO_TRY_CNT)
+ if (i == SD_IO_TRY_CNT)
DBG_871X(KERN_ERR "%s: FAIL!(%d) addr = 0x%05x, val = 0x%x, try_cnt =%d\n", __func__, *err, addr, v, i);
else
DBG_871X(KERN_ERR "%s: (%d) addr = 0x%05x, val = 0x%x, try_cnt =%d\n", __func__, *err, addr, v, i);
@@ -317,7 +317,7 @@ void sd_write8(struct intf_hdl *pintfhdl, u32 addr, u8 v, s32 *err)
if (padapter->bSurpriseRemoved) {
/* DBG_871X(" %s (padapter->bSurpriseRemoved ||adapter->pwrctrlpriv.pnp_bstop_trx)!!!\n", __func__); */
- return ;
+ return;
}
func = psdio->func;
@@ -346,7 +346,7 @@ void sd_write32(struct intf_hdl *pintfhdl, u32 addr, u32 v, s32 *err)
if (padapter->bSurpriseRemoved) {
/* DBG_871X(" %s (padapter->bSurpriseRemoved ||adapter->pwrctrlpriv.pnp_bstop_trx)!!!\n", __func__); */
- return ;
+ return;
}
func = psdio->func;
@@ -365,7 +365,7 @@ void sd_write32(struct intf_hdl *pintfhdl, u32 addr, u32 v, s32 *err)
DBG_871X(KERN_ERR "%s: (%d) addr = 0x%05x val = 0x%08x\n", __func__, *err, addr, v);
*err = 0;
- for (i = 0; i<SD_IO_TRY_CNT; i++)
+ for (i = 0; i < SD_IO_TRY_CNT; i++)
{
if (claim_needed) sdio_claim_host(func);
sdio_writel(func, v, addr, err);
@@ -386,7 +386,7 @@ void sd_write32(struct intf_hdl *pintfhdl, u32 addr, u32 v, s32 *err)
}
}
- if (i ==SD_IO_TRY_CNT)
+ if (i == SD_IO_TRY_CNT)
DBG_871X(KERN_ERR "%s: FAIL!(%d) addr = 0x%05x val = 0x%08x, try_cnt =%d\n", __func__, *err, addr, v, i);
else
DBG_871X(KERN_ERR "%s: (%d) addr = 0x%05x val = 0x%08x, try_cnt =%d\n", __func__, *err, addr, v, i);
@@ -428,7 +428,7 @@ s32 _sd_read(struct intf_hdl *pintfhdl, u32 addr, u32 cnt, void *pdata)
func = psdio->func;
- if (unlikely((cnt == 1) || (cnt ==2)))
+ if (unlikely((cnt == 1) || (cnt == 2)))
{
int i;
u8 *pbuf = (u8 *)pdata;
@@ -465,7 +465,7 @@ s32 _sd_read(struct intf_hdl *pintfhdl, u32 addr, u32 cnt, void *pdata)
*0 Success
*others Fail
*/
-s32 sd_read(struct intf_hdl * pintfhdl, u32 addr, u32 cnt, void *pdata)
+s32 sd_read(struct intf_hdl *pintfhdl, u32 addr, u32 cnt, void *pdata)
{
struct adapter *padapter;
struct dvobj_priv *psdiodev;
@@ -517,7 +517,7 @@ s32 _sd_write(struct intf_hdl *pintfhdl, u32 addr, u32 cnt, void *pdata)
struct sdio_func *func;
u32 size;
- s32 err =-EPERM;
+ s32 err = -EPERM;
padapter = pintfhdl->padapter;
psdiodev = pintfhdl->pintf_dev;
@@ -529,9 +529,9 @@ s32 _sd_write(struct intf_hdl *pintfhdl, u32 addr, u32 cnt, void *pdata)
}
func = psdio->func;
-/* size = sdio_align_size(func, cnt); */
+/* size = sdio_align_size(func, cnt); */
- if (unlikely((cnt == 1) || (cnt ==2)))
+ if (unlikely((cnt == 1) || (cnt == 2)))
{
int i;
u8 *pbuf = (u8 *)pdata;
@@ -576,7 +576,7 @@ s32 sd_write(struct intf_hdl *pintfhdl, u32 addr, u32 cnt, void *pdata)
PSDIO_DATA psdio;
struct sdio_func *func;
bool claim_needed;
- s32 err =-EPERM;
+ s32 err = -EPERM;
padapter = pintfhdl->padapter;
psdiodev = pintfhdl->pintf_dev;
diff --git a/drivers/staging/rtl8723bs/os_dep/wifi_regd.c b/drivers/staging/rtl8723bs/os_dep/wifi_regd.c
index 9c61125f5910..305e88a6b2ca 100644
--- a/drivers/staging/rtl8723bs/os_dep/wifi_regd.c
+++ b/drivers/staging/rtl8723bs/os_dep/wifi_regd.c
@@ -14,42 +14,43 @@
*/
/*
- *Only these channels all allow active
- *scan on all world regulatory domains
+ * Only these channels all allow active
+ * scan on all world regulatory domains
*/
/* 2G chan 01 - chan 11 */
#define RTW_2GHZ_CH01_11 \
- REG_RULE(2412-10, 2462+10, 40, 0, 20, 0)
+ REG_RULE(2412 - 10, 2462 + 10, 40, 0, 20, 0)
/*
- *We enable active scan on these a case
- *by case basis by regulatory domain
+ * We enable active scan on these a case
+ * by case basis by regulatory domain
*/
/* 2G chan 12 - chan 13, PASSIV SCAN */
#define RTW_2GHZ_CH12_13 \
- REG_RULE(2467-10, 2472+10, 40, 0, 20, \
+ REG_RULE(2467 - 10, 2472 + 10, 40, 0, 20, \
NL80211_RRF_PASSIVE_SCAN)
/* 2G chan 14, PASSIVS SCAN, NO OFDM (B only) */
#define RTW_2GHZ_CH14 \
- REG_RULE(2484-10, 2484+10, 40, 0, 20, \
+ REG_RULE(2484 - 10, 2484 + 10, 40, 0, 20, \
NL80211_RRF_PASSIVE_SCAN | NL80211_RRF_NO_OFDM)
static const struct ieee80211_regdomain rtw_regdom_rd = {
.n_reg_rules = 3,
.alpha2 = "99",
.reg_rules = {
- RTW_2GHZ_CH01_11,
- RTW_2GHZ_CH12_13,
- }
+ RTW_2GHZ_CH01_11,
+ RTW_2GHZ_CH12_13,
+ }
};
static int rtw_ieee80211_channel_to_frequency(int chan, int band)
{
/* see 802.11 17.3.8.3.2 and Annex J
- * there are overlapping channel numbers in 5GHz and 2GHz bands */
+ * there are overlapping channel numbers in 5GHz and 2GHz bands
+ */
/* NL80211_BAND_2GHZ */
if (chan == 14)
@@ -73,7 +74,7 @@ static void _rtw_reg_apply_flags(struct wiphy *wiphy)
u16 channel;
u32 freq;
- /* all channels disable */
+ /* all channels disable */
for (i = 0; i < NUM_NL80211_BANDS; i++) {
sband = wiphy->bands[i];
@@ -87,7 +88,7 @@ static void _rtw_reg_apply_flags(struct wiphy *wiphy)
}
}
- /* channels apply by channel plans. */
+ /* channels apply by channel plans. */
for (i = 0; i < max_chan_nums; i++) {
channel = channel_set[i].ChannelNum;
freq =
@@ -96,12 +97,10 @@ static void _rtw_reg_apply_flags(struct wiphy *wiphy)
ch = ieee80211_get_channel(wiphy, freq);
if (ch) {
- if (channel_set[i].ScanType == SCAN_PASSIVE) {
+ if (channel_set[i].ScanType == SCAN_PASSIVE)
ch->flags = IEEE80211_CHAN_NO_IR;
- }
- else {
+ else
ch->flags = 0;
- }
}
}
}
@@ -123,10 +122,11 @@ static const struct ieee80211_regdomain *_rtw_regdomain_select(struct
}
static void _rtw_regd_init_wiphy(struct rtw_regulatory *reg,
- struct wiphy *wiphy,
- void (*reg_notifier) (struct wiphy * wiphy,
- struct regulatory_request *
- request))
+ struct wiphy *wiphy,
+ void (*reg_notifier)(struct wiphy *wiphy,
+ struct
+ regulatory_request *
+ request))
{
const struct ieee80211_regdomain *regd;
@@ -144,11 +144,11 @@ static void _rtw_regd_init_wiphy(struct rtw_regulatory *reg,
}
int rtw_regd_init(struct adapter *padapter,
- void (*reg_notifier) (struct wiphy * wiphy,
+ void (*reg_notifier)(struct wiphy *wiphy,
struct regulatory_request *request))
{
- /* struct registry_priv *registrypriv = &padapter->registrypriv; */
struct wiphy *wiphy = padapter->rtw_wdev->wiphy;
+
_rtw_regd_init_wiphy(NULL, wiphy, reg_notifier);
return 0;
diff --git a/drivers/staging/rts5208/rtsx_scsi.c b/drivers/staging/rts5208/rtsx_scsi.c
index a95c5de1aa00..36b5a11f21d2 100644
--- a/drivers/staging/rts5208/rtsx_scsi.c
+++ b/drivers/staging/rts5208/rtsx_scsi.c
@@ -536,7 +536,7 @@ static int inquiry(struct scsi_cmnd *srb, struct rtsx_chip *chip)
if (sendbytes > 8) {
memcpy(buf, inquiry_buf, 8);
- memcpy(buf + 8, inquiry_string, sendbytes - 8);
+ strncpy(buf + 8, inquiry_string, sendbytes - 8);
if (pro_formatter_flag) {
/* Additional Length */
buf[4] = 0x33;
diff --git a/drivers/staging/rts5208/sd.c b/drivers/staging/rts5208/sd.c
index bdd35b611f27..c2eb072cbe1d 100644
--- a/drivers/staging/rts5208/sd.c
+++ b/drivers/staging/rts5208/sd.c
@@ -1057,7 +1057,7 @@ fail:
rtsx_write_register(chip, SD_DCMPS_CTL, DCMPS_CHANGE, 0);
rtsx_write_register(chip, SD_VP_CTL, PHASE_CHANGE, 0);
- wait_timeout(10);
+ mdelay(10);
sd_reset_dcm(chip, tune_dir);
return STATUS_FAIL;
}
@@ -5231,7 +5231,7 @@ int sd_power_off_card3v3(struct rtsx_chip *chip)
return STATUS_FAIL;
}
- wait_timeout(50);
+ mdelay(50);
}
if (chip->asic_code) {
diff --git a/drivers/staging/rts5208/xd.c b/drivers/staging/rts5208/xd.c
index 85aba05acbc1..74d36f9a4c1d 100644
--- a/drivers/staging/rts5208/xd.c
+++ b/drivers/staging/rts5208/xd.c
@@ -1268,7 +1268,7 @@ static int xd_copy_page(struct rtsx_chip *chip, u32 old_blk, u32 new_blk,
reg = 0;
rtsx_read_register(chip, XD_CTL, &reg);
if (reg & (XD_ECC1_ERROR | XD_ECC2_ERROR)) {
- wait_timeout(100);
+ mdelay(100);
if (detect_card_cd(chip,
XD_CARD) != STATUS_SUCCESS) {
diff --git a/drivers/staging/sm750fb/ddk750_chip.c b/drivers/staging/sm750fb/ddk750_chip.c
index 5e4bfb601cea..944dd25924be 100644
--- a/drivers/staging/sm750fb/ddk750_chip.c
+++ b/drivers/staging/sm750fb/ddk750_chip.c
@@ -175,7 +175,7 @@ static void set_master_clock(unsigned int frequency)
}
sm750_set_current_gate(reg);
- }
+ }
}
unsigned int ddk750_get_vm_size(void)
@@ -224,7 +224,7 @@ int ddk750_init_hw(struct initchip_param *pInitParam)
sm750_set_current_gate(reg);
if (sm750_get_chip_type() != SM750LE) {
- /* set panel pll and graphic mode via mmio_88 */
+ /* set panel pll and graphic mode via mmio_88 */
reg = peek32(VGA_CONFIGURATION);
reg |= (VGA_CONFIGURATION_PLL | VGA_CONFIGURATION_MODE);
poke32(VGA_CONFIGURATION, reg);
@@ -309,7 +309,8 @@ int ddk750_init_hw(struct initchip_param *pInitParam)
* M = {1,...,255}
* N = {2,...,15}
*/
-unsigned int sm750_calc_pll_value(unsigned int request_orig, struct pll_value *pll)
+unsigned int sm750_calc_pll_value(unsigned int request_orig,
+ struct pll_value *pll)
{
/*
* as sm750 register definition,
diff --git a/drivers/staging/sm750fb/ddk750_dvi.c b/drivers/staging/sm750fb/ddk750_dvi.c
index 171ae063f06f..87a199d6cdaf 100644
--- a/drivers/staging/sm750fb/ddk750_dvi.c
+++ b/drivers/staging/sm750fb/ddk750_dvi.c
@@ -29,26 +29,31 @@ static dvi_ctrl_device_t g_dcftSupportedDviController[] = {
#endif
};
-int dviInit(
- unsigned char edgeSelect,
- unsigned char busSelect,
- unsigned char dualEdgeClkSelect,
- unsigned char hsyncEnable,
- unsigned char vsyncEnable,
- unsigned char deskewEnable,
- unsigned char deskewSetting,
- unsigned char continuousSyncEnable,
- unsigned char pllFilterEnable,
- unsigned char pllFilterValue
- )
+int dviInit(unsigned char edgeSelect,
+ unsigned char busSelect,
+ unsigned char dualEdgeClkSelect,
+ unsigned char hsyncEnable,
+ unsigned char vsyncEnable,
+ unsigned char deskewEnable,
+ unsigned char deskewSetting,
+ unsigned char continuousSyncEnable,
+ unsigned char pllFilterEnable,
+ unsigned char pllFilterValue)
{
dvi_ctrl_device_t *pCurrentDviCtrl;
pCurrentDviCtrl = g_dcftSupportedDviController;
if (pCurrentDviCtrl->pfnInit) {
- return pCurrentDviCtrl->pfnInit(edgeSelect, busSelect, dualEdgeClkSelect, hsyncEnable,
- vsyncEnable, deskewEnable, deskewSetting, continuousSyncEnable,
- pllFilterEnable, pllFilterValue);
+ return pCurrentDviCtrl->pfnInit(edgeSelect,
+ busSelect,
+ dualEdgeClkSelect,
+ hsyncEnable,
+ vsyncEnable,
+ deskewEnable,
+ deskewSetting,
+ continuousSyncEnable,
+ pllFilterEnable,
+ pllFilterValue);
}
return -1; /* error */
}
diff --git a/drivers/staging/sm750fb/ddk750_dvi.h b/drivers/staging/sm750fb/ddk750_dvi.h
index 677939cb5130..4a8394561f76 100644
--- a/drivers/staging/sm750fb/ddk750_dvi.h
+++ b/drivers/staging/sm750fb/ddk750_dvi.h
@@ -3,17 +3,16 @@
/* dvi chip stuffs structros */
-typedef long (*PFN_DVICTRL_INIT)(
- unsigned char edgeSelect,
- unsigned char busSelect,
- unsigned char dualEdgeClkSelect,
- unsigned char hsyncEnable,
- unsigned char vsyncEnable,
- unsigned char deskewEnable,
- unsigned char deskewSetting,
- unsigned char continuousSyncEnable,
- unsigned char pllFilterEnable,
- unsigned char pllFilterValue);
+typedef long (*PFN_DVICTRL_INIT)(unsigned char edgeSelect,
+ unsigned char busSelect,
+ unsigned char dualEdgeClkSelect,
+ unsigned char hsyncEnable,
+ unsigned char vsyncEnable,
+ unsigned char deskewEnable,
+ unsigned char deskewSetting,
+ unsigned char continuousSyncEnable,
+ unsigned char pllFilterEnable,
+ unsigned char pllFilterValue);
typedef void (*PFN_DVICTRL_RESETCHIP)(void);
typedef char* (*PFN_DVICTRL_GETCHIPSTRING)(void);
@@ -42,18 +41,16 @@ typedef struct _dvi_ctrl_device_t {
#define DVI_CTRL_SII164
/* dvi functions prototype */
-int dviInit(
- unsigned char edgeSelect,
- unsigned char busSelect,
- unsigned char dualEdgeClkSelect,
- unsigned char hsyncEnable,
- unsigned char vsyncEnable,
- unsigned char deskewEnable,
- unsigned char deskewSetting,
- unsigned char continuousSyncEnable,
- unsigned char pllFilterEnable,
- unsigned char pllFilterValue
-);
+int dviInit(unsigned char edgeSelect,
+ unsigned char busSelect,
+ unsigned char dualEdgeClkSelect,
+ unsigned char hsyncEnable,
+ unsigned char vsyncEnable,
+ unsigned char deskewEnable,
+ unsigned char deskewSetting,
+ unsigned char continuousSyncEnable,
+ unsigned char pllFilterEnable,
+ unsigned char pllFilterValue);
#endif
diff --git a/drivers/staging/sm750fb/ddk750_hwi2c.c b/drivers/staging/sm750fb/ddk750_hwi2c.c
index fe814e4881f9..ec556a978a98 100644
--- a/drivers/staging/sm750fb/ddk750_hwi2c.c
+++ b/drivers/staging/sm750fb/ddk750_hwi2c.c
@@ -8,9 +8,7 @@
#define MAX_HWI2C_FIFO 16
#define HWI2C_WAIT_TIMEOUT 0xF0000
-int sm750_hw_i2c_init(
-unsigned char bus_speed_mode
-)
+int sm750_hw_i2c_init(unsigned char bus_speed_mode)
{
unsigned int value;
@@ -81,11 +79,9 @@ static long hw_i2c_wait_tx_done(void)
* Return Value:
* Total number of bytes those are actually written.
*/
-static unsigned int hw_i2c_write_data(
- unsigned char addr,
- unsigned int length,
- unsigned char *buf
-)
+static unsigned int hw_i2c_write_data(unsigned char addr,
+ unsigned int length,
+ unsigned char *buf)
{
unsigned char count, i;
unsigned int total_bytes = 0;
@@ -148,11 +144,9 @@ static unsigned int hw_i2c_write_data(
* Return Value:
* Total number of actual bytes read from the slave device
*/
-static unsigned int hw_i2c_read_data(
- unsigned char addr,
- unsigned int length,
- unsigned char *buf
-)
+static unsigned int hw_i2c_read_data(unsigned char addr,
+ unsigned int length,
+ unsigned char *buf)
{
unsigned char count, i;
unsigned int total_bytes = 0;
@@ -212,10 +206,7 @@ static unsigned int hw_i2c_read_data(
* Return Value:
* Register value
*/
-unsigned char sm750_hw_i2c_read_reg(
- unsigned char addr,
- unsigned char reg
-)
+unsigned char sm750_hw_i2c_read_reg(unsigned char addr, unsigned char reg)
{
unsigned char value = 0xFF;
@@ -238,11 +229,9 @@ unsigned char sm750_hw_i2c_read_reg(
* 0 - Success
* -1 - Fail
*/
-int sm750_hw_i2c_write_reg(
- unsigned char addr,
- unsigned char reg,
- unsigned char data
-)
+int sm750_hw_i2c_write_reg(unsigned char addr,
+ unsigned char reg,
+ unsigned char data)
{
unsigned char value[2];
diff --git a/drivers/staging/sm750fb/ddk750_sii164.c b/drivers/staging/sm750fb/ddk750_sii164.c
index 259006ace219..0431833de781 100644
--- a/drivers/staging/sm750fb/ddk750_sii164.c
+++ b/drivers/staging/sm750fb/ddk750_sii164.c
@@ -112,18 +112,16 @@ unsigned short sii164GetDeviceID(void)
* 0 - Success
* -1 - Fail.
*/
-long sii164InitChip(
- unsigned char edgeSelect,
- unsigned char busSelect,
- unsigned char dualEdgeClkSelect,
- unsigned char hsyncEnable,
- unsigned char vsyncEnable,
- unsigned char deskewEnable,
- unsigned char deskewSetting,
- unsigned char continuousSyncEnable,
- unsigned char pllFilterEnable,
- unsigned char pllFilterValue
-)
+long sii164InitChip(unsigned char edgeSelect,
+ unsigned char busSelect,
+ unsigned char dualEdgeClkSelect,
+ unsigned char hsyncEnable,
+ unsigned char vsyncEnable,
+ unsigned char deskewEnable,
+ unsigned char deskewSetting,
+ unsigned char continuousSyncEnable,
+ unsigned char pllFilterEnable,
+ unsigned char pllFilterValue)
{
unsigned char config;
@@ -259,7 +257,6 @@ void sii164ResetChip(void)
sii164SetPower(1);
}
-
/*
* sii164GetChipString
* This function returns a char string name of the current DVI Controller chip.
@@ -270,7 +267,6 @@ char *sii164GetChipString(void)
return gDviCtrlChipName;
}
-
/*
* sii164SetPower
* This function sets the power configuration of the DVI Controller Chip.
@@ -278,9 +274,7 @@ char *sii164GetChipString(void)
* Input:
* powerUp - Flag to set the power down or up
*/
-void sii164SetPower(
- unsigned char powerUp
-)
+void sii164SetPower(unsigned char powerUp)
{
unsigned char config;
@@ -298,18 +292,16 @@ void sii164SetPower(
}
}
-
/*
* sii164SelectHotPlugDetectionMode
* This function selects the mode of the hot plug detection.
*/
-static void sii164SelectHotPlugDetectionMode(
- sii164_hot_plug_mode_t hotPlugMode
-)
+static void sii164SelectHotPlugDetectionMode(sii164_hot_plug_mode_t hotPlugMode)
{
unsigned char detectReg;
- detectReg = i2cReadReg(SII164_I2C_ADDRESS, SII164_DETECT) & ~SII164_DETECT_MONITOR_SENSE_OUTPUT_FLAG;
+ detectReg = i2cReadReg(SII164_I2C_ADDRESS, SII164_DETECT) &
+ ~SII164_DETECT_MONITOR_SENSE_OUTPUT_FLAG;
switch (hotPlugMode) {
case SII164_HOTPLUG_DISABLE:
detectReg |= SII164_DETECT_MONITOR_SENSE_OUTPUT_HIGH;
@@ -336,9 +328,7 @@ static void sii164SelectHotPlugDetectionMode(
*
* enableHotPlug - Enable (=1) / disable (=0) Hot Plug detection
*/
-void sii164EnableHotPlugDetection(
- unsigned char enableHotPlug
-)
+void sii164EnableHotPlugDetection(unsigned char enableHotPlug)
{
unsigned char detectReg;
@@ -365,7 +355,8 @@ unsigned char sii164IsConnected(void)
{
unsigned char hotPlugValue;
- hotPlugValue = i2cReadReg(SII164_I2C_ADDRESS, SII164_DETECT) & SII164_DETECT_HOT_PLUG_STATUS_MASK;
+ hotPlugValue = i2cReadReg(SII164_I2C_ADDRESS, SII164_DETECT) &
+ SII164_DETECT_HOT_PLUG_STATUS_MASK;
if (hotPlugValue == SII164_DETECT_HOT_PLUG_STATUS_ON)
return 1;
else
@@ -384,7 +375,8 @@ unsigned char sii164CheckInterrupt(void)
{
unsigned char detectReg;
- detectReg = i2cReadReg(SII164_I2C_ADDRESS, SII164_DETECT) & SII164_DETECT_MONITOR_STATE_MASK;
+ detectReg = i2cReadReg(SII164_I2C_ADDRESS, SII164_DETECT) &
+ SII164_DETECT_MONITOR_STATE_MASK;
if (detectReg == SII164_DETECT_MONITOR_STATE_CHANGE)
return 1;
else
@@ -401,7 +393,8 @@ void sii164ClearInterrupt(void)
/* Clear the MDI interrupt */
detectReg = i2cReadReg(SII164_I2C_ADDRESS, SII164_DETECT);
- i2cWriteReg(SII164_I2C_ADDRESS, SII164_DETECT, detectReg | SII164_DETECT_MONITOR_STATE_CLEAR);
+ i2cWriteReg(SII164_I2C_ADDRESS, SII164_DETECT,
+ detectReg | SII164_DETECT_MONITOR_STATE_CLEAR);
}
#endif
diff --git a/drivers/staging/sm750fb/ddk750_sii164.h b/drivers/staging/sm750fb/ddk750_sii164.h
index 664ad089f753..6968cf532f16 100644
--- a/drivers/staging/sm750fb/ddk750_sii164.h
+++ b/drivers/staging/sm750fb/ddk750_sii164.h
@@ -13,18 +13,16 @@ typedef enum _sii164_hot_plug_mode_t {
/* Silicon Image SiI164 chip prototype */
-long sii164InitChip(
- unsigned char edgeSelect,
- unsigned char busSelect,
- unsigned char dualEdgeClkSelect,
- unsigned char hsyncEnable,
- unsigned char vsyncEnable,
- unsigned char deskewEnable,
- unsigned char deskewSetting,
- unsigned char continuousSyncEnable,
- unsigned char pllFilterEnable,
- unsigned char pllFilterValue
-);
+long sii164InitChip(unsigned char edgeSelect,
+ unsigned char busSelect,
+ unsigned char dualEdgeClkSelect,
+ unsigned char hsyncEnable,
+ unsigned char vsyncEnable,
+ unsigned char deskewEnable,
+ unsigned char deskewSetting,
+ unsigned char continuousSyncEnable,
+ unsigned char pllFilterEnable,
+ unsigned char pllFilterValue);
unsigned short sii164GetVendorID(void);
unsigned short sii164GetDeviceID(void);
diff --git a/drivers/staging/sm750fb/ddk750_swi2c.c b/drivers/staging/sm750fb/ddk750_swi2c.c
index a4ac07cd50cb..19c5ffc72b16 100644
--- a/drivers/staging/sm750fb/ddk750_swi2c.c
+++ b/drivers/staging/sm750fb/ddk750_swi2c.c
@@ -349,8 +349,7 @@ static unsigned char sw_i2c_read_byte(unsigned char ack)
* -1 - Fail to initialize the i2c
* 0 - Success
*/
-static long sm750le_i2c_init(unsigned char clk_gpio,
- unsigned char data_gpio)
+static long sm750le_i2c_init(unsigned char clk_gpio, unsigned char data_gpio)
{
int i;
@@ -388,10 +387,7 @@ static long sm750le_i2c_init(unsigned char clk_gpio,
* -1 - Fail to initialize the i2c
* 0 - Success
*/
-long sm750_sw_i2c_init(
- unsigned char clk_gpio,
- unsigned char data_gpio
-)
+long sm750_sw_i2c_init(unsigned char clk_gpio, unsigned char data_gpio)
{
int i;
@@ -448,10 +444,7 @@ long sm750_sw_i2c_init(
* Return Value:
* Register value
*/
-unsigned char sm750_sw_i2c_read_reg(
- unsigned char addr,
- unsigned char reg
-)
+unsigned char sm750_sw_i2c_read_reg(unsigned char addr, unsigned char reg)
{
unsigned char data;
@@ -488,11 +481,9 @@ unsigned char sm750_sw_i2c_read_reg(
* 0 - Success
* -1 - Fail
*/
-long sm750_sw_i2c_write_reg(
- unsigned char addr,
- unsigned char reg,
- unsigned char data
-)
+long sm750_sw_i2c_write_reg(unsigned char addr,
+ unsigned char reg,
+ unsigned char data)
{
long ret = 0;
diff --git a/drivers/staging/sm750fb/ddk750_swi2c.h b/drivers/staging/sm750fb/ddk750_swi2c.h
index 5a9466efc7bd..3b8a96d6d25a 100644
--- a/drivers/staging/sm750fb/ddk750_swi2c.h
+++ b/drivers/staging/sm750fb/ddk750_swi2c.h
@@ -28,10 +28,7 @@
* -1 - Fail to initialize the i2c
* 0 - Success
*/
-long sm750_sw_i2c_init(
- unsigned char clk_gpio,
- unsigned char data_gpio
-);
+long sm750_sw_i2c_init(unsigned char clk_gpio, unsigned char data_gpio);
/*
* This function reads the slave device's register
@@ -44,10 +41,7 @@ long sm750_sw_i2c_init(
* Return Value:
* Register value
*/
-unsigned char sm750_sw_i2c_read_reg(
- unsigned char addr,
- unsigned char reg
-);
+unsigned char sm750_sw_i2c_read_reg(unsigned char addr, unsigned char reg);
/*
* This function writes a value to the slave device's register
@@ -62,10 +56,8 @@ unsigned char sm750_sw_i2c_read_reg(
* 0 - Success
* -1 - Fail
*/
-long sm750_sw_i2c_write_reg(
- unsigned char addr,
- unsigned char reg,
- unsigned char data
-);
+long sm750_sw_i2c_write_reg(unsigned char addr,
+ unsigned char reg,
+ unsigned char data);
#endif /* _SWI2C_H_ */
diff --git a/drivers/staging/sm750fb/sm750.c b/drivers/staging/sm750fb/sm750.c
index 386d4adcd91d..3aa4128703d5 100644
--- a/drivers/staging/sm750fb/sm750.c
+++ b/drivers/staging/sm750fb/sm750.c
@@ -33,7 +33,7 @@ static int g_hwcursor = 1;
static int g_noaccel;
static int g_nomtrr;
static const char *g_fbmode[] = {NULL, NULL};
-static const char *g_def_fbmode = "800x600-16@60";
+static const char *g_def_fbmode = "1024x768-32@60";
static char *g_settings;
static int g_dualview;
static char *g_option;
@@ -112,42 +112,42 @@ static int lynxfb_ops_cursor(struct fb_info *info, struct fb_cursor *fbcursor)
cursor = &crtc->cursor;
if (fbcursor->image.width > cursor->maxW ||
- fbcursor->image.height > cursor->maxH ||
- fbcursor->image.depth > 1) {
+ fbcursor->image.height > cursor->maxH ||
+ fbcursor->image.depth > 1) {
return -ENXIO;
}
sm750_hw_cursor_disable(cursor);
if (fbcursor->set & FB_CUR_SETSIZE)
sm750_hw_cursor_setSize(cursor,
- fbcursor->image.width,
- fbcursor->image.height);
+ fbcursor->image.width,
+ fbcursor->image.height);
if (fbcursor->set & FB_CUR_SETPOS)
sm750_hw_cursor_setPos(cursor,
- fbcursor->image.dx - info->var.xoffset,
- fbcursor->image.dy - info->var.yoffset);
+ fbcursor->image.dx - info->var.xoffset,
+ fbcursor->image.dy - info->var.yoffset);
if (fbcursor->set & FB_CUR_SETCMAP) {
/* get the 16bit color of kernel means */
u16 fg, bg;
fg = ((info->cmap.red[fbcursor->image.fg_color] & 0xf800)) |
- ((info->cmap.green[fbcursor->image.fg_color] & 0xfc00) >> 5) |
- ((info->cmap.blue[fbcursor->image.fg_color] & 0xf800) >> 11);
+ ((info->cmap.green[fbcursor->image.fg_color] & 0xfc00) >> 5) |
+ ((info->cmap.blue[fbcursor->image.fg_color] & 0xf800) >> 11);
bg = ((info->cmap.red[fbcursor->image.bg_color] & 0xf800)) |
- ((info->cmap.green[fbcursor->image.bg_color] & 0xfc00) >> 5) |
- ((info->cmap.blue[fbcursor->image.bg_color] & 0xf800) >> 11);
+ ((info->cmap.green[fbcursor->image.bg_color] & 0xfc00) >> 5) |
+ ((info->cmap.blue[fbcursor->image.bg_color] & 0xf800) >> 11);
sm750_hw_cursor_setColor(cursor, fg, bg);
}
if (fbcursor->set & (FB_CUR_SETSHAPE | FB_CUR_SETIMAGE)) {
sm750_hw_cursor_setData(cursor,
- fbcursor->rop,
- fbcursor->image.data,
- fbcursor->mask);
+ fbcursor->rop,
+ fbcursor->image.data,
+ fbcursor->mask);
}
if (fbcursor->enable)
@@ -183,19 +183,19 @@ static void lynxfb_ops_fillrect(struct fb_info *info,
rop = (region->rop != ROP_COPY) ? HW_ROP2_XOR : HW_ROP2_COPY;
/*
- * If not use spin_lock,system will die if user load driver
+ * If not use spin_lock, system will die if user load driver
* and immediately unload driver frequently (dual)
+ * since they fb_count could change during the lifetime of
+ * this lock, we are holding it for all cases.
*/
- if (sm750_dev->fb_count > 1)
- spin_lock(&sm750_dev->slock);
+ spin_lock(&sm750_dev->slock);
sm750_dev->accel.de_fillrect(&sm750_dev->accel,
base, pitch, Bpp,
region->dx, region->dy,
region->width, region->height,
color, rop);
- if (sm750_dev->fb_count > 1)
- spin_unlock(&sm750_dev->slock);
+ spin_unlock(&sm750_dev->slock);
}
static void lynxfb_ops_copyarea(struct fb_info *info,
@@ -219,17 +219,17 @@ static void lynxfb_ops_copyarea(struct fb_info *info,
/*
* If not use spin_lock, system will die if user load driver
* and immediately unload driver frequently (dual)
+ * since they fb_count could change during the lifetime of
+ * this lock, we are holding it for all cases.
*/
- if (sm750_dev->fb_count > 1)
- spin_lock(&sm750_dev->slock);
+ spin_lock(&sm750_dev->slock);
sm750_dev->accel.de_copyarea(&sm750_dev->accel,
base, pitch, region->sx, region->sy,
base, pitch, Bpp, region->dx, region->dy,
region->width, region->height,
HW_ROP2_COPY);
- if (sm750_dev->fb_count > 1)
- spin_unlock(&sm750_dev->slock);
+ spin_unlock(&sm750_dev->slock);
}
static void lynxfb_ops_imageblit(struct fb_info *info,
@@ -268,9 +268,10 @@ static void lynxfb_ops_imageblit(struct fb_info *info,
/*
* If not use spin_lock, system will die if user load driver
* and immediately unload driver frequently (dual)
+ * since they fb_count could change during the lifetime of
+ * this lock, we are holding it for all cases.
*/
- if (sm750_dev->fb_count > 1)
- spin_lock(&sm750_dev->slock);
+ spin_lock(&sm750_dev->slock);
sm750_dev->accel.de_imageblit(&sm750_dev->accel,
image->data, image->width >> 3, 0,
@@ -278,8 +279,7 @@ static void lynxfb_ops_imageblit(struct fb_info *info,
image->dx, image->dy,
image->width, image->height,
fgcol, bgcol, HW_ROP2_COPY);
- if (sm750_dev->fb_count > 1)
- spin_unlock(&sm750_dev->slock);
+ spin_unlock(&sm750_dev->slock);
}
static int lynxfb_ops_pan_display(struct fb_var_screeninfo *var,
diff --git a/drivers/staging/sm750fb/sm750.h b/drivers/staging/sm750fb/sm750.h
index 5b186dafedec..4386122799b2 100644
--- a/drivers/staging/sm750fb/sm750.h
+++ b/drivers/staging/sm750fb/sm750.h
@@ -189,14 +189,22 @@ void hw_sm750_initAccel(struct sm750_dev *sm750_dev);
int hw_sm750_deWait(void);
int hw_sm750le_deWait(void);
-int hw_sm750_output_setMode(struct lynxfb_output*, struct fb_var_screeninfo*,
- struct fb_fix_screeninfo*);
-int hw_sm750_crtc_checkMode(struct lynxfb_crtc*, struct fb_var_screeninfo*);
-int hw_sm750_crtc_setMode(struct lynxfb_crtc*, struct fb_var_screeninfo*,
- struct fb_fix_screeninfo*);
-int hw_sm750_setColReg(struct lynxfb_crtc*, ushort, ushort, ushort, ushort);
-int hw_sm750_setBLANK(struct lynxfb_output*, int);
-int hw_sm750le_setBLANK(struct lynxfb_output*, int);
+int hw_sm750_output_setMode(struct lynxfb_output *output,
+ struct fb_var_screeninfo *var,
+ struct fb_fix_screeninfo *fix);
+
+int hw_sm750_crtc_checkMode(struct lynxfb_crtc *crtc,
+ struct fb_var_screeninfo *var);
+
+int hw_sm750_crtc_setMode(struct lynxfb_crtc *crtc,
+ struct fb_var_screeninfo *var,
+ struct fb_fix_screeninfo *fix);
+
+int hw_sm750_setColReg(struct lynxfb_crtc *crtc, ushort index,
+ ushort red, ushort green, ushort blue);
+
+int hw_sm750_setBLANK(struct lynxfb_output *output, int blank);
+int hw_sm750le_setBLANK(struct lynxfb_output *output, int blank);
int hw_sm750_pan_display(struct lynxfb_crtc *crtc,
const struct fb_var_screeninfo *var,
const struct fb_info *info);
diff --git a/drivers/staging/sm750fb/sm750_accel.c b/drivers/staging/sm750fb/sm750_accel.c
index 6be86e4963be..4b720cfa05de 100644
--- a/drivers/staging/sm750fb/sm750_accel.c
+++ b/drivers/staging/sm750fb/sm750_accel.c
@@ -42,10 +42,11 @@ void sm750_hw_de_init(struct lynx_accel *accel)
/* dpr1c */
reg = 0x3;
- clr = DE_STRETCH_FORMAT_PATTERN_XY | DE_STRETCH_FORMAT_PATTERN_Y_MASK |
- DE_STRETCH_FORMAT_PATTERN_X_MASK |
- DE_STRETCH_FORMAT_ADDRESSING_MASK |
- DE_STRETCH_FORMAT_SOURCE_HEIGHT_MASK;
+ clr = DE_STRETCH_FORMAT_PATTERN_XY |
+ DE_STRETCH_FORMAT_PATTERN_Y_MASK |
+ DE_STRETCH_FORMAT_PATTERN_X_MASK |
+ DE_STRETCH_FORMAT_ADDRESSING_MASK |
+ DE_STRETCH_FORMAT_SOURCE_HEIGHT_MASK;
/* DE_STRETCH bpp format need be initialized in setMode routine */
write_dpr(accel, DE_STRETCH_FORMAT,
@@ -84,9 +85,9 @@ void sm750_hw_set2dformat(struct lynx_accel *accel, int fmt)
}
int sm750_hw_fillrect(struct lynx_accel *accel,
- u32 base, u32 pitch, u32 Bpp,
- u32 x, u32 y, u32 width, u32 height,
- u32 color, u32 rop)
+ u32 base, u32 pitch, u32 Bpp,
+ u32 x, u32 y, u32 width, u32 height,
+ u32 color, u32 rop)
{
u32 deCtrl;
diff --git a/drivers/staging/sm750fb/sm750_cursor.c b/drivers/staging/sm750fb/sm750_cursor.c
index b64dc8a4a8fb..aa47a16ac75c 100644
--- a/drivers/staging/sm750fb/sm750_cursor.c
+++ b/drivers/staging/sm750fb/sm750_cursor.c
@@ -60,15 +60,13 @@ void sm750_hw_cursor_disable(struct lynx_cursor *cursor)
poke32(HWC_ADDRESS, 0);
}
-void sm750_hw_cursor_setSize(struct lynx_cursor *cursor,
- int w, int h)
+void sm750_hw_cursor_setSize(struct lynx_cursor *cursor, int w, int h)
{
cursor->w = w;
cursor->h = h;
}
-void sm750_hw_cursor_setPos(struct lynx_cursor *cursor,
- int x, int y)
+void sm750_hw_cursor_setPos(struct lynx_cursor *cursor, int x, int y)
{
u32 reg;
@@ -77,8 +75,7 @@ void sm750_hw_cursor_setPos(struct lynx_cursor *cursor,
poke32(HWC_LOCATION, reg);
}
-void sm750_hw_cursor_setColor(struct lynx_cursor *cursor,
- u32 fg, u32 bg)
+void sm750_hw_cursor_setColor(struct lynx_cursor *cursor, u32 fg, u32 bg)
{
u32 reg = (fg << HWC_COLOR_12_2_RGB565_SHIFT) &
HWC_COLOR_12_2_RGB565_MASK;
@@ -87,8 +84,8 @@ void sm750_hw_cursor_setColor(struct lynx_cursor *cursor,
poke32(HWC_COLOR_3, 0xffe0);
}
-void sm750_hw_cursor_setData(struct lynx_cursor *cursor,
- u16 rop, const u8 *pcol, const u8 *pmsk)
+void sm750_hw_cursor_setData(struct lynx_cursor *cursor, u16 rop,
+ const u8 *pcol, const u8 *pmsk)
{
int i, j, count, pitch, offset;
u8 color, mask, opr;
@@ -138,8 +135,8 @@ void sm750_hw_cursor_setData(struct lynx_cursor *cursor,
}
-void sm750_hw_cursor_setData2(struct lynx_cursor *cursor,
- u16 rop, const u8 *pcol, const u8 *pmsk)
+void sm750_hw_cursor_setData2(struct lynx_cursor *cursor, u16 rop,
+ const u8 *pcol, const u8 *pmsk)
{
int i, j, count, pitch, offset;
u8 color, mask;
diff --git a/drivers/staging/speakup/Makefile b/drivers/staging/speakup/Makefile
index c5e43a59822f..c864ea69c40d 100644
--- a/drivers/staging/speakup/Makefile
+++ b/drivers/staging/speakup/Makefile
@@ -25,6 +25,7 @@ speakup-y := \
kobjects.o \
selection.o \
serialio.o \
+ spk_ttyio.o \
synth.o \
thread.o \
varhandlers.o
diff --git a/drivers/staging/speakup/main.c b/drivers/staging/speakup/main.c
index d2ad596850f3..82e5de248947 100644
--- a/drivers/staging/speakup/main.c
+++ b/drivers/staging/speakup/main.c
@@ -1945,6 +1945,7 @@ static int handle_goto(struct vc_data *vc, u_char type, u_char ch, u_short key)
goto oops;
if (ch == 8) {
u16 wch;
+
if (num == 0)
return -1;
wch = goto_buf[--num];
@@ -2287,6 +2288,7 @@ static int vt_notifier_call(struct notifier_block *nb,
speakup_bs(vc);
} else {
u16 d = param->c;
+
speakup_con_write(vc, &d, 1);
}
break;
diff --git a/drivers/staging/speakup/serialio.c b/drivers/staging/speakup/serialio.c
index ba060d0ceca2..9cfc8142a318 100644
--- a/drivers/staging/speakup/serialio.c
+++ b/drivers/staging/speakup/serialio.c
@@ -28,11 +28,17 @@ static int timeouts;
static int spk_serial_out(struct spk_synth *in_synth, const char ch);
static void spk_serial_send_xchar(char ch);
static void spk_serial_tiocmset(unsigned int set, unsigned int clear);
+static unsigned char spk_serial_in(void);
+static unsigned char spk_serial_in_nowait(void);
+static void spk_serial_flush_buffer(void);
struct spk_io_ops spk_serial_io_ops = {
.synth_out = spk_serial_out,
.send_xchar = spk_serial_send_xchar,
.tiocmset = spk_serial_tiocmset,
+ .synth_in = spk_serial_in,
+ .synth_in_nowait = spk_serial_in_nowait,
+ .flush_buffer = spk_serial_flush_buffer,
};
EXPORT_SYMBOL_GPL(spk_serial_io_ops);
@@ -132,8 +138,8 @@ static void start_serial_interrupt(int irq)
outb(UART_MCR_DTR | UART_MCR_RTS | UART_MCR_OUT2,
speakup_info.port_tts + UART_MCR);
/* Turn on Interrupts */
- outb(UART_IER_MSI|UART_IER_RLSI|UART_IER_RDI,
- speakup_info.port_tts + UART_IER);
+ outb(UART_IER_MSI | UART_IER_RLSI | UART_IER_RDI,
+ speakup_info.port_tts + UART_IER);
inb(speakup_info.port_tts + UART_LSR);
inb(speakup_info.port_tts + UART_RX);
inb(speakup_info.port_tts + UART_IIR);
@@ -156,6 +162,7 @@ static void spk_serial_send_xchar(char ch)
static void spk_serial_tiocmset(unsigned int set, unsigned int clear)
{
int old = inb(speakup_info.port_tts + UART_MCR);
+
outb((old & ~clear) | set, speakup_info.port_tts + UART_MCR);
}
@@ -221,7 +228,8 @@ int spk_wait_for_xmitr(struct spk_synth *in_synth)
}
while (spk_serial_tx_busy()) {
if (--tmout == 0) {
- pr_warn("%s: timed out (tx busy)\n", in_synth->long_name);
+ pr_warn("%s: timed out (tx busy)\n",
+ in_synth->long_name);
timeouts++;
return 0;
}
@@ -240,7 +248,7 @@ int spk_wait_for_xmitr(struct spk_synth *in_synth)
return 1;
}
-unsigned char spk_serial_in(void)
+static unsigned char spk_serial_in(void)
{
int tmout = SPK_SERIAL_TIMEOUT;
@@ -253,9 +261,8 @@ unsigned char spk_serial_in(void)
}
return inb_p(speakup_info.port_tts + UART_RX);
}
-EXPORT_SYMBOL_GPL(spk_serial_in);
-unsigned char spk_serial_in_nowait(void)
+static unsigned char spk_serial_in_nowait(void)
{
unsigned char lsr;
@@ -264,7 +271,11 @@ unsigned char spk_serial_in_nowait(void)
return 0;
return inb_p(speakup_info.port_tts + UART_RX);
}
-EXPORT_SYMBOL_GPL(spk_serial_in_nowait);
+
+static void spk_serial_flush_buffer(void)
+{
+ /* TODO: flush the UART 16550 buffer */
+}
static int spk_serial_out(struct spk_synth *in_synth, const char ch)
{
@@ -275,7 +286,8 @@ static int spk_serial_out(struct spk_synth *in_synth, const char ch)
return 0;
}
-const char *spk_serial_synth_immediate(struct spk_synth *synth, const char *buff)
+const char *spk_serial_synth_immediate(struct spk_synth *synth,
+ const char *buff)
{
u_char ch;
diff --git a/drivers/staging/speakup/serialio.h b/drivers/staging/speakup/serialio.h
index 3ad7ff0bc3c3..89de6fff9cb2 100644
--- a/drivers/staging/speakup/serialio.h
+++ b/drivers/staging/speakup/serialio.h
@@ -8,6 +8,8 @@
#endif
#include <linux/serial_core.h>
+#include "spk_priv.h"
+
/*
* this is cut&paste from 8250.h. Get rid of the structure, the definitions
* and this whole broken driver.
@@ -21,7 +23,7 @@ struct old_serial_port {
};
/* countdown values for serial timeouts in us */
-#define SPK_SERIAL_TIMEOUT 100000
+#define SPK_SERIAL_TIMEOUT SPK_SYNTH_TIMEOUT
/* countdown values transmitter/dsr timeouts in us */
#define SPK_XMITR_TIMEOUT 100000
/* countdown values cts timeouts in us */
diff --git a/drivers/staging/speakup/speakup_acntsa.c b/drivers/staging/speakup/speakup_acntsa.c
index de67ffda7d45..0e10404e2e8c 100644
--- a/drivers/staging/speakup/speakup_acntsa.c
+++ b/drivers/staging/speakup/speakup_acntsa.c
@@ -96,13 +96,14 @@ static struct spk_synth synth_acntsa = {
.trigger = 50,
.jiffies = 30,
.full = 40000,
+ .dev_name = SYNTH_DEFAULT_DEV,
.startup = SYNTH_START,
.checkval = SYNTH_CHECK,
.vars = vars,
- .io_ops = &spk_serial_io_ops,
+ .io_ops = &spk_ttyio_ops,
.probe = synth_probe,
- .release = spk_serial_release,
- .synth_immediate = spk_serial_synth_immediate,
+ .release = spk_ttyio_release,
+ .synth_immediate = spk_ttyio_synth_immediate,
.catch_up = spk_do_catch_up,
.flush = spk_synth_flush,
.is_alive = spk_synth_is_alive_restart,
@@ -125,7 +126,7 @@ static int synth_probe(struct spk_synth *synth)
{
int failed;
- failed = spk_serial_synth_probe(synth);
+ failed = spk_ttyio_synth_probe(synth);
if (failed == 0) {
synth->synth_immediate(synth, "\033=R\r");
mdelay(100);
@@ -135,9 +136,11 @@ static int synth_probe(struct spk_synth *synth)
}
module_param_named(ser, synth_acntsa.ser, int, 0444);
+module_param_named(dev, synth_acntsa.dev_name, charp, S_IRUGO);
module_param_named(start, synth_acntsa.startup, short, 0444);
MODULE_PARM_DESC(ser, "Set the serial port for the synthesizer (0-based).");
+MODULE_PARM_DESC(dev, "Set the device e.g. ttyUSB0, for the synthesizer.");
MODULE_PARM_DESC(start, "Start the synthesizer once it is loaded.");
module_spk_synth(synth_acntsa);
diff --git a/drivers/staging/speakup/speakup_apollo.c b/drivers/staging/speakup/speakup_apollo.c
index cead8b1b1bfc..2edb56c8a559 100644
--- a/drivers/staging/speakup/speakup_apollo.c
+++ b/drivers/staging/speakup/speakup_apollo.c
@@ -22,9 +22,9 @@
#include <linux/sched.h>
#include <linux/timer.h>
#include <linux/kthread.h>
+#include <linux/serial_reg.h> /* for UART_MCR* constants */
#include "spk_priv.h"
-#include "serialio.h"
#include "speakup.h"
#define DRV_VERSION "2.21"
@@ -105,13 +105,14 @@ static struct spk_synth synth_apollo = {
.trigger = 50,
.jiffies = 50,
.full = 40000,
+ .dev_name = SYNTH_DEFAULT_DEV,
.startup = SYNTH_START,
.checkval = SYNTH_CHECK,
.vars = vars,
- .io_ops = &spk_serial_io_ops,
- .probe = spk_serial_synth_probe,
- .release = spk_serial_release,
- .synth_immediate = spk_serial_synth_immediate,
+ .io_ops = &spk_ttyio_ops,
+ .probe = spk_ttyio_synth_probe,
+ .release = spk_ttyio_release,
+ .synth_immediate = spk_ttyio_synth_immediate,
.catch_up = do_catch_up,
.flush = spk_synth_flush,
.is_alive = spk_synth_is_alive_restart,
@@ -199,9 +200,11 @@ static void do_catch_up(struct spk_synth *synth)
}
module_param_named(ser, synth_apollo.ser, int, 0444);
+module_param_named(dev, synth_apollo.dev_name, charp, S_IRUGO);
module_param_named(start, synth_apollo.startup, short, 0444);
MODULE_PARM_DESC(ser, "Set the serial port for the synthesizer (0-based).");
+MODULE_PARM_DESC(dev, "Set the device e.g. ttyUSB0, for the synthesizer.");
MODULE_PARM_DESC(start, "Start the synthesizer once it is loaded.");
module_spk_synth(synth_apollo);
diff --git a/drivers/staging/speakup/speakup_audptr.c b/drivers/staging/speakup/speakup_audptr.c
index 6880352a7b74..8ae826eba71c 100644
--- a/drivers/staging/speakup/speakup_audptr.c
+++ b/drivers/staging/speakup/speakup_audptr.c
@@ -20,7 +20,6 @@
*/
#include "spk_priv.h"
#include "speakup.h"
-#include "serialio.h"
#define DRV_VERSION "2.11"
#define SYNTH_CLEAR 0x18 /* flush synth buffer */
@@ -101,13 +100,14 @@ static struct spk_synth synth_audptr = {
.trigger = 50,
.jiffies = 30,
.full = 18000,
+ .dev_name = SYNTH_DEFAULT_DEV,
.startup = SYNTH_START,
.checkval = SYNTH_CHECK,
.vars = vars,
- .io_ops = &spk_serial_io_ops,
+ .io_ops = &spk_ttyio_ops,
.probe = synth_probe,
- .release = spk_serial_release,
- .synth_immediate = spk_serial_synth_immediate,
+ .release = spk_ttyio_release,
+ .synth_immediate = spk_ttyio_synth_immediate,
.catch_up = spk_do_catch_up,
.flush = synth_flush,
.is_alive = spk_synth_is_alive_restart,
@@ -128,6 +128,7 @@ static struct spk_synth synth_audptr = {
static void synth_flush(struct spk_synth *synth)
{
+ synth->io_ops->flush_buffer();
synth->io_ops->send_xchar(SYNTH_CLEAR);
synth->io_ops->synth_out(synth, PROCSPEECH);
}
@@ -138,11 +139,11 @@ static void synth_version(struct spk_synth *synth)
char synth_id[40] = "";
synth->synth_immediate(synth, "\x05[Q]");
- synth_id[test] = spk_serial_in();
+ synth_id[test] = synth->io_ops->synth_in();
if (synth_id[test] == 'A') {
do {
/* read version string from synth */
- synth_id[++test] = spk_serial_in();
+ synth_id[++test] = synth->io_ops->synth_in();
} while (synth_id[test] != '\n' && test < 32);
synth_id[++test] = 0x00;
}
@@ -154,7 +155,7 @@ static int synth_probe(struct spk_synth *synth)
{
int failed;
- failed = spk_serial_synth_probe(synth);
+ failed = spk_ttyio_synth_probe(synth);
if (failed == 0)
synth_version(synth);
synth->alive = !failed;
@@ -162,9 +163,11 @@ static int synth_probe(struct spk_synth *synth)
}
module_param_named(ser, synth_audptr.ser, int, 0444);
+module_param_named(dev, synth_audptr.dev_name, charp, S_IRUGO);
module_param_named(start, synth_audptr.startup, short, 0444);
MODULE_PARM_DESC(ser, "Set the serial port for the synthesizer (0-based).");
+MODULE_PARM_DESC(dev, "Set the device e.g. ttyUSB0, for the synthesizer.");
MODULE_PARM_DESC(start, "Start the synthesizer once it is loaded.");
module_spk_synth(synth_audptr);
diff --git a/drivers/staging/speakup/speakup_bns.c b/drivers/staging/speakup/speakup_bns.c
index a972a5147c6b..60bcf0df8123 100644
--- a/drivers/staging/speakup/speakup_bns.c
+++ b/drivers/staging/speakup/speakup_bns.c
@@ -93,13 +93,14 @@ static struct spk_synth synth_bns = {
.trigger = 50,
.jiffies = 50,
.full = 40000,
+ .dev_name = SYNTH_DEFAULT_DEV,
.startup = SYNTH_START,
.checkval = SYNTH_CHECK,
.vars = vars,
- .io_ops = &spk_serial_io_ops,
- .probe = spk_serial_synth_probe,
- .release = spk_serial_release,
- .synth_immediate = spk_serial_synth_immediate,
+ .io_ops = &spk_ttyio_ops,
+ .probe = spk_ttyio_synth_probe,
+ .release = spk_ttyio_release,
+ .synth_immediate = spk_ttyio_synth_immediate,
.catch_up = spk_do_catch_up,
.flush = spk_synth_flush,
.is_alive = spk_synth_is_alive_restart,
@@ -119,9 +120,11 @@ static struct spk_synth synth_bns = {
};
module_param_named(ser, synth_bns.ser, int, 0444);
+module_param_named(dev, synth_bns.dev_name, charp, S_IRUGO);
module_param_named(start, synth_bns.startup, short, 0444);
MODULE_PARM_DESC(ser, "Set the serial port for the synthesizer (0-based).");
+MODULE_PARM_DESC(dev, "Set the device e.g. ttyUSB0, for the synthesizer.");
MODULE_PARM_DESC(start, "Start the synthesizer once it is loaded.");
module_spk_synth(synth_bns);
diff --git a/drivers/staging/speakup/speakup_decext.c b/drivers/staging/speakup/speakup_decext.c
index c564bf8e1531..95f4b2116d0c 100644
--- a/drivers/staging/speakup/speakup_decext.c
+++ b/drivers/staging/speakup/speakup_decext.c
@@ -24,26 +24,22 @@
#include <linux/kthread.h>
#include "spk_priv.h"
-#include "serialio.h"
#include "speakup.h"
#define DRV_VERSION "2.14"
#define SYNTH_CLEAR 0x03
#define PROCSPEECH 0x0b
-static unsigned char last_char;
-static inline u_char get_last_char(void)
-{
- u_char avail = inb_p(speakup_info.port_tts + UART_LSR) & UART_LSR_DR;
+static volatile unsigned char last_char;
- if (avail)
- last_char = inb_p(speakup_info.port_tts + UART_RX);
- return last_char;
+static void read_buff_add(u_char ch)
+{
+ last_char = ch;
}
static inline bool synth_full(void)
{
- return get_last_char() == 0x13;
+ return last_char == 0x13;
}
static void do_catch_up(struct spk_synth *synth);
@@ -124,18 +120,19 @@ static struct spk_synth synth_decext = {
.jiffies = 50,
.full = 40000,
.flags = SF_DEC,
+ .dev_name = SYNTH_DEFAULT_DEV,
.startup = SYNTH_START,
.checkval = SYNTH_CHECK,
.vars = vars,
- .io_ops = &spk_serial_io_ops,
- .probe = spk_serial_synth_probe,
- .release = spk_serial_release,
- .synth_immediate = spk_serial_synth_immediate,
+ .io_ops = &spk_ttyio_ops,
+ .probe = spk_ttyio_synth_probe,
+ .release = spk_ttyio_release,
+ .synth_immediate = spk_ttyio_synth_immediate,
.catch_up = do_catch_up,
.flush = synth_flush,
.is_alive = spk_synth_is_alive_restart,
.synth_adjust = NULL,
- .read_buff_add = NULL,
+ .read_buff_add = read_buff_add,
.get_index = NULL,
.indexing = {
.command = NULL,
@@ -225,13 +222,16 @@ static void do_catch_up(struct spk_synth *synth)
static void synth_flush(struct spk_synth *synth)
{
in_escape = 0;
+ synth->io_ops->flush_buffer();
synth->synth_immediate(synth, "\033P;10z\033\\");
}
module_param_named(ser, synth_decext.ser, int, 0444);
+module_param_named(dev, synth_decext.dev_name, charp, S_IRUGO);
module_param_named(start, synth_decext.startup, short, 0444);
MODULE_PARM_DESC(ser, "Set the serial port for the synthesizer (0-based).");
+MODULE_PARM_DESC(dev, "Set the device e.g. ttyUSB0, for the synthesizer.");
MODULE_PARM_DESC(start, "Start the synthesizer once it is loaded.");
module_spk_synth(synth_decext);
diff --git a/drivers/staging/speakup/speakup_decpc.c b/drivers/staging/speakup/speakup_decpc.c
index 5d22c3b7edd4..7a8df7dc1e38 100644
--- a/drivers/staging/speakup/speakup_decpc.c
+++ b/drivers/staging/speakup/speakup_decpc.c
@@ -84,7 +84,7 @@
#define CTRL_last_index 0x0b00 /* get last index spoken */
#define CTRL_io_priority 0x0c00 /* change i/o priority */
#define CTRL_free_mem 0x0d00 /* get free paragraphs on module */
-#define CTRL_get_lang 0x0e00 /* return bit mask of loaded languages */
+#define CTRL_get_lang 0x0e00 /* return bitmask of loaded languages */
#define CMD_test 0x2000 /* self-test request */
#define TEST_mask 0x0F00 /* isolate test field */
#define TEST_null 0x0000 /* no test requested */
diff --git a/drivers/staging/speakup/speakup_dectlk.c b/drivers/staging/speakup/speakup_dectlk.c
index 0cdbd5e9b36b..f06995480022 100644
--- a/drivers/staging/speakup/speakup_dectlk.c
+++ b/drivers/staging/speakup/speakup_dectlk.c
@@ -27,7 +27,6 @@
#include <linux/kthread.h>
#include "speakup.h"
#include "spk_priv.h"
-#include "serialio.h"
#define DRV_VERSION "2.20"
#define SYNTH_CLEAR 0x03
@@ -42,7 +41,7 @@ static inline int synth_full(void)
static void do_catch_up(struct spk_synth *synth);
static void synth_flush(struct spk_synth *synth);
static void read_buff_add(u_char c);
-static unsigned char get_index(void);
+static unsigned char get_index(struct spk_synth *synth);
static int in_escape;
static int is_flushing;
@@ -125,15 +124,16 @@ static struct spk_synth synth_dectlk = {
.trigger = 50,
.jiffies = 50,
.full = 40000,
+ .dev_name = SYNTH_DEFAULT_DEV,
.startup = SYNTH_START,
.checkval = SYNTH_CHECK,
.vars = vars,
.default_pitch = ap_defaults,
.default_vol = g5_defaults,
- .io_ops = &spk_serial_io_ops,
- .probe = spk_serial_synth_probe,
- .release = spk_serial_release,
- .synth_immediate = spk_serial_synth_immediate,
+ .io_ops = &spk_ttyio_ops,
+ .probe = spk_ttyio_synth_probe,
+ .release = spk_ttyio_release,
+ .synth_immediate = spk_ttyio_synth_immediate,
.catch_up = do_catch_up,
.flush = synth_flush,
.is_alive = spk_synth_is_alive_restart,
@@ -163,7 +163,7 @@ static int is_indnum(u_char *ch)
static u_char lastind;
-static unsigned char get_index(void)
+static unsigned char get_index(struct spk_synth *synth)
{
u_char rv;
@@ -294,13 +294,16 @@ static void synth_flush(struct spk_synth *synth)
synth->io_ops->synth_out(synth, ']');
in_escape = 0;
is_flushing = 1;
+ synth->io_ops->flush_buffer();
synth->io_ops->synth_out(synth, SYNTH_CLEAR);
}
module_param_named(ser, synth_dectlk.ser, int, 0444);
+module_param_named(dev, synth_dectlk.dev_name, charp, S_IRUGO);
module_param_named(start, synth_dectlk.startup, short, 0444);
MODULE_PARM_DESC(ser, "Set the serial port for the synthesizer (0-based).");
+MODULE_PARM_DESC(dev, "Set the device e.g. ttyUSB0, for the synthesizer.");
MODULE_PARM_DESC(start, "Start the synthesizer once it is loaded.");
module_spk_synth(synth_dectlk);
diff --git a/drivers/staging/speakup/speakup_dtlk.c b/drivers/staging/speakup/speakup_dtlk.c
index 33180937222d..8999e3eb5c26 100644
--- a/drivers/staging/speakup/speakup_dtlk.c
+++ b/drivers/staging/speakup/speakup_dtlk.c
@@ -138,7 +138,7 @@ static struct spk_synth synth_dtlk = {
.is_alive = spk_synth_is_alive_nop,
.synth_adjust = NULL,
.read_buff_add = NULL,
- .get_index = spk_serial_in_nowait,
+ .get_index = spk_synth_get_index,
.indexing = {
.command = "\x01%di",
.lowindex = 1,
diff --git a/drivers/staging/speakup/speakup_dtlk.h b/drivers/staging/speakup/speakup_dtlk.h
index 46d885fcfb20..51ac0f2fcded 100644
--- a/drivers/staging/speakup/speakup_dtlk.h
+++ b/drivers/staging/speakup/speakup_dtlk.h
@@ -24,11 +24,11 @@
* usec later.
*/
#define TTS_ALMOST_FULL 0x08 /* mask for AF bit: When set to 1,
- * indicates that less than 300 bytes
- * are available in the TTS input
- * buffer. AF is always 0 in the PCM,
- * TGN and CVSD modes.
- */
+ * indicates that less than 300 bytes
+ * are available in the TTS input
+ * buffer. AF is always 0 in the PCM,
+ * TGN and CVSD modes.
+ */
#define TTS_ALMOST_EMPTY 0x04 /* mask for AE bit: When set to 1,
* indicates that less than 300 bytes
* are remaining in DoubleTalk's input
diff --git a/drivers/staging/speakup/speakup_dummy.c b/drivers/staging/speakup/speakup_dummy.c
index 8db7aa358f31..851953d5eefb 100644
--- a/drivers/staging/speakup/speakup_dummy.c
+++ b/drivers/staging/speakup/speakup_dummy.c
@@ -95,13 +95,14 @@ static struct spk_synth synth_dummy = {
.trigger = 50,
.jiffies = 50,
.full = 40000,
+ .dev_name = SYNTH_DEFAULT_DEV,
.startup = SYNTH_START,
.checkval = SYNTH_CHECK,
.vars = vars,
- .io_ops = &spk_serial_io_ops,
- .probe = spk_serial_synth_probe,
- .release = spk_serial_release,
- .synth_immediate = spk_serial_synth_immediate,
+ .io_ops = &spk_ttyio_ops,
+ .probe = spk_ttyio_synth_probe,
+ .release = spk_ttyio_release,
+ .synth_immediate = spk_ttyio_synth_immediate,
.catch_up = spk_do_catch_up,
.flush = spk_synth_flush,
.is_alive = spk_synth_is_alive_restart,
@@ -121,9 +122,11 @@ static struct spk_synth synth_dummy = {
};
module_param_named(ser, synth_dummy.ser, int, 0444);
+module_param_named(dev, synth_dummy.dev_name, charp, S_IRUGO);
module_param_named(start, synth_dummy.startup, short, 0444);
MODULE_PARM_DESC(ser, "Set the serial port for the synthesizer (0-based).");
+MODULE_PARM_DESC(dev, "Set the device e.g. ttyUSB0, for the synthesizer.");
MODULE_PARM_DESC(start, "Start the synthesizer once it is loaded.");
module_spk_synth(synth_dummy);
diff --git a/drivers/staging/speakup/speakup_ltlk.c b/drivers/staging/speakup/speakup_ltlk.c
index 11275f49bea4..423795f88f53 100644
--- a/drivers/staging/speakup/speakup_ltlk.c
+++ b/drivers/staging/speakup/speakup_ltlk.c
@@ -20,7 +20,6 @@
*/
#include "speakup.h"
#include "spk_priv.h"
-#include "serialio.h"
#include "speakup_dtlk.h" /* local header file for LiteTalk values */
#define DRV_VERSION "2.11"
@@ -108,19 +107,20 @@ static struct spk_synth synth_ltlk = {
.trigger = 50,
.jiffies = 50,
.full = 40000,
+ .dev_name = SYNTH_DEFAULT_DEV,
.startup = SYNTH_START,
.checkval = SYNTH_CHECK,
.vars = vars,
- .io_ops = &spk_serial_io_ops,
+ .io_ops = &spk_ttyio_ops,
.probe = synth_probe,
- .release = spk_serial_release,
- .synth_immediate = spk_serial_synth_immediate,
+ .release = spk_ttyio_release,
+ .synth_immediate = spk_ttyio_synth_immediate,
.catch_up = spk_do_catch_up,
.flush = spk_synth_flush,
.is_alive = spk_synth_is_alive_restart,
.synth_adjust = NULL,
.read_buff_add = NULL,
- .get_index = spk_serial_in_nowait,
+ .get_index = spk_synth_get_index,
.indexing = {
.command = "\x01%di",
.lowindex = 1,
@@ -141,7 +141,7 @@ static void synth_interrogate(struct spk_synth *synth)
synth->synth_immediate(synth, "\x18\x01?");
for (i = 0; i < 50; i++) {
- buf[i] = spk_serial_in();
+ buf[i] = synth->io_ops->synth_in();
if (i > 2 && buf[i] == 0x7f)
break;
}
@@ -159,7 +159,7 @@ static int synth_probe(struct spk_synth *synth)
{
int failed = 0;
- failed = spk_serial_synth_probe(synth);
+ failed = spk_ttyio_synth_probe(synth);
if (failed == 0)
synth_interrogate(synth);
synth->alive = !failed;
@@ -167,9 +167,11 @@ static int synth_probe(struct spk_synth *synth)
}
module_param_named(ser, synth_ltlk.ser, int, 0444);
+module_param_named(dev, synth_ltlk.dev_name, charp, S_IRUGO);
module_param_named(start, synth_ltlk.startup, short, 0444);
MODULE_PARM_DESC(ser, "Set the serial port for the synthesizer (0-based).");
+MODULE_PARM_DESC(dev, "Set the device e.g. ttyUSB0, for the synthesizer.");
MODULE_PARM_DESC(start, "Start the synthesizer once it is loaded.");
module_spk_synth(synth_ltlk);
diff --git a/drivers/staging/speakup/speakup_soft.c b/drivers/staging/speakup/speakup_soft.c
index e454f5685f70..d99daf69e501 100644
--- a/drivers/staging/speakup/speakup_soft.c
+++ b/drivers/staging/speakup/speakup_soft.c
@@ -36,7 +36,7 @@
static int softsynth_probe(struct spk_synth *synth);
static void softsynth_release(void);
static int softsynth_is_alive(struct spk_synth *synth);
-static unsigned char get_index(void);
+static unsigned char get_index(struct spk_synth *synth);
static struct miscdevice synth_device, synthu_device;
static int init_pos;
@@ -340,7 +340,7 @@ static unsigned int softsynth_poll(struct file *fp, struct poll_table_struct *wa
return ret;
}
-static unsigned char get_index(void)
+static unsigned char get_index(struct spk_synth *synth)
{
int rv;
diff --git a/drivers/staging/speakup/speakup_spkout.c b/drivers/staging/speakup/speakup_spkout.c
index d95c375a0736..9ca21edc42ce 100644
--- a/drivers/staging/speakup/speakup_spkout.c
+++ b/drivers/staging/speakup/speakup_spkout.c
@@ -20,7 +20,6 @@
*/
#include "spk_priv.h"
#include "speakup.h"
-#include "serialio.h"
#define DRV_VERSION "2.11"
#define SYNTH_CLEAR 0x18
@@ -99,19 +98,20 @@ static struct spk_synth synth_spkout = {
.trigger = 50,
.jiffies = 50,
.full = 40000,
+ .dev_name = SYNTH_DEFAULT_DEV,
.startup = SYNTH_START,
.checkval = SYNTH_CHECK,
.vars = vars,
- .io_ops = &spk_serial_io_ops,
- .probe = spk_serial_synth_probe,
- .release = spk_serial_release,
- .synth_immediate = spk_serial_synth_immediate,
+ .io_ops = &spk_ttyio_ops,
+ .probe = spk_ttyio_synth_probe,
+ .release = spk_ttyio_release,
+ .synth_immediate = spk_ttyio_synth_immediate,
.catch_up = spk_do_catch_up,
.flush = synth_flush,
.is_alive = spk_synth_is_alive_restart,
.synth_adjust = NULL,
.read_buff_add = NULL,
- .get_index = spk_serial_in_nowait,
+ .get_index = spk_synth_get_index,
.indexing = {
.command = "\x05[%c",
.lowindex = 1,
@@ -126,13 +126,16 @@ static struct spk_synth synth_spkout = {
static void synth_flush(struct spk_synth *synth)
{
+ synth->io_ops->flush_buffer();
synth->io_ops->send_xchar(SYNTH_CLEAR);
}
module_param_named(ser, synth_spkout.ser, int, 0444);
+module_param_named(dev, synth_spkout.dev_name, charp, S_IRUGO);
module_param_named(start, synth_spkout.startup, short, 0444);
MODULE_PARM_DESC(ser, "Set the serial port for the synthesizer (0-based).");
+MODULE_PARM_DESC(dev, "Set the device e.g. ttyUSB0, for the synthesizer.");
MODULE_PARM_DESC(start, "Start the synthesizer once it is loaded.");
module_spk_synth(synth_spkout);
diff --git a/drivers/staging/speakup/speakup_txprt.c b/drivers/staging/speakup/speakup_txprt.c
index 3f531fb99fd3..831ee404e7a1 100644
--- a/drivers/staging/speakup/speakup_txprt.c
+++ b/drivers/staging/speakup/speakup_txprt.c
@@ -92,13 +92,14 @@ static struct spk_synth synth_txprt = {
.trigger = 50,
.jiffies = 50,
.full = 40000,
+ .dev_name = SYNTH_DEFAULT_DEV,
.startup = SYNTH_START,
.checkval = SYNTH_CHECK,
.vars = vars,
- .io_ops = &spk_serial_io_ops,
- .probe = spk_serial_synth_probe,
- .release = spk_serial_release,
- .synth_immediate = spk_serial_synth_immediate,
+ .io_ops = &spk_ttyio_ops,
+ .probe = spk_ttyio_synth_probe,
+ .release = spk_ttyio_release,
+ .synth_immediate = spk_ttyio_synth_immediate,
.catch_up = spk_do_catch_up,
.flush = spk_synth_flush,
.is_alive = spk_synth_is_alive_restart,
@@ -118,9 +119,11 @@ static struct spk_synth synth_txprt = {
};
module_param_named(ser, synth_txprt.ser, int, 0444);
+module_param_named(dev, synth_txprt.dev_name, charp, S_IRUGO);
module_param_named(start, synth_txprt.startup, short, 0444);
MODULE_PARM_DESC(ser, "Set the serial port for the synthesizer (0-based).");
+MODULE_PARM_DESC(dev, "Set the device e.g. ttyUSB0, for the synthesizer.");
MODULE_PARM_DESC(start, "Start the synthesizer once it is loaded.");
module_spk_synth(synth_txprt);
diff --git a/drivers/staging/speakup/spk_priv.h b/drivers/staging/speakup/spk_priv.h
index 995f586bddcd..87b6a0a4c54d 100644
--- a/drivers/staging/speakup/spk_priv.h
+++ b/drivers/staging/speakup/spk_priv.h
@@ -39,13 +39,15 @@
#endif
#define KT_SPKUP 15
+#define SPK_SYNTH_TIMEOUT 100000 /* in micro-seconds */
+#define SYNTH_DEFAULT_DEV "ttyS0"
+#define SYNTH_DEFAULT_SER 0
const struct old_serial_port *spk_serial_init(int index);
void spk_stop_serial_interrupt(void);
int spk_wait_for_xmitr(struct spk_synth *in_synth);
-unsigned char spk_serial_in(void);
-unsigned char spk_serial_in_nowait(void);
void spk_serial_release(void);
+void spk_ttyio_release(void);
void synth_buffer_skip_nonlatin1(void);
u16 synth_buffer_getc(void);
@@ -58,9 +60,12 @@ ssize_t spk_var_store(struct kobject *kobj, struct kobj_attribute *attr,
const char *buf, size_t count);
int spk_serial_synth_probe(struct spk_synth *synth);
+int spk_ttyio_synth_probe(struct spk_synth *synth);
const char *spk_serial_synth_immediate(struct spk_synth *synth, const char *buff);
+const char *spk_ttyio_synth_immediate(struct spk_synth *synth, const char *buff);
void spk_do_catch_up(struct spk_synth *synth);
void spk_synth_flush(struct spk_synth *synth);
+unsigned char spk_synth_get_index(struct spk_synth *synth);
int spk_synth_is_alive_nop(struct spk_synth *synth);
int spk_synth_is_alive_restart(struct spk_synth *synth);
__printf(1, 2)
@@ -79,5 +84,6 @@ extern struct speakup_info_t speakup_info;
extern struct var_t synth_time_vars[];
extern struct spk_io_ops spk_serial_io_ops;
+extern struct spk_io_ops spk_ttyio_ops;
#endif
diff --git a/drivers/staging/speakup/spk_ttyio.c b/drivers/staging/speakup/spk_ttyio.c
new file mode 100644
index 000000000000..ed8e96b06ead
--- /dev/null
+++ b/drivers/staging/speakup/spk_ttyio.c
@@ -0,0 +1,320 @@
+#include <linux/types.h>
+#include <linux/tty.h>
+#include <linux/tty_flip.h>
+#include <linux/slab.h>
+
+#include "speakup.h"
+#include "spk_types.h"
+#include "spk_priv.h"
+
+#define DEV_PREFIX_LP "lp"
+
+static const char * const lp_supported[] = { "acntsa", "bns", "dummy",
+ "txprt" };
+
+struct spk_ldisc_data {
+ char buf;
+ struct semaphore sem;
+ bool buf_free;
+};
+
+static struct spk_synth *spk_ttyio_synth;
+static struct tty_struct *speakup_tty;
+
+static int ser_to_dev(int ser, dev_t *dev_no)
+{
+ if (ser < 0 || ser > (255 - 64)) {
+ pr_err("speakup: Invalid ser param. Must be between 0 and 191 inclusive.\n");
+ return -EINVAL;
+ }
+
+ *dev_no = MKDEV(4, (64 + ser));
+ return 0;
+}
+
+static int get_dev_to_use(struct spk_synth *synth, dev_t *dev_no)
+{
+ /* use ser only when dev is not specified */
+ if (strcmp(synth->dev_name, SYNTH_DEFAULT_DEV) ||
+ synth->ser == SYNTH_DEFAULT_SER) {
+ /* for /dev/lp* check if synth is supported */
+ if (strncmp(synth->dev_name, DEV_PREFIX_LP,
+ strlen(DEV_PREFIX_LP)) == 0)
+ if (match_string(lp_supported, ARRAY_SIZE(lp_supported),
+ synth->name) < 0) {
+ int i;
+
+ pr_err("speakup: lp* is only supported on:");
+ for (i = 0; i < ARRAY_SIZE(lp_supported); i++)
+ pr_cont(" %s", lp_supported[i]);
+ pr_cont("\n");
+
+ return -ENOTSUPP;
+ }
+
+ return tty_dev_name_to_number(synth->dev_name, dev_no);
+ }
+
+ return ser_to_dev(synth->ser, dev_no);
+}
+
+static int spk_ttyio_ldisc_open(struct tty_struct *tty)
+{
+ struct spk_ldisc_data *ldisc_data;
+
+ if (tty->ops->write == NULL)
+ return -EOPNOTSUPP;
+ speakup_tty = tty;
+
+ ldisc_data = kmalloc(sizeof(struct spk_ldisc_data), GFP_KERNEL);
+ if (!ldisc_data) {
+ pr_err("speakup: Failed to allocate ldisc_data.\n");
+ return -ENOMEM;
+ }
+
+ sema_init(&ldisc_data->sem, 0);
+ ldisc_data->buf_free = true;
+ speakup_tty->disc_data = ldisc_data;
+
+ return 0;
+}
+
+static void spk_ttyio_ldisc_close(struct tty_struct *tty)
+{
+ kfree(speakup_tty->disc_data);
+ speakup_tty = NULL;
+}
+
+static int spk_ttyio_receive_buf2(struct tty_struct *tty,
+ const unsigned char *cp, char *fp, int count)
+{
+ struct spk_ldisc_data *ldisc_data = tty->disc_data;
+
+ if (spk_ttyio_synth->read_buff_add) {
+ int i;
+
+ for (i = 0; i < count; i++)
+ spk_ttyio_synth->read_buff_add(cp[i]);
+
+ return count;
+ }
+
+ if (!ldisc_data->buf_free)
+ /* ttyio_in will tty_schedule_flip */
+ return 0;
+
+ /* Make sure the consumer has read buf before we have seen
+ * buf_free == true and overwrite buf */
+ mb();
+
+ ldisc_data->buf = cp[0];
+ ldisc_data->buf_free = false;
+ up(&ldisc_data->sem);
+
+ return 1;
+}
+
+static struct tty_ldisc_ops spk_ttyio_ldisc_ops = {
+ .owner = THIS_MODULE,
+ .magic = TTY_LDISC_MAGIC,
+ .name = "speakup_ldisc",
+ .open = spk_ttyio_ldisc_open,
+ .close = spk_ttyio_ldisc_close,
+ .receive_buf2 = spk_ttyio_receive_buf2,
+};
+
+static int spk_ttyio_out(struct spk_synth *in_synth, const char ch);
+static void spk_ttyio_send_xchar(char ch);
+static void spk_ttyio_tiocmset(unsigned int set, unsigned int clear);
+static unsigned char spk_ttyio_in(void);
+static unsigned char spk_ttyio_in_nowait(void);
+static void spk_ttyio_flush_buffer(void);
+
+struct spk_io_ops spk_ttyio_ops = {
+ .synth_out = spk_ttyio_out,
+ .send_xchar = spk_ttyio_send_xchar,
+ .tiocmset = spk_ttyio_tiocmset,
+ .synth_in = spk_ttyio_in,
+ .synth_in_nowait = spk_ttyio_in_nowait,
+ .flush_buffer = spk_ttyio_flush_buffer,
+};
+EXPORT_SYMBOL_GPL(spk_ttyio_ops);
+
+static inline void get_termios(struct tty_struct *tty, struct ktermios *out_termios)
+{
+ down_read(&tty->termios_rwsem);
+ *out_termios = tty->termios;
+ up_read(&tty->termios_rwsem);
+}
+
+static int spk_ttyio_initialise_ldisc(struct spk_synth *synth)
+{
+ int ret = 0;
+ struct tty_struct *tty;
+ struct ktermios tmp_termios;
+ dev_t dev;
+
+ ret = tty_register_ldisc(N_SPEAKUP, &spk_ttyio_ldisc_ops);
+ if (ret) {
+ pr_err("Error registering line discipline.\n");
+ return ret;
+ }
+
+ ret = get_dev_to_use(synth, &dev);
+ if (ret)
+ return ret;
+
+ tty = tty_open_by_driver(dev, NULL, NULL);
+ if (IS_ERR(tty))
+ return PTR_ERR(tty);
+
+ if (tty->ops->open)
+ ret = tty->ops->open(tty, NULL);
+ else
+ ret = -ENODEV;
+
+ if (ret) {
+ tty_unlock(tty);
+ return ret;
+ }
+
+ clear_bit(TTY_HUPPED, &tty->flags);
+ /* ensure hardware flow control is enabled */
+ get_termios(tty, &tmp_termios);
+ if (!(tmp_termios.c_cflag & CRTSCTS)) {
+ tmp_termios.c_cflag |= CRTSCTS;
+ tty_set_termios(tty, &tmp_termios);
+ /*
+ * check c_cflag to see if it's updated as tty_set_termios may not return
+ * error even when no tty bits are changed by the request.
+ */
+ get_termios(tty, &tmp_termios);
+ if (!(tmp_termios.c_cflag & CRTSCTS))
+ pr_warn("speakup: Failed to set hardware flow control\n");
+ }
+
+ tty_unlock(tty);
+
+ ret = tty_set_ldisc(tty, N_SPEAKUP);
+
+ return ret;
+}
+
+static int spk_ttyio_out(struct spk_synth *in_synth, const char ch)
+{
+ if (in_synth->alive && speakup_tty && speakup_tty->ops->write) {
+ int ret = speakup_tty->ops->write(speakup_tty, &ch, 1);
+
+ if (ret == 0)
+ /* No room */
+ return 0;
+ if (ret < 0) {
+ pr_warn("%s: I/O error, deactivating speakup\n", in_synth->long_name);
+ /* No synth any more, so nobody will restart TTYs, and we thus
+ * need to do it ourselves. Now that there is no synth we can
+ * let application flood anyway
+ */
+ in_synth->alive = 0;
+ speakup_start_ttys();
+ return 0;
+ }
+ return 1;
+ }
+ return 0;
+}
+
+static void spk_ttyio_send_xchar(char ch)
+{
+ speakup_tty->ops->send_xchar(speakup_tty, ch);
+}
+
+static void spk_ttyio_tiocmset(unsigned int set, unsigned int clear)
+{
+ speakup_tty->ops->tiocmset(speakup_tty, set, clear);
+}
+
+static unsigned char ttyio_in(int timeout)
+{
+ struct spk_ldisc_data *ldisc_data = speakup_tty->disc_data;
+ char rv;
+
+ if (down_timeout(&ldisc_data->sem, usecs_to_jiffies(timeout)) == -ETIME) {
+ if (timeout)
+ pr_warn("spk_ttyio: timeout (%d) while waiting for input\n",
+ timeout);
+ return 0xff;
+ }
+
+ rv = ldisc_data->buf;
+ /* Make sure we have read buf before we set buf_free to let
+ * the producer overwrite it */
+ mb();
+ ldisc_data->buf_free = true;
+ /* Let TTY push more characters */
+ tty_schedule_flip(speakup_tty->port);
+
+ return rv;
+}
+
+static unsigned char spk_ttyio_in(void)
+{
+ return ttyio_in(SPK_SYNTH_TIMEOUT);
+}
+
+static unsigned char spk_ttyio_in_nowait(void)
+{
+ u8 rv = ttyio_in(0);
+
+ return (rv == 0xff) ? 0 : rv;
+}
+
+static void spk_ttyio_flush_buffer(void)
+{
+ if (speakup_tty->ops->flush_buffer)
+ speakup_tty->ops->flush_buffer(speakup_tty);
+}
+
+int spk_ttyio_synth_probe(struct spk_synth *synth)
+{
+ int rv = spk_ttyio_initialise_ldisc(synth);
+
+ if (rv)
+ return rv;
+
+ synth->alive = 1;
+ spk_ttyio_synth = synth;
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(spk_ttyio_synth_probe);
+
+void spk_ttyio_release(void)
+{
+ if (!speakup_tty)
+ return;
+
+ tty_lock(speakup_tty);
+
+ if (speakup_tty->ops->close)
+ speakup_tty->ops->close(speakup_tty, NULL);
+
+ tty_ldisc_flush(speakup_tty);
+ tty_unlock(speakup_tty);
+ tty_ldisc_release(speakup_tty);
+}
+EXPORT_SYMBOL_GPL(spk_ttyio_release);
+
+const char *spk_ttyio_synth_immediate(struct spk_synth *synth, const char *buff)
+{
+ u_char ch;
+
+ while ((ch = *buff)) {
+ if (ch == '\n')
+ ch = synth->procspeech;
+ if (tty_write_room(speakup_tty) < 1 || !synth->io_ops->synth_out(synth, ch))
+ return buff;
+ buff++;
+ }
+ return NULL;
+}
+EXPORT_SYMBOL_GPL(spk_ttyio_synth_immediate);
diff --git a/drivers/staging/speakup/spk_types.h b/drivers/staging/speakup/spk_types.h
index c156975392c8..22f657d45e46 100644
--- a/drivers/staging/speakup/spk_types.h
+++ b/drivers/staging/speakup/spk_types.h
@@ -152,6 +152,9 @@ struct spk_io_ops {
int (*synth_out)(struct spk_synth *synth, const char ch);
void (*send_xchar)(char ch);
void (*tiocmset)(unsigned int set, unsigned int clear);
+ unsigned char (*synth_in)(void);
+ unsigned char (*synth_in_nowait)(void);
+ void (*flush_buffer)(void);
};
struct spk_synth {
@@ -166,6 +169,7 @@ struct spk_synth {
int jiffies;
int full;
int ser;
+ char *dev_name;
short flags;
short startup;
const int checkval; /* for validating a proper synth module */
@@ -182,7 +186,7 @@ struct spk_synth {
int (*is_alive)(struct spk_synth *synth);
int (*synth_adjust)(struct st_var_header *var);
void (*read_buff_add)(u_char);
- unsigned char (*get_index)(void);
+ unsigned char (*get_index)(struct spk_synth *synth);
struct synth_indexing indexing;
int alive;
struct attribute_group attributes;
diff --git a/drivers/staging/speakup/synth.c b/drivers/staging/speakup/synth.c
index 352e9eebc3de..a1ca68c76579 100644
--- a/drivers/staging/speakup/synth.c
+++ b/drivers/staging/speakup/synth.c
@@ -120,10 +120,17 @@ EXPORT_SYMBOL_GPL(spk_do_catch_up);
void spk_synth_flush(struct spk_synth *synth)
{
+ synth->io_ops->flush_buffer();
synth->io_ops->synth_out(synth, synth->clear);
}
EXPORT_SYMBOL_GPL(spk_synth_flush);
+unsigned char spk_synth_get_index(struct spk_synth *synth)
+{
+ return synth->io_ops->synth_in_nowait();
+}
+EXPORT_SYMBOL_GPL(spk_synth_get_index);
+
int spk_synth_is_alive_nop(struct spk_synth *synth)
{
synth->alive = 1;
@@ -249,7 +256,7 @@ void spk_reset_index_count(int sc)
if (first)
first = 0;
else
- synth->get_index();
+ synth->get_index(synth);
index_count = 0;
sentence_count = sc;
}
@@ -282,7 +289,7 @@ void synth_insert_next_index(int sent_num)
void spk_get_index_count(int *linecount, int *sentcount)
{
- int ind = synth->get_index();
+ int ind = synth->get_index(synth);
if (ind) {
sentence_count = ind % 10;
@@ -438,10 +445,15 @@ int synth_add(struct spk_synth *in_synth)
mutex_unlock(&spk_mutex);
return -1;
}
- synths[i++] = in_synth;
- synths[i] = NULL;
+
if (in_synth->startup)
status = do_synth_init(in_synth);
+
+ if (!status) {
+ synths[i++] = in_synth;
+ synths[i] = NULL;
+ }
+
mutex_unlock(&spk_mutex);
return status;
}
diff --git a/drivers/staging/typec/fusb302/fusb302.c b/drivers/staging/typec/fusb302/fusb302.c
index 4a356e509fe4..03a3809d18f0 100644
--- a/drivers/staging/typec/fusb302/fusb302.c
+++ b/drivers/staging/typec/fusb302/fusb302.c
@@ -1039,8 +1039,8 @@ static int fusb302_pd_send_message(struct fusb302_chip *chip,
}
/* packsym tells the FUSB302 chip that the next X bytes are payload */
buf[pos++] = FUSB302_TKN_PACKSYM | (len & 0x1F);
- buf[pos++] = msg->header & 0xFF;
- buf[pos++] = (msg->header >> 8) & 0xFF;
+ memcpy(&buf[pos], &msg->header, sizeof(msg->header));
+ pos += sizeof(msg->header);
len -= 2;
memcpy(&buf[pos], msg->payload, len);
diff --git a/drivers/staging/unisys/Documentation/overview.txt b/drivers/staging/unisys/Documentation/overview.txt
index 1146c1cf5c2a..e0466bfada2f 100644
--- a/drivers/staging/unisys/Documentation/overview.txt
+++ b/drivers/staging/unisys/Documentation/overview.txt
@@ -221,7 +221,7 @@ The following files exist under /sys/devices/visorbus<x>/vbus<x>:dev<y>:
The visorhba driver registers with visorbus as the function driver to
handle virtual scsi disk devices, specified using the
-SPAR_VHBA_CHANNEL_PROTOCOL_UUID type in the visorbus_register_visor_driver()
+VISOR_VHBA_CHANNEL_UUID type in the visorbus_register_visor_driver()
call. visorhba uses scsi_add_host() to expose a Linux block device
(e.g., /sys/block/) in the guest environment for each s-Par virtual device.
@@ -240,7 +240,7 @@ When compiled as a module, visorhba can be autoloaded by visorbus in
standard udev/systemd environments, as it includes the modules.alias
definition:
- "visorbus:"+SPAR_VHBA_CHANNEL_PROTOCOL_UUID_STR
+ "visorbus:"+VISOR_VHBA_CHANNEL_UUID_STR
i.e.:
@@ -252,7 +252,7 @@ i.e.:
The visornic driver registers with visorbus as the function driver to
handle virtual network devices, specified using the
-SPAR_VNIC_CHANNEL_PROTOCOL_UUID type in the visorbus_register_visor_driver()
+VISOR_VNIC_CHANNEL_UUID type in the visorbus_register_visor_driver()
call. visornic uses register_netdev() to expose a Linux device of class net
(e.g., /sys/class/net/) in the guest environment for each s-Par virtual
device.
@@ -270,7 +270,7 @@ When compiled as a module, visornic can be autoloaded by visorbus in
standard udev/systemd environments, as it includes the modules.alias
definition:
- "visorbus:"+SPAR_VNIC_CHANNEL_PROTOCOL_UUID_STR
+ "visorbus:"+VISOR_VNIC_CHANNEL_UUID_STR
i.e.:
@@ -282,7 +282,7 @@ i.e.:
The visorinput driver registers with visorbus as the function driver to
handle human input devices, specified using the
-SPAR_KEYBOARD_CHANNEL_PROTOCOL_UUID and SPAR_MOUSE_CHANNEL_PROTOCOL_UUID
+VISOR_KEYBOARD_CHANNEL_UUID and VISOR_MOUSE_CHANNEL_UUID
types in the visorbus_register_visor_driver() call. visorinput uses
input_register_device() to expose devices of class input
(e.g., /sys/class/input/) for virtual keyboard and virtual mouse devices.
@@ -307,8 +307,8 @@ When compiled as a module, visorinput can be autoloaded by visorbus in
standard udev/systemd environments, as it includes the modules.alias
definition:
- "visorbus:"+SPAR_MOUSE_CHANNEL_PROTOCOL_UUID_STR
- "visorbus:"+SPAR_KEYBOARD_CHANNEL_PROTOCOL_UUID_STR
+ "visorbus:"+VISOR_MOUSE_CHANNEL_UUID_STR
+ "visorbus:"+VISOR_KEYBOARD_CHANNEL_UUID_STR
i.e.:
diff --git a/drivers/staging/unisys/include/channel.h b/drivers/staging/unisys/include/channel.h
index 057421eeb1ae..692efcb38245 100644
--- a/drivers/staging/unisys/include/channel.h
+++ b/drivers/staging/unisys/include/channel.h
@@ -32,7 +32,7 @@
#define COVER(v, d) ((d) * DIV_ROUND_UP(v, d))
#endif
-#define ULTRA_CHANNEL_PROTOCOL_SIGNATURE SIGNATURE_32('E', 'C', 'N', 'L')
+#define VISOR_CHANNEL_SIGNATURE SIGNATURE_32('E', 'C', 'N', 'L')
enum channel_serverstate {
CHANNELSRV_UNINITIALIZED = 0, /* channel is in an undefined state */
@@ -59,10 +59,10 @@ enum channel_clientstate {
/* access channel anytime */
};
-#define SPAR_CHANNEL_SERVER_READY(ch) \
+#define VISOR_CHANNEL_SERVER_READY(ch) \
(readl(&(ch)->srv_state) == CHANNELSRV_READY)
-#define ULTRA_VALID_CHANNELCLI_TRANSITION(o, n) \
+#define VISOR_VALID_CHANNELCLI_TRANSITION(o, n) \
(((((o) == CHANNELCLI_DETACHED) && ((n) == CHANNELCLI_DISABLED)) || \
(((o) == CHANNELCLI_ATTACHING) && ((n) == CHANNELCLI_DISABLED)) || \
(((o) == CHANNELCLI_ATTACHED) && ((n) == CHANNELCLI_DISABLED)) || \
@@ -80,33 +80,33 @@ enum channel_clientstate {
(((o) == CHANNELCLI_BUSY) && ((n) == CHANNELCLI_OWNED)) || (0)) \
? (1) : (0))
-/* Values for ULTRA_CHANNEL_PROTOCOL.CliErrorBoot: */
+/* Values for VISORA_CHANNEL_PROTOCOL.CliErrorBoot: */
/* throttling invalid boot channel statetransition error due to client
* disabled
*/
-#define ULTRA_CLIERRORBOOT_THROTTLEMSG_DISABLED 0x01
+#define VISOR_CLIERRORBOOT_THROTTLEMSG_DISABLED 0x01
/* throttling invalid boot channel statetransition error due to client
* not attached
*/
-#define ULTRA_CLIERRORBOOT_THROTTLEMSG_NOTATTACHED 0x02
+#define VISOR_CLIERRORBOOT_THROTTLEMSG_NOTATTACHED 0x02
/* throttling invalid boot channel statetransition error due to busy channel */
-#define ULTRA_CLIERRORBOOT_THROTTLEMSG_BUSY 0x04
+#define VISOR_CLIERRORBOOT_THROTTLEMSG_BUSY 0x04
-/* Values for ULTRA_CHANNEL_PROTOCOL.Features: This define exists so
+/* Values for VISOR_CHANNEL_PROTOCOL.Features: This define exists so
* that windows guest can look at the FeatureFlags in the io channel,
* and configure the windows driver to use interrupts or not based on
* this setting. This flag is set in uislib after the
- * ULTRA_VHBA_init_channel is called. All feature bits for all
+ * VISOR_VHBA_init_channel is called. All feature bits for all
* channels should be defined here. The io channel feature bits are
* defined right here
*/
-#define ULTRA_IO_DRIVER_ENABLES_INTS (0x1ULL << 1)
-#define ULTRA_IO_CHANNEL_IS_POLLING (0x1ULL << 3)
-#define ULTRA_IO_IOVM_IS_OK_WITH_DRIVER_DISABLING_INTS (0x1ULL << 4)
-#define ULTRA_IO_DRIVER_DISABLES_INTS (0x1ULL << 5)
-#define ULTRA_IO_DRIVER_SUPPORTS_ENHANCED_RCVBUF_CHECKING (0x1ULL << 6)
+#define VISOR_DRIVER_ENABLES_INTS (0x1ULL << 1)
+#define VISOR_CHANNEL_IS_POLLING (0x1ULL << 3)
+#define VISOR_IOVM_OK_DRIVER_DISABLING_INTS (0x1ULL << 4)
+#define VISOR_DRIVER_DISABLES_INTS (0x1ULL << 5)
+#define VISOR_DRIVER_ENHANCED_RCVBUF_CHECKING (0x1ULL << 6)
/* Common Channel Header */
struct channel_header {
@@ -156,7 +156,7 @@ struct channel_header {
u8 recover_channel;
} __packed;
-#define ULTRA_CHANNEL_ENABLE_INTS (0x1ULL << 0)
+#define VISOR_CHANNEL_ENABLE_INTS (0x1ULL << 0)
/* Subheader for the Signal Type variation of the Common Channel */
struct signal_queue_header {
@@ -204,12 +204,12 @@ struct signal_queue_header {
* is used to pass the EFI_DIAG_CAPTURE_PROTOCOL needed to log messages.
*/
static inline int
-spar_check_channel(struct channel_header *ch,
- uuid_le expected_uuid,
- char *chname,
- u64 expected_min_bytes,
- u32 expected_version,
- u64 expected_signature)
+visor_check_channel(struct channel_header *ch,
+ uuid_le expected_uuid,
+ char *chname,
+ u64 expected_min_bytes,
+ u32 expected_version,
+ u64 expected_signature)
{
if (uuid_le_cmp(expected_uuid, NULL_UUID_LE) != 0) {
/* caller wants us to verify type GUID */
@@ -254,27 +254,25 @@ spar_check_channel(struct channel_header *ch,
*/
/* {414815ed-c58c-11da-95a9-00e08161165f} */
-#define SPAR_VHBA_CHANNEL_PROTOCOL_UUID \
+#define VISOR_VHBA_CHANNEL_UUID \
UUID_LE(0x414815ed, 0xc58c, 0x11da, \
0x95, 0xa9, 0x0, 0xe0, 0x81, 0x61, 0x16, 0x5f)
-static const uuid_le spar_vhba_channel_protocol_uuid =
- SPAR_VHBA_CHANNEL_PROTOCOL_UUID;
-#define SPAR_VHBA_CHANNEL_PROTOCOL_UUID_STR \
+static const uuid_le visor_vhba_channel_uuid = VISOR_VHBA_CHANNEL_UUID;
+#define VISOR_VHBA_CHANNEL_UUID_STR \
"414815ed-c58c-11da-95a9-00e08161165f"
/* {8cd5994d-c58e-11da-95a9-00e08161165f} */
-#define SPAR_VNIC_CHANNEL_PROTOCOL_UUID \
+#define VISOR_VNIC_CHANNEL_UUID \
UUID_LE(0x8cd5994d, 0xc58e, 0x11da, \
0x95, 0xa9, 0x0, 0xe0, 0x81, 0x61, 0x16, 0x5f)
-static const uuid_le spar_vnic_channel_protocol_uuid =
- SPAR_VNIC_CHANNEL_PROTOCOL_UUID;
-#define SPAR_VNIC_CHANNEL_PROTOCOL_UUID_STR \
+static const uuid_le visor_vnic_channel_uuid = VISOR_VNIC_CHANNEL_UUID;
+#define VISOR_VNIC_CHANNEL_UUID_STR \
"8cd5994d-c58e-11da-95a9-00e08161165f"
/* {72120008-4AAB-11DC-8530-444553544200} */
-#define SPAR_SIOVM_UUID \
+#define VISOR_SIOVM_UUID \
UUID_LE(0x72120008, 0x4AAB, 0x11DC, \
0x85, 0x30, 0x44, 0x45, 0x53, 0x54, 0x42, 0x00)
-static const uuid_le spar_siovm_uuid = SPAR_SIOVM_UUID;
+static const uuid_le visor_siovm_uuid = VISOR_SIOVM_UUID;
#endif
diff --git a/drivers/staging/unisys/include/iochannel.h b/drivers/staging/unisys/include/iochannel.h
index 9bde848a321c..c7cb3fbde7b2 100644
--- a/drivers/staging/unisys/include/iochannel.h
+++ b/drivers/staging/unisys/include/iochannel.h
@@ -34,10 +34,9 @@
#include <linux/dma-direction.h>
#include "channel.h"
-#define ULTRA_VHBA_CHANNEL_PROTOCOL_SIGNATURE ULTRA_CHANNEL_PROTOCOL_SIGNATURE
-#define ULTRA_VNIC_CHANNEL_PROTOCOL_SIGNATURE ULTRA_CHANNEL_PROTOCOL_SIGNATURE
-#define ULTRA_VSWITCH_CHANNEL_PROTOCOL_SIGNATURE \
- ULTRA_CHANNEL_PROTOCOL_SIGNATURE
+#define VISOR_VHBA_CHANNEL_SIGNATURE VISOR_CHANNEL_SIGNATURE
+#define VISOR_VNIC_CHANNEL_SIGNATURE VISOR_CHANNEL_SIGNATURE
+#define VISOR_VSWITCH_CHANNEL_SIGNATURE VISOR_CHANNEL_SIGNATURE
/*
* Must increment these whenever you insert or delete fields within this channel
@@ -46,21 +45,21 @@
* usually add fields to the END of the channel struct without needing to
* increment this.
*/
-#define ULTRA_VHBA_CHANNEL_PROTOCOL_VERSIONID 2
-#define ULTRA_VNIC_CHANNEL_PROTOCOL_VERSIONID 2
-#define ULTRA_VSWITCH_CHANNEL_PROTOCOL_VERSIONID 1
-
-#define SPAR_VHBA_CHANNEL_OK_CLIENT(ch) \
- (spar_check_channel(ch, spar_vhba_channel_protocol_uuid, \
- "vhba", MIN_IO_CHANNEL_SIZE, \
- ULTRA_VHBA_CHANNEL_PROTOCOL_VERSIONID, \
- ULTRA_VHBA_CHANNEL_PROTOCOL_SIGNATURE))
-
-#define SPAR_VNIC_CHANNEL_OK_CLIENT(ch) \
- (spar_check_channel(ch, spar_vnic_channel_protocol_uuid, \
- "vnic", MIN_IO_CHANNEL_SIZE, \
- ULTRA_VNIC_CHANNEL_PROTOCOL_VERSIONID, \
- ULTRA_VNIC_CHANNEL_PROTOCOL_SIGNATURE))
+#define VISOR_VHBA_CHANNEL_VERSIONID 2
+#define VISOR_VNIC_CHANNEL_VERSIONID 2
+#define VISOR_VSWITCH_CHANNEL_VERSIONID 1
+
+#define VISOR_VHBA_CHANNEL_OK_CLIENT(ch) \
+ (visor_check_channel(ch, visor_vhba_channel_uuid, \
+ "vhba", MIN_IO_CHANNEL_SIZE, \
+ VISOR_VHBA_CHANNEL_VERSIONID, \
+ VISOR_VHBA_CHANNEL_SIGNATURE))
+
+#define VISOR_VNIC_CHANNEL_OK_CLIENT(ch) \
+ (visor_check_channel(ch, visor_vnic_channel_uuid, \
+ "vnic", MIN_IO_CHANNEL_SIZE, \
+ VISOR_VNIC_CHANNEL_VERSIONID, \
+ VISOR_VNIC_CHANNEL_SIGNATURE))
/*
* Everything necessary to handle SCSI & NIC traffic between Guest Partition and
@@ -530,7 +529,7 @@ struct iochannel_vnic {
* this header there is a large region of memory which contains the command and
* response queues as specified in cmd_q and rsp_q SIGNAL_QUEUE_HEADERS.
*/
-struct spar_io_channel_protocol {
+struct visor_io_channel {
struct channel_header channel_header;
struct signal_queue_header cmd_q;
struct signal_queue_header rsp_q;
diff --git a/drivers/staging/unisys/visorbus/controlvmchannel.h b/drivers/staging/unisys/visorbus/controlvmchannel.h
index 274f72422166..ed045eff0e33 100644
--- a/drivers/staging/unisys/visorbus/controlvmchannel.h
+++ b/drivers/staging/unisys/visorbus/controlvmchannel.h
@@ -19,12 +19,11 @@
#include "channel.h"
/* {2B3C2D10-7EF5-4ad8-B966-3448B7386B3D} */
-#define SPAR_CONTROLVM_CHANNEL_PROTOCOL_UUID \
+#define VISOR_CONTROLVM_CHANNEL_UUID \
UUID_LE(0x2b3c2d10, 0x7ef5, 0x4ad8, \
0xb9, 0x66, 0x34, 0x48, 0xb7, 0x38, 0x6b, 0x3d)
-#define ULTRA_CONTROLVM_CHANNEL_PROTOCOL_SIGNATURE \
- ULTRA_CHANNEL_PROTOCOL_SIGNATURE
+#define VISOR_CONTROLVM_CHANNEL_SIGNATURE VISOR_CHANNEL_SIGNATURE
#define CONTROLVM_MESSAGE_MAX 64
/* Must increment this whenever you insert or delete fields within
@@ -33,15 +32,15 @@
* software. Note that you can usually add fields to the END of the
* channel struct withOUT needing to increment this.
*/
-#define ULTRA_CONTROLVM_CHANNEL_PROTOCOL_VERSIONID 1
+#define VISOR_CONTROLVM_CHANNEL_VERSIONID 1
-#define SPAR_CONTROLVM_CHANNEL_OK_CLIENT(ch) \
- (spar_check_channel(ch, \
- SPAR_CONTROLVM_CHANNEL_PROTOCOL_UUID, \
- "controlvm", \
- sizeof(struct spar_controlvm_channel_protocol), \
- ULTRA_CONTROLVM_CHANNEL_PROTOCOL_VERSIONID, \
- ULTRA_CONTROLVM_CHANNEL_PROTOCOL_SIGNATURE))
+#define VISOR_CONTROLVM_CHANNEL_OK_CLIENT(ch) \
+ (visor_check_channel(ch, \
+ VISOR_CONTROLVM_CHANNEL_UUID, \
+ "controlvm", \
+ sizeof(struct visor_controlvm_channel), \
+ VISOR_CONTROLVM_CHANNEL_VERSIONID, \
+ VISOR_CONTROLVM_CHANNEL_SIGNATURE))
/* Defines for various channel queues */
#define CONTROLVM_QUEUE_REQUEST 0
@@ -52,7 +51,7 @@
/* Max num of messages stored during IOVM creation to be reused after crash */
#define CONTROLVM_CRASHMSG_MAX 2
-struct spar_segment_state {
+struct visor_segment_state {
/* Bit 0: May enter other states */
u16 enabled:1;
/* Bit 1: Assigned to active partition */
@@ -76,15 +75,15 @@ struct spar_segment_state {
*/
} __packed;
-static const struct spar_segment_state segment_state_running = {
+static const struct visor_segment_state segment_state_running = {
1, 1, 1, 0, 1, 1, 1, 1
};
-static const struct spar_segment_state segment_state_paused = {
+static const struct visor_segment_state segment_state_paused = {
1, 1, 1, 0, 1, 1, 1, 0
};
-static const struct spar_segment_state segment_state_standby = {
+static const struct visor_segment_state segment_state_standby = {
1, 1, 0, 0, 1, 1, 1, 0
};
@@ -149,7 +148,7 @@ struct irq_info {
u8 reserved[3]; /* Natural alignment purposes */
} __packed;
-struct efi_spar_indication {
+struct efi_visor_indication {
u64 boot_to_fw_ui:1; /* Bit 0: Stop in uefi ui */
u64 clear_nvram:1; /* Bit 1: Clear NVRAM */
u64 clear_cmos:1; /* Bit 2: Clear CMOS */
@@ -158,9 +157,9 @@ struct efi_spar_indication {
u64 reserved:60; /* Natural alignment */
} __packed;
-enum ultra_chipset_feature {
- ULTRA_CHIPSET_FEATURE_REPLY = 0x00000001,
- ULTRA_CHIPSET_FEATURE_PARA_HOTPLUG = 0x00000002,
+enum visor_chipset_feature {
+ VISOR_CHIPSET_FEATURE_REPLY = 0x00000001,
+ VISOR_CHIPSET_FEATURE_PARA_HOTPLUG = 0x00000002,
};
/* This is the common structure that is at the beginning of every
@@ -298,13 +297,13 @@ struct controlvm_message_packet {
/* for CONTROLVM_DEVICE_RECONFIGURE */
struct {
u32 bus_no;
- struct spar_segment_state state;
+ struct visor_segment_state state;
u8 reserved[2]; /* Natural alignment purposes */
} __packed bus_change_state; /* for CONTROLVM_BUS_CHANGESTATE */
struct {
u32 bus_no;
u32 dev_no;
- struct spar_segment_state state;
+ struct visor_segment_state state;
struct {
/* =1 if message is for a physical device */
u32 phys_device:1;
@@ -317,7 +316,7 @@ struct controlvm_message_packet {
struct {
u32 bus_no;
u32 dev_no;
- struct spar_segment_state state;
+ struct visor_segment_state state;
u8 reserved[6]; /* Natural alignment purposes */
} __packed device_change_state_event;
/* for CONTROLVM_DEVICE_CHANGESTATE_EVENT */
@@ -326,7 +325,7 @@ struct controlvm_message_packet {
u32 bus_count;
/* indicates the max number of switches */
u32 switch_count;
- enum ultra_chipset_feature features;
+ enum visor_chipset_feature features;
u32 platform_number; /* Platform Number */
} __packed init_chipset; /* for CONTROLVM_CHIPSET_INIT */
struct {
@@ -349,7 +348,7 @@ struct controlvm_message {
struct controlvm_message_packet cmd;
} __packed;
-struct spar_controlvm_channel_protocol {
+struct visor_controlvm_channel {
struct channel_header header;
u64 gp_controlvm; /* guest phys addr of this channel */
u64 gp_partition_tables;/* guest phys addr of partition tables */
@@ -371,7 +370,7 @@ struct spar_controlvm_channel_protocol {
u32 message_count; /* CONTROLVM_MESSAGE_MAX */
u64 gp_smbios_table; /* guest phys addr of SMBIOS tables */
u64 gp_physical_smbios_table; /* guest phys addr of SMBIOS table */
- /* ULTRA_MAX_GUESTS_PER_SERVICE */
+ /* VISOR_MAX_GUESTS_PER_SERVICE */
char gp_reserved[2688];
/* guest physical address of EFI firmware image base */
@@ -402,11 +401,10 @@ struct spar_controlvm_channel_protocol {
u32 installation_text_id; /* Id of string to display */
/* Number of remaining installation steps (for progress bars) */
u16 installation_remaining_steps;
- /* ULTRA_TOOL_ACTIONS Installation Action field */
+ /* VISOR_TOOL_ACTIONS Installation Action field */
u8 tool_action;
u8 reserved; /* alignment */
- struct efi_spar_indication efi_spar_ind;
- struct efi_spar_indication efi_spar_ind_supported;
+ struct efi_visor_indication efi_visor_ind;
u32 sp_reserved;
/* Force signals to begin on 128-byte cache line */
u8 reserved2[28];
@@ -444,7 +442,7 @@ struct spar_controlvm_channel_protocol {
* of total_length should equal PayloadBytes. The format of the strings at
* PayloadVmOffset will take different forms depending on the message.
*/
-struct spar_controlvm_parameters_header {
+struct visor_controlvm_parameters_header {
u32 total_length;
u32 header_length;
u32 connection_offset;
diff --git a/drivers/staging/unisys/visorbus/vbuschannel.h b/drivers/staging/unisys/visorbus/vbuschannel.h
index f0ef5ecf3d7d..01d7d517dba7 100644
--- a/drivers/staging/unisys/visorbus/vbuschannel.h
+++ b/drivers/staging/unisys/visorbus/vbuschannel.h
@@ -27,13 +27,12 @@
#include "channel.h"
/* {193b331b-c58f-11da-95a9-00e08161165f} */
-#define SPAR_VBUS_CHANNEL_PROTOCOL_UUID \
+#define VISOR_VBUS_CHANNEL_UUID \
UUID_LE(0x193b331b, 0xc58f, 0x11da, \
0x95, 0xa9, 0x0, 0xe0, 0x81, 0x61, 0x16, 0x5f)
-static const uuid_le spar_vbus_channel_protocol_uuid =
- SPAR_VBUS_CHANNEL_PROTOCOL_UUID;
+static const uuid_le visor_vbus_channel_uuid = VISOR_VBUS_CHANNEL_UUID;
-#define SPAR_VBUS_CHANNEL_PROTOCOL_SIGNATURE ULTRA_CHANNEL_PROTOCOL_SIGNATURE
+#define VISOR_VBUS_CHANNEL_SIGNATURE VISOR_CHANNEL_SIGNATURE
/* Must increment this whenever you insert or delete fields within this channel
* struct. Also increment whenever you change the meaning of fields within this
@@ -41,7 +40,7 @@ static const uuid_le spar_vbus_channel_protocol_uuid =
* usually add fields to the END of the channel struct withOUT needing to
* increment this.
*/
-#define SPAR_VBUS_CHANNEL_PROTOCOL_VERSIONID 1
+#define VISOR_VBUS_CHANNEL_VERSIONID 1
/*
* An array of this struct is present in the channel area for each vbus.
@@ -49,16 +48,16 @@ static const uuid_le spar_vbus_channel_protocol_uuid =
* It is filled in by the client side to provide info about the device
* and driver from the client's perspective.
*/
-struct ultra_vbus_deviceinfo {
+struct visor_vbus_deviceinfo {
u8 devtype[16]; /* short string identifying the device type */
u8 drvname[16]; /* driver .sys file name */
u8 infostrs[96]; /* kernel version */
u8 reserved[128]; /* pad size to 256 bytes */
} __packed;
-struct spar_vbus_headerinfo {
+struct visor_vbus_headerinfo {
u32 struct_bytes; /* size of this struct in bytes */
- u32 device_info_struct_bytes; /* sizeof(ULTRA_VBUS_DEVICEINFO) */
+ u32 device_info_struct_bytes; /* sizeof(VISOR_VBUS_DEVICEINFO) */
u32 dev_info_count; /* num of items in DevInfo member */
/* (this is the allocated size) */
u32 chp_info_offset; /* byte offset from beginning of this struct */
@@ -70,15 +69,15 @@ struct spar_vbus_headerinfo {
u8 reserved[104];
} __packed;
-struct spar_vbus_channel_protocol {
+struct visor_vbus_channel {
struct channel_header channel_header; /* initialized by server */
- struct spar_vbus_headerinfo hdr_info; /* initialized by server */
+ struct visor_vbus_headerinfo hdr_info; /* initialized by server */
/* the remainder of this channel is filled in by the client */
- struct ultra_vbus_deviceinfo chp_info;
+ struct visor_vbus_deviceinfo chp_info;
/* describes client chipset device and driver */
- struct ultra_vbus_deviceinfo bus_info;
+ struct visor_vbus_deviceinfo bus_info;
/* describes client bus device and driver */
- struct ultra_vbus_deviceinfo dev_info[0];
+ struct visor_vbus_deviceinfo dev_info[0];
/* describes client device and driver for each device on the bus */
} __packed;
diff --git a/drivers/staging/unisys/visorbus/visorbus_main.c b/drivers/staging/unisys/visorbus/visorbus_main.c
index a692561c81c8..1c785dd19ddd 100644
--- a/drivers/staging/unisys/visorbus/visorbus_main.c
+++ b/drivers/staging/unisys/visorbus/visorbus_main.c
@@ -64,9 +64,9 @@ static const struct attribute_group *visorbus_dev_groups[] = {
};
/* filled in with info about parent chipset driver when we register with it */
-static struct ultra_vbus_deviceinfo chipset_driverinfo;
+static struct visor_vbus_deviceinfo chipset_driverinfo;
/* filled in with info about this driver, wrt it servicing client busses */
-static struct ultra_vbus_deviceinfo clientbus_driverinfo;
+static struct visor_vbus_deviceinfo clientbus_driverinfo;
/* list of visor_device structs, linked via .list_all */
static LIST_HEAD(list_all_bus_instances);
@@ -356,9 +356,9 @@ static const struct attribute_group *visorbus_groups[] = {
* /sys/kernel/debug/visorbus/visorbus<n>.
*/
/*
- * vbuschannel_print_devinfo() - format a struct ultra_vbus_deviceinfo
+ * vbuschannel_print_devinfo() - format a struct visor_vbus_deviceinfo
* and write it to a seq_file
- * @devinfo: the struct ultra_vbus_deviceinfo to format
+ * @devinfo: the struct visor_vbus_deviceinfo to format
* @seq: seq_file to write to
* @devix: the device index to be included in the output data, or -1 if no
* device index is to be included
@@ -366,7 +366,7 @@ static const struct attribute_group *visorbus_groups[] = {
* Reads @devInfo, and writes it in human-readable notation to @seq.
*/
static void
-vbuschannel_print_devinfo(struct ultra_vbus_deviceinfo *devinfo,
+vbuschannel_print_devinfo(struct visor_vbus_deviceinfo *devinfo,
struct seq_file *seq, int devix)
{
if (!isprint(devinfo->devtype[0]))
@@ -397,7 +397,7 @@ static int client_bus_info_debugfs_show(struct seq_file *seq, void *v)
int i;
unsigned long off;
- struct ultra_vbus_deviceinfo dev_info;
+ struct visor_vbus_deviceinfo dev_info;
if (!channel)
return 0;
@@ -407,16 +407,14 @@ static int client_bus_info_debugfs_show(struct seq_file *seq, void *v)
((vdev->name) ? (char *)(vdev->name) : ""),
vdev->chipset_bus_no);
if (visorchannel_read(channel,
- offsetof(struct spar_vbus_channel_protocol,
- chp_info),
+ offsetof(struct visor_vbus_channel, chp_info),
&dev_info, sizeof(dev_info)) >= 0)
vbuschannel_print_devinfo(&dev_info, seq, -1);
if (visorchannel_read(channel,
- offsetof(struct spar_vbus_channel_protocol,
- bus_info),
+ offsetof(struct visor_vbus_channel, bus_info),
&dev_info, sizeof(dev_info)) >= 0)
vbuschannel_print_devinfo(&dev_info, seq, -1);
- off = offsetof(struct spar_vbus_channel_protocol, dev_info);
+ off = offsetof(struct visor_vbus_channel, dev_info);
i = 0;
while (off + sizeof(dev_info) <= visorchannel_get_nbytes(channel)) {
if (visorchannel_read(channel, off, &dev_info,
@@ -684,16 +682,16 @@ remove_visor_device(struct visor_device *dev)
static int
get_vbus_header_info(struct visorchannel *chan,
- struct spar_vbus_headerinfo *hdr_info)
+ struct visor_vbus_headerinfo *hdr_info)
{
int err;
- if (!spar_check_channel(visorchannel_get_header(chan),
- spar_vbus_channel_protocol_uuid,
- "vbus",
- sizeof(struct spar_vbus_channel_protocol),
- SPAR_VBUS_CHANNEL_PROTOCOL_VERSIONID,
- SPAR_VBUS_CHANNEL_PROTOCOL_SIGNATURE))
+ if (!visor_check_channel(visorchannel_get_header(chan),
+ visor_vbus_channel_uuid,
+ "vbus",
+ sizeof(struct visor_vbus_channel),
+ VISOR_VBUS_CHANNEL_VERSIONID,
+ VISOR_VBUS_CHANNEL_SIGNATURE))
return -EINVAL;
err = visorchannel_read(chan, sizeof(struct channel_header), hdr_info,
@@ -701,11 +699,11 @@ get_vbus_header_info(struct visorchannel *chan,
if (err < 0)
return err;
- if (hdr_info->struct_bytes < sizeof(struct spar_vbus_headerinfo))
+ if (hdr_info->struct_bytes < sizeof(struct visor_vbus_headerinfo))
return -EINVAL;
if (hdr_info->device_info_struct_bytes <
- sizeof(struct ultra_vbus_deviceinfo))
+ sizeof(struct visor_vbus_deviceinfo))
return -EINVAL;
return 0;
@@ -713,7 +711,7 @@ get_vbus_header_info(struct visorchannel *chan,
/*
* write_vbus_chp_info() - write the contents of <info> to the struct
- * spar_vbus_channel_protocol.chp_info
+ * visor_vbus_channel.chp_info
* @chan: indentifies the s-Par channel that will be updated
* @hdr_info: used to find appropriate channel offset to write data
* @info: contains the information to write
@@ -726,8 +724,8 @@ get_vbus_header_info(struct visorchannel *chan,
*/
static void
write_vbus_chp_info(struct visorchannel *chan,
- struct spar_vbus_headerinfo *hdr_info,
- struct ultra_vbus_deviceinfo *info)
+ struct visor_vbus_headerinfo *hdr_info,
+ struct visor_vbus_deviceinfo *info)
{
int off = sizeof(struct channel_header) + hdr_info->chp_info_offset;
@@ -739,7 +737,7 @@ write_vbus_chp_info(struct visorchannel *chan,
/*
* write_vbus_bus_info() - write the contents of <info> to the struct
- * spar_vbus_channel_protocol.bus_info
+ * visor_vbus_channel.bus_info
* @chan: indentifies the s-Par channel that will be updated
* @hdr_info: used to find appropriate channel offset to write data
* @info: contains the information to write
@@ -752,8 +750,8 @@ write_vbus_chp_info(struct visorchannel *chan,
*/
static void
write_vbus_bus_info(struct visorchannel *chan,
- struct spar_vbus_headerinfo *hdr_info,
- struct ultra_vbus_deviceinfo *info)
+ struct visor_vbus_headerinfo *hdr_info,
+ struct visor_vbus_deviceinfo *info)
{
int off = sizeof(struct channel_header) + hdr_info->bus_info_offset;
@@ -765,7 +763,7 @@ write_vbus_bus_info(struct visorchannel *chan,
/*
* write_vbus_dev_info() - write the contents of <info> to the struct
- * spar_vbus_channel_protocol.dev_info[<devix>]
+ * visor_vbus_channel.dev_info[<devix>]
* @chan: indentifies the s-Par channel that will be updated
* @hdr_info: used to find appropriate channel offset to write data
* @info: contains the information to write
@@ -779,8 +777,8 @@ write_vbus_bus_info(struct visorchannel *chan,
*/
static void
write_vbus_dev_info(struct visorchannel *chan,
- struct spar_vbus_headerinfo *hdr_info,
- struct ultra_vbus_deviceinfo *info, unsigned int devix)
+ struct visor_vbus_headerinfo *hdr_info,
+ struct visor_vbus_deviceinfo *info, unsigned int devix)
{
int off =
(sizeof(struct channel_header) + hdr_info->dev_info_offset) +
@@ -793,10 +791,10 @@ write_vbus_dev_info(struct visorchannel *chan,
}
static void bus_device_info_init(
- struct ultra_vbus_deviceinfo *bus_device_info_ptr,
+ struct visor_vbus_deviceinfo *bus_device_info_ptr,
const char *dev_type, const char *drv_name)
{
- memset(bus_device_info_ptr, 0, sizeof(struct ultra_vbus_deviceinfo));
+ memset(bus_device_info_ptr, 0, sizeof(struct visor_vbus_deviceinfo));
snprintf(bus_device_info_ptr->devtype,
sizeof(bus_device_info_ptr->devtype),
"%s", (dev_type) ? dev_type : "unknownType");
@@ -823,9 +821,9 @@ fix_vbus_dev_info(struct visor_device *visordev)
struct visor_driver *visordrv;
u32 bus_no = visordev->chipset_bus_no;
u32 dev_no = visordev->chipset_dev_no;
- struct ultra_vbus_deviceinfo dev_info;
+ struct visor_vbus_deviceinfo dev_info;
const char *chan_type_name = NULL;
- struct spar_vbus_headerinfo *hdr_info;
+ struct visor_vbus_headerinfo *hdr_info;
if (!visordev->device.driver)
return;
@@ -833,7 +831,7 @@ fix_vbus_dev_info(struct visor_device *visordev)
bdev = visorbus_get_device_by_id(bus_no, BUS_ROOT_DEVICE, NULL);
if (!bdev)
return;
- hdr_info = (struct spar_vbus_headerinfo *)bdev->vbus_hdr_info;
+ hdr_info = (struct visor_vbus_headerinfo *)bdev->vbus_hdr_info;
if (!hdr_info)
return;
visordrv = to_visor_driver(visordev->device.driver);
@@ -981,18 +979,18 @@ int visorbus_register_visor_driver(struct visor_driver *drv)
EXPORT_SYMBOL_GPL(visorbus_register_visor_driver);
/*
- * create_bus_instance() - create a device instance for the visor bus itself
+ * visorbus_create_instance() - create a device instance for the visorbus itself
* @dev: struct visor_device indicating the bus instance
*
* Return: 0 for success, otherwise negative errno value indicating reason for
* failure
*/
static int
-create_bus_instance(struct visor_device *dev)
+visorbus_create_instance(struct visor_device *dev)
{
int id = dev->chipset_bus_no;
int err;
- struct spar_vbus_headerinfo *hdr_info;
+ struct visor_vbus_headerinfo *hdr_info;
hdr_info = kzalloc(sizeof(*hdr_info), GFP_KERNEL);
if (!hdr_info)
@@ -1032,16 +1030,16 @@ create_bus_instance(struct visor_device *dev)
err_debugfs_dir:
debugfs_remove_recursive(dev->debugfs_dir);
kfree(hdr_info);
- dev_err(&dev->device, "create_bus_instance failed: %d\n", err);
+ dev_err(&dev->device, "visorbus_create_instance failed: %d\n", err);
return err;
}
/*
- * remove_bus_instance() - remove a device instance for the visor bus itself
+ * visorbus_remove_instance() - remove a device instance for the visorbus itself
* @dev: struct visor_device indentifying the bus to remove
*/
static void
-remove_bus_instance(struct visor_device *dev)
+visorbus_remove_instance(struct visor_device *dev)
{
/*
* Note that this will result in the release method for
@@ -1061,7 +1059,7 @@ remove_bus_instance(struct visor_device *dev)
}
/*
- * remove_all_visor_devices() - remove all child visor bus device instances
+ * remove_all_visor_devices() - remove all child visorbus device instances
*/
static void
remove_all_visor_devices(void)
@@ -1077,29 +1075,29 @@ remove_all_visor_devices(void)
}
int
-chipset_bus_create(struct visor_device *dev)
+visorchipset_bus_create(struct visor_device *dev)
{
int err;
- err = create_bus_instance(dev);
+ err = visorbus_create_instance(dev);
if (err < 0)
return err;
- bus_create_response(dev, err);
+ visorbus_create_response(dev, err);
return 0;
}
void
-chipset_bus_destroy(struct visor_device *dev)
+visorchipset_bus_destroy(struct visor_device *dev)
{
- remove_bus_instance(dev);
- bus_destroy_response(dev, 0);
+ visorbus_remove_instance(dev);
+ visorbus_destroy_response(dev, 0);
}
int
-chipset_device_create(struct visor_device *dev_info)
+visorchipset_device_create(struct visor_device *dev_info)
{
int err;
@@ -1107,17 +1105,17 @@ chipset_device_create(struct visor_device *dev_info)
if (err < 0)
return err;
- device_create_response(dev_info, err);
+ visorbus_device_create_response(dev_info, err);
return 0;
}
void
-chipset_device_destroy(struct visor_device *dev_info)
+visorchipset_device_destroy(struct visor_device *dev_info)
{
remove_visor_device(dev_info);
- device_destroy_response(dev_info, 0);
+ visorbus_device_destroy_response(dev_info, 0);
}
/*
@@ -1137,7 +1135,7 @@ pause_state_change_complete(struct visor_device *dev, int status)
dev->pausing = false;
- device_pause_response(dev, status);
+ visorbus_device_pause_response(dev, status);
}
/*
@@ -1162,12 +1160,12 @@ resume_state_change_complete(struct visor_device *dev, int status)
* which will presumably want to send some sort of response to
* the initiator.
*/
- device_resume_response(dev, status);
+ visorbus_device_resume_response(dev, status);
}
/*
- * initiate_chipset_device_pause_resume() - start a pause or resume operation
- * for a visor device
+ * visorchipset_initiate_device_pause_resume() - start a pause or resume
+ * operation for a visor device
* @dev: struct visor_device identifying the device being paused or resumed
* @is_pause: true to indicate pause operation, false to indicate resume
*
@@ -1177,7 +1175,8 @@ resume_state_change_complete(struct visor_device *dev, int status)
* resume_state_change_complete().
*/
static int
-initiate_chipset_device_pause_resume(struct visor_device *dev, bool is_pause)
+visorchipset_initiate_device_pause_resume(struct visor_device *dev,
+ bool is_pause)
{
int err;
struct visor_driver *drv = NULL;
@@ -1211,7 +1210,7 @@ initiate_chipset_device_pause_resume(struct visor_device *dev, bool is_pause)
}
/**
- * chipset_device_pause() - start a pause operation for a visor device
+ * visorchipset_device_pause() - start a pause operation for a visor device
* @dev_info: struct visor_device identifying the device being paused
*
* Tell the subordinate function driver for a specific device to pause
@@ -1219,11 +1218,11 @@ initiate_chipset_device_pause_resume(struct visor_device *dev, bool is_pause)
* via a callback function; see pause_state_change_complete().
*/
int
-chipset_device_pause(struct visor_device *dev_info)
+visorchipset_device_pause(struct visor_device *dev_info)
{
int err;
- err = initiate_chipset_device_pause_resume(dev_info, true);
+ err = visorchipset_initiate_device_pause_resume(dev_info, true);
if (err < 0) {
dev_info->pausing = false;
@@ -1234,7 +1233,7 @@ chipset_device_pause(struct visor_device *dev_info)
}
/**
- * chipset_device_resume() - start a resume operation for a visor device
+ * visorchipset_device_resume() - start a resume operation for a visor device
* @dev_info: struct visor_device identifying the device being resumed
*
* Tell the subordinate function driver for a specific device to resume
@@ -1242,11 +1241,11 @@ chipset_device_pause(struct visor_device *dev_info)
* via a callback function; see resume_state_change_complete().
*/
int
-chipset_device_resume(struct visor_device *dev_info)
+visorchipset_device_resume(struct visor_device *dev_info)
{
int err;
- err = initiate_chipset_device_pause_resume(dev_info, false);
+ err = visorchipset_initiate_device_pause_resume(dev_info, false);
if (err < 0) {
dev_info->resuming = false;
@@ -1289,7 +1288,7 @@ visorbus_exit(void)
struct visor_device *dev = list_entry(listentry,
struct visor_device,
list_all);
- remove_bus_instance(dev);
+ visorbus_remove_instance(dev);
}
bus_unregister(&visorbus_type);
diff --git a/drivers/staging/unisys/visorbus/visorbus_private.h b/drivers/staging/unisys/visorbus/visorbus_private.h
index 9f030b1f589f..98a5af19189d 100644
--- a/drivers/staging/unisys/visorbus/visorbus_private.h
+++ b/drivers/staging/unisys/visorbus/visorbus_private.h
@@ -27,19 +27,19 @@
* command line
*/
-int chipset_bus_create(struct visor_device *bus_info);
-void chipset_bus_destroy(struct visor_device *bus_info);
-int chipset_device_create(struct visor_device *dev_info);
-void chipset_device_destroy(struct visor_device *dev_info);
-int chipset_device_pause(struct visor_device *dev_info);
-int chipset_device_resume(struct visor_device *dev_info);
+int visorchipset_bus_create(struct visor_device *bus_info);
+void visorchipset_bus_destroy(struct visor_device *bus_info);
+int visorchipset_device_create(struct visor_device *dev_info);
+void visorchipset_device_destroy(struct visor_device *dev_info);
+int visorchipset_device_pause(struct visor_device *dev_info);
+int visorchipset_device_resume(struct visor_device *dev_info);
-void bus_create_response(struct visor_device *p, int response);
-void bus_destroy_response(struct visor_device *p, int response);
-void device_create_response(struct visor_device *p, int response);
-void device_destroy_response(struct visor_device *p, int response);
-void device_resume_response(struct visor_device *p, int response);
-void device_pause_response(struct visor_device *p, int response);
+void visorbus_create_response(struct visor_device *p, int response);
+void visorbus_destroy_response(struct visor_device *p, int response);
+void visorbus_device_create_response(struct visor_device *p, int response);
+void visorbus_device_destroy_response(struct visor_device *p, int response);
+void visorbus_device_resume_response(struct visor_device *p, int response);
+void visorbus_device_pause_response(struct visor_device *p, int response);
int visorbus_init(void);
void visorbus_exit(void);
diff --git a/drivers/staging/unisys/visorbus/visorchannel.c b/drivers/staging/unisys/visorbus/visorchannel.c
index 9e1cea22ce68..6885c2cb7135 100644
--- a/drivers/staging/unisys/visorbus/visorchannel.c
+++ b/drivers/staging/unisys/visorbus/visorchannel.c
@@ -28,11 +28,11 @@
#define MYDRVNAME "visorchannel"
-#define SPAR_CONSOLEVIDEO_CHANNEL_PROTOCOL_GUID \
+#define VISOR_CONSOLEVIDEO_CHANNEL_GUID \
UUID_LE(0x3cd6e705, 0xd6a2, 0x4aa5, \
0xad, 0x5c, 0x7b, 0x8, 0x88, 0x9d, 0xff, 0xe2)
-static const uuid_le spar_video_guid = SPAR_CONSOLEVIDEO_CHANNEL_PROTOCOL_GUID;
+static const uuid_le visor_video_guid = VISOR_CONSOLEVIDEO_CHANNEL_GUID;
struct visorchannel {
u64 physaddr;
@@ -415,7 +415,7 @@ visorchannel_create_guts(u64 physaddr, unsigned long channel_bytes,
* release later on.
*/
channel->requested = request_mem_region(physaddr, size, MYDRVNAME);
- if (!channel->requested && uuid_le_cmp(guid, spar_video_guid))
+ if (!channel->requested && uuid_le_cmp(guid, visor_video_guid))
/* we only care about errors if this is not the video channel */
goto err_destroy_channel;
@@ -445,7 +445,7 @@ visorchannel_create_guts(u64 physaddr, unsigned long channel_bytes,
channel->mapped = NULL;
channel->requested = request_mem_region(channel->physaddr,
channel_bytes, MYDRVNAME);
- if (!channel->requested && uuid_le_cmp(guid, spar_video_guid))
+ if (!channel->requested && uuid_le_cmp(guid, visor_video_guid))
/* we only care about errors if this is not the video channel */
goto err_destroy_channel;
diff --git a/drivers/staging/unisys/visorbus/visorchipset.c b/drivers/staging/unisys/visorbus/visorchipset.c
index 4cfd0fae9bd5..22150564b4fb 100644
--- a/drivers/staging/unisys/visorbus/visorchipset.c
+++ b/drivers/staging/unisys/visorbus/visorchipset.c
@@ -34,12 +34,12 @@
#define MAX_CONTROLVM_PAYLOAD_BYTES (1024 * 128)
-#define UNISYS_SPAR_LEAF_ID 0x40000000
+#define UNISYS_VISOR_LEAF_ID 0x40000000
/* The s-Par leaf ID returns "UnisysSpar64" encoded across ebx, ecx, edx */
-#define UNISYS_SPAR_ID_EBX 0x73696e55
-#define UNISYS_SPAR_ID_ECX 0x70537379
-#define UNISYS_SPAR_ID_EDX 0x34367261
+#define UNISYS_VISOR_ID_EBX 0x73696e55
+#define UNISYS_VISOR_ID_ECX 0x70537379
+#define UNISYS_VISOR_ID_EDX 0x34367261
/*
* When the controlvm channel is idle for at least MIN_IDLE_SECONDS,
@@ -101,7 +101,7 @@ static ssize_t toolaction_show(struct device *dev,
int err;
err = visorchannel_read(chipset_dev->controlvm_channel,
- offsetof(struct spar_controlvm_channel_protocol,
+ offsetof(struct visor_controlvm_channel,
tool_action),
&tool_action, sizeof(u8));
if (err)
@@ -120,11 +120,10 @@ static ssize_t toolaction_store(struct device *dev,
if (kstrtou8(buf, 10, &tool_action))
return -EINVAL;
- err = visorchannel_write
- (chipset_dev->controlvm_channel,
- offsetof(struct spar_controlvm_channel_protocol,
- tool_action),
- &tool_action, sizeof(u8));
+ err = visorchannel_write(chipset_dev->controlvm_channel,
+ offsetof(struct visor_controlvm_channel,
+ tool_action),
+ &tool_action, sizeof(u8));
if (err)
return err;
@@ -136,18 +135,18 @@ static ssize_t boottotool_show(struct device *dev,
struct device_attribute *attr,
char *buf)
{
- struct efi_spar_indication efi_spar_indication;
+ struct efi_visor_indication efi_visor_indication;
int err;
err = visorchannel_read(chipset_dev->controlvm_channel,
- offsetof(struct spar_controlvm_channel_protocol,
- efi_spar_ind),
- &efi_spar_indication,
- sizeof(struct efi_spar_indication));
+ offsetof(struct visor_controlvm_channel,
+ efi_visor_ind),
+ &efi_visor_indication,
+ sizeof(struct efi_visor_indication));
if (err)
return err;
- return sprintf(buf, "%u\n", efi_spar_indication.boot_to_tool);
+ return sprintf(buf, "%u\n", efi_visor_indication.boot_to_tool);
}
static ssize_t boottotool_store(struct device *dev,
@@ -155,17 +154,17 @@ static ssize_t boottotool_store(struct device *dev,
const char *buf, size_t count)
{
int val, err;
- struct efi_spar_indication efi_spar_indication;
+ struct efi_visor_indication efi_visor_indication;
if (kstrtoint(buf, 10, &val))
return -EINVAL;
- efi_spar_indication.boot_to_tool = val;
- err = visorchannel_write
- (chipset_dev->controlvm_channel,
- offsetof(struct spar_controlvm_channel_protocol,
- efi_spar_ind), &(efi_spar_indication),
- sizeof(struct efi_spar_indication));
+ efi_visor_indication.boot_to_tool = val;
+ err = visorchannel_write(chipset_dev->controlvm_channel,
+ offsetof(struct visor_controlvm_channel,
+ efi_visor_ind),
+ &(efi_visor_indication),
+ sizeof(struct efi_visor_indication));
if (err)
return err;
@@ -180,7 +179,7 @@ static ssize_t error_show(struct device *dev, struct device_attribute *attr,
int err;
err = visorchannel_read(chipset_dev->controlvm_channel,
- offsetof(struct spar_controlvm_channel_protocol,
+ offsetof(struct visor_controlvm_channel,
installation_error),
&error, sizeof(u32));
if (err)
@@ -197,11 +196,10 @@ static ssize_t error_store(struct device *dev, struct device_attribute *attr,
if (kstrtou32(buf, 10, &error))
return -EINVAL;
- err = visorchannel_write
- (chipset_dev->controlvm_channel,
- offsetof(struct spar_controlvm_channel_protocol,
- installation_error),
- &error, sizeof(u32));
+ err = visorchannel_write(chipset_dev->controlvm_channel,
+ offsetof(struct visor_controlvm_channel,
+ installation_error),
+ &error, sizeof(u32));
if (err)
return err;
return count;
@@ -214,11 +212,10 @@ static ssize_t textid_show(struct device *dev, struct device_attribute *attr,
u32 text_id = 0;
int err;
- err = visorchannel_read
- (chipset_dev->controlvm_channel,
- offsetof(struct spar_controlvm_channel_protocol,
- installation_text_id),
- &text_id, sizeof(u32));
+ err = visorchannel_read(chipset_dev->controlvm_channel,
+ offsetof(struct visor_controlvm_channel,
+ installation_text_id),
+ &text_id, sizeof(u32));
if (err)
return err;
@@ -234,11 +231,10 @@ static ssize_t textid_store(struct device *dev, struct device_attribute *attr,
if (kstrtou32(buf, 10, &text_id))
return -EINVAL;
- err = visorchannel_write
- (chipset_dev->controlvm_channel,
- offsetof(struct spar_controlvm_channel_protocol,
- installation_text_id),
- &text_id, sizeof(u32));
+ err = visorchannel_write(chipset_dev->controlvm_channel,
+ offsetof(struct visor_controlvm_channel,
+ installation_text_id),
+ &text_id, sizeof(u32));
if (err)
return err;
return count;
@@ -252,7 +248,7 @@ static ssize_t remaining_steps_show(struct device *dev,
int err;
err = visorchannel_read(chipset_dev->controlvm_channel,
- offsetof(struct spar_controlvm_channel_protocol,
+ offsetof(struct visor_controlvm_channel,
installation_remaining_steps),
&remaining_steps, sizeof(u16));
if (err)
@@ -271,11 +267,10 @@ static ssize_t remaining_steps_store(struct device *dev,
if (kstrtou16(buf, 10, &remaining_steps))
return -EINVAL;
- err = visorchannel_write
- (chipset_dev->controlvm_channel,
- offsetof(struct spar_controlvm_channel_protocol,
- installation_remaining_steps),
- &remaining_steps, sizeof(u16));
+ err = visorchannel_write(chipset_dev->controlvm_channel,
+ offsetof(struct visor_controlvm_channel,
+ installation_remaining_steps),
+ &remaining_steps, sizeof(u16));
if (err)
return err;
return count;
@@ -285,9 +280,9 @@ static DEVICE_ATTR_RW(remaining_steps);
static uuid_le
parser_id_get(struct parser_context *ctx)
{
- struct spar_controlvm_parameters_header *phdr = NULL;
+ struct visor_controlvm_parameters_header *phdr = NULL;
- phdr = (struct spar_controlvm_parameters_header *)(ctx->data);
+ phdr = (struct visor_controlvm_parameters_header *)(ctx->data);
return phdr->id;
}
@@ -331,9 +326,9 @@ parser_string_get(struct parser_context *ctx)
static void *
parser_name_get(struct parser_context *ctx)
{
- struct spar_controlvm_parameters_header *phdr = NULL;
+ struct visor_controlvm_parameters_header *phdr = NULL;
- phdr = (struct spar_controlvm_parameters_header *)(ctx->data);
+ phdr = (struct visor_controlvm_parameters_header *)(ctx->data);
if (phdr->name_offset + phdr->name_length > ctx->param_bytes)
return NULL;
@@ -400,7 +395,7 @@ controlvm_init_response(struct controlvm_message *msg,
static int
controlvm_respond_chipset_init(struct controlvm_message_header *msg_hdr,
int response,
- enum ultra_chipset_feature features)
+ enum visor_chipset_feature features)
{
struct controlvm_message outmsg;
@@ -414,7 +409,7 @@ static int
chipset_init(struct controlvm_message *inmsg)
{
static int chipset_inited;
- enum ultra_chipset_feature features = 0;
+ enum visor_chipset_feature features = 0;
int rc = CONTROLVM_RESP_SUCCESS;
int res = 0;
@@ -430,13 +425,13 @@ chipset_init(struct controlvm_message *inmsg)
* also supports it).
*/
features = inmsg->cmd.init_chipset.features &
- ULTRA_CHIPSET_FEATURE_PARA_HOTPLUG;
+ VISOR_CHIPSET_FEATURE_PARA_HOTPLUG;
/*
* Set the "reply" bit so Command knows this is a
* features-aware driver.
*/
- features |= ULTRA_CHIPSET_FEATURE_REPLY;
+ features |= VISOR_CHIPSET_FEATURE_REPLY;
out_respond:
if (inmsg->hdr.flags.response_expected)
@@ -447,7 +442,7 @@ out_respond:
static int
controlvm_respond(struct controlvm_message_header *msg_hdr, int response,
- struct spar_segment_state *state)
+ struct visor_segment_state *state)
{
struct controlvm_message outmsg;
@@ -470,14 +465,14 @@ enum crash_obj_type {
};
static int
-save_crash_message(struct controlvm_message *msg, enum crash_obj_type typ)
+save_crash_message(struct controlvm_message *msg, enum crash_obj_type cr_type)
{
u32 local_crash_msg_offset;
u16 local_crash_msg_count;
int err;
err = visorchannel_read(chipset_dev->controlvm_channel,
- offsetof(struct spar_controlvm_channel_protocol,
+ offsetof(struct visor_controlvm_channel,
saved_crash_message_count),
&local_crash_msg_count, sizeof(u16));
if (err) {
@@ -493,7 +488,7 @@ save_crash_message(struct controlvm_message *msg, enum crash_obj_type typ)
}
err = visorchannel_read(chipset_dev->controlvm_channel,
- offsetof(struct spar_controlvm_channel_protocol,
+ offsetof(struct visor_controlvm_channel,
saved_crash_message_offset),
&local_crash_msg_offset, sizeof(u32));
if (err) {
@@ -502,7 +497,7 @@ save_crash_message(struct controlvm_message *msg, enum crash_obj_type typ)
return err;
}
- switch (typ) {
+ switch (cr_type) {
case CRASH_DEV:
local_crash_msg_offset += sizeof(struct controlvm_message);
err = visorchannel_write(chipset_dev->controlvm_channel,
@@ -551,7 +546,7 @@ controlvm_responder(enum controlvm_id cmd_id,
static int
device_changestate_responder(enum controlvm_id cmd_id,
struct visor_device *p, int response,
- struct spar_segment_state response_state)
+ struct visor_segment_state response_state)
{
struct controlvm_message outmsg;
u32 bus_no = p->chipset_bus_no;
@@ -573,7 +568,7 @@ device_changestate_responder(enum controlvm_id cmd_id,
}
static int
-bus_create(struct controlvm_message *inmsg)
+visorbus_create(struct controlvm_message *inmsg)
{
struct controlvm_message_packet *cmd = &inmsg->cmd;
struct controlvm_message_header *pmsg_hdr = NULL;
@@ -585,7 +580,7 @@ bus_create(struct controlvm_message *inmsg)
bus_info = visorbus_get_device_by_id(bus_no, BUS_ROOT_DEVICE, NULL);
if (bus_info && (bus_info->state.created == 1)) {
dev_err(&chipset_dev->acpi_device->dev,
- "failed bus_create: already exists\n");
+ "failed visorbus_create: already exists\n");
err = -EEXIST;
goto err_respond;
}
@@ -600,7 +595,7 @@ bus_create(struct controlvm_message *inmsg)
bus_info->chipset_bus_no = bus_no;
bus_info->chipset_dev_no = BUS_ROOT_DEVICE;
- if (uuid_le_cmp(cmd->create_bus.bus_inst_uuid, spar_siovm_uuid) == 0) {
+ if (uuid_le_cmp(cmd->create_bus.bus_inst_uuid, visor_siovm_uuid) == 0) {
err = save_crash_message(inmsg, CRASH_BUS);
if (err)
goto err_free_bus_info;
@@ -630,9 +625,9 @@ bus_create(struct controlvm_message *inmsg)
}
bus_info->visorchannel = visorchannel;
- /* Response will be handled by chipset_bus_create */
- err = chipset_bus_create(bus_info);
- /* If error chipset_bus_create didn't respond, need to respond here */
+ /* Response will be handled by visorchipset_bus_create */
+ err = visorchipset_bus_create(bus_info);
+ /* If visorchipset_bus_create didn't respond, need to respond here */
if (err)
goto err_destroy_channel;
@@ -654,7 +649,7 @@ err_respond:
}
static int
-bus_destroy(struct controlvm_message *inmsg)
+visorbus_destroy(struct controlvm_message *inmsg)
{
struct controlvm_message_packet *cmd = &inmsg->cmd;
struct controlvm_message_header *pmsg_hdr = NULL;
@@ -688,8 +683,8 @@ bus_destroy(struct controlvm_message *inmsg)
bus_info->pending_msg_hdr = pmsg_hdr;
}
- /* Response will be handled by chipset_bus_destroy */
- chipset_bus_destroy(bus_info);
+ /* Response will be handled by visorchipset_bus_destroy */
+ visorchipset_bus_destroy(bus_info);
return 0;
err_respond:
@@ -699,8 +694,8 @@ err_respond:
}
static int
-bus_configure(struct controlvm_message *inmsg,
- struct parser_context *parser_ctx)
+visorbus_configure(struct controlvm_message *inmsg,
+ struct parser_context *parser_ctx)
{
struct controlvm_message_packet *cmd = &inmsg->cmd;
u32 bus_no;
@@ -737,14 +732,14 @@ bus_configure(struct controlvm_message *inmsg,
err_respond:
dev_err(&chipset_dev->acpi_device->dev,
- "bus_configured exited with err: %d\n", err);
+ "visorbus_configure exited with err: %d\n", err);
if (inmsg->hdr.flags.response_expected == 1)
controlvm_responder(inmsg->hdr.id, &inmsg->hdr, err);
return err;
}
static int
-my_device_create(struct controlvm_message *inmsg)
+visorbus_device_create(struct controlvm_message *inmsg)
{
struct controlvm_message_packet *cmd = &inmsg->cmd;
struct controlvm_message_header *pmsg_hdr = NULL;
@@ -807,7 +802,7 @@ my_device_create(struct controlvm_message *inmsg)
dev_info->visorchannel = visorchannel;
dev_info->channel_type_guid = cmd->create_device.data_type_uuid;
if (uuid_le_cmp(cmd->create_device.data_type_uuid,
- spar_vhba_channel_protocol_uuid) == 0) {
+ visor_vhba_channel_uuid) == 0) {
err = save_crash_message(inmsg, CRASH_DEV);
if (err)
goto err_destroy_visorchannel;
@@ -824,8 +819,8 @@ my_device_create(struct controlvm_message *inmsg)
sizeof(struct controlvm_message_header));
dev_info->pending_msg_hdr = pmsg_hdr;
}
- /* Chipset_device_create will send response */
- err = chipset_device_create(dev_info);
+ /* visorchipset_device_create will send response */
+ err = visorchipset_device_create(dev_info);
if (err)
goto err_destroy_visorchannel;
@@ -844,13 +839,13 @@ err_respond:
}
static int
-my_device_changestate(struct controlvm_message *inmsg)
+visorbus_device_changestate(struct controlvm_message *inmsg)
{
struct controlvm_message_packet *cmd = &inmsg->cmd;
struct controlvm_message_header *pmsg_hdr = NULL;
u32 bus_no = cmd->device_change_state.bus_no;
u32 dev_no = cmd->device_change_state.dev_no;
- struct spar_segment_state state = cmd->device_change_state.state;
+ struct visor_segment_state state = cmd->device_change_state.state;
struct visor_device *dev_info;
int err = 0;
@@ -882,16 +877,16 @@ my_device_changestate(struct controlvm_message *inmsg)
if (state.alive == segment_state_running.alive &&
state.operating == segment_state_running.operating)
- /* Response will be sent from chipset_device_resume */
- err = chipset_device_resume(dev_info);
+ /* Response will be sent from visorchipset_device_resume */
+ err = visorchipset_device_resume(dev_info);
/* ServerNotReady / ServerLost / SegmentStateStandby */
else if (state.alive == segment_state_standby.alive &&
state.operating == segment_state_standby.operating)
/*
* technically this is standby case where server is lost.
- * Response will be sent from chipset_device_pause.
+ * Response will be sent from visorchipset_device_pause.
*/
- err = chipset_device_pause(dev_info);
+ err = visorchipset_device_pause(dev_info);
if (err)
goto err_respond;
@@ -905,7 +900,7 @@ err_respond:
}
static int
-my_device_destroy(struct controlvm_message *inmsg)
+visorbus_device_destroy(struct controlvm_message *inmsg)
{
struct controlvm_message_packet *cmd = &inmsg->cmd;
struct controlvm_message_header *pmsg_hdr = NULL;
@@ -941,7 +936,7 @@ my_device_destroy(struct controlvm_message *inmsg)
dev_info->pending_msg_hdr = pmsg_hdr;
}
- chipset_device_destroy(dev_info);
+ visorchipset_device_destroy(dev_info);
return 0;
err_respond:
@@ -1179,15 +1174,15 @@ parahotplug_request_kickoff(struct parahotplug_request *req)
env_cmd, env_id, env_state, env_bus, env_dev, env_func, NULL
};
- sprintf(env_cmd, "SPAR_PARAHOTPLUG=1");
- sprintf(env_id, "SPAR_PARAHOTPLUG_ID=%d", req->id);
- sprintf(env_state, "SPAR_PARAHOTPLUG_STATE=%d",
+ sprintf(env_cmd, "VISOR_PARAHOTPLUG=1");
+ sprintf(env_id, "VISOR_PARAHOTPLUG_ID=%d", req->id);
+ sprintf(env_state, "VISOR_PARAHOTPLUG_STATE=%d",
cmd->device_change_state.state.active);
- sprintf(env_bus, "SPAR_PARAHOTPLUG_BUS=%d",
+ sprintf(env_bus, "VISOR_PARAHOTPLUG_BUS=%d",
cmd->device_change_state.bus_no);
- sprintf(env_dev, "SPAR_PARAHOTPLUG_DEVICE=%d",
+ sprintf(env_dev, "VISOR_PARAHOTPLUG_DEVICE=%d",
cmd->device_change_state.dev_no >> 3);
- sprintf(env_func, "SPAR_PARAHOTPLUG_FUNCTION=%d",
+ sprintf(env_func, "VISOR_PARAHOTPLUG_FUNCTION=%d",
cmd->device_change_state.dev_no & 0x7);
return kobject_uevent_env(&chipset_dev->acpi_device->dev.kobj,
@@ -1387,7 +1382,7 @@ setup_crash_devices_work_queue(struct work_struct *work)
/* get saved message count */
if (visorchannel_read(chipset_dev->controlvm_channel,
- offsetof(struct spar_controlvm_channel_protocol,
+ offsetof(struct visor_controlvm_channel,
saved_crash_message_count),
&local_crash_msg_count, sizeof(u16)) < 0) {
dev_err(&chipset_dev->acpi_device->dev,
@@ -1403,7 +1398,7 @@ setup_crash_devices_work_queue(struct work_struct *work)
/* get saved crash message offset */
if (visorchannel_read(chipset_dev->controlvm_channel,
- offsetof(struct spar_controlvm_channel_protocol,
+ offsetof(struct visor_controlvm_channel,
saved_crash_message_offset),
&local_crash_msg_offset, sizeof(u32)) < 0) {
dev_err(&chipset_dev->acpi_device->dev,
@@ -1438,7 +1433,7 @@ setup_crash_devices_work_queue(struct work_struct *work)
"no valid create_bus message\n");
return;
}
- bus_create(&local_crash_bus_msg);
+ visorbus_create(&local_crash_bus_msg);
/* reuse create device message for storage device */
if (!local_crash_dev_msg.cmd.create_device.channel_addr) {
@@ -1446,11 +1441,11 @@ setup_crash_devices_work_queue(struct work_struct *work)
"no valid create_device message\n");
return;
}
- my_device_create(&local_crash_dev_msg);
+ visorbus_device_create(&local_crash_dev_msg);
}
void
-bus_create_response(struct visor_device *bus_info, int response)
+visorbus_create_response(struct visor_device *bus_info, int response)
{
if (response >= 0)
bus_info->state.created = 1;
@@ -1463,7 +1458,7 @@ bus_create_response(struct visor_device *bus_info, int response)
}
void
-bus_destroy_response(struct visor_device *bus_info, int response)
+visorbus_destroy_response(struct visor_device *bus_info, int response)
{
controlvm_responder(CONTROLVM_BUS_DESTROY, bus_info->pending_msg_hdr,
response);
@@ -1473,7 +1468,7 @@ bus_destroy_response(struct visor_device *bus_info, int response)
}
void
-device_create_response(struct visor_device *dev_info, int response)
+visorbus_device_create_response(struct visor_device *dev_info, int response)
{
if (response >= 0)
dev_info->state.created = 1;
@@ -1486,7 +1481,7 @@ device_create_response(struct visor_device *dev_info, int response)
}
void
-device_destroy_response(struct visor_device *dev_info, int response)
+visorbus_device_destroy_response(struct visor_device *dev_info, int response)
{
controlvm_responder(CONTROLVM_DEVICE_DESTROY, dev_info->pending_msg_hdr,
response);
@@ -1496,8 +1491,7 @@ device_destroy_response(struct visor_device *dev_info, int response)
}
void
-device_pause_response(struct visor_device *dev_info,
- int response)
+visorbus_device_pause_response(struct visor_device *dev_info, int response)
{
device_changestate_responder(CONTROLVM_DEVICE_CHANGESTATE,
dev_info, response,
@@ -1508,7 +1502,7 @@ device_pause_response(struct visor_device *dev_info,
}
void
-device_resume_response(struct visor_device *dev_info, int response)
+visorbus_device_resume_response(struct visor_device *dev_info, int response)
{
device_changestate_responder(CONTROLVM_DEVICE_CHANGESTATE,
dev_info, response,
@@ -1599,9 +1593,6 @@ handle_command(struct controlvm_message inmsg, u64 channel_addr)
/* create parsing context if necessary */
local_addr = (inmsg.hdr.flags.test_message == 1);
- if (channel_addr == 0)
- return -EINVAL;
-
parm_addr = channel_addr + inmsg.hdr.payload_vm_offset;
parm_bytes = inmsg.hdr.payload_bytes;
@@ -1634,16 +1625,16 @@ handle_command(struct controlvm_message inmsg, u64 channel_addr)
err = chipset_init(&inmsg);
break;
case CONTROLVM_BUS_CREATE:
- err = bus_create(&inmsg);
+ err = visorbus_create(&inmsg);
break;
case CONTROLVM_BUS_DESTROY:
- err = bus_destroy(&inmsg);
+ err = visorbus_destroy(&inmsg);
break;
case CONTROLVM_BUS_CONFIGURE:
- err = bus_configure(&inmsg, parser_ctx);
+ err = visorbus_configure(&inmsg, parser_ctx);
break;
case CONTROLVM_DEVICE_CREATE:
- err = my_device_create(&inmsg);
+ err = visorbus_device_create(&inmsg);
break;
case CONTROLVM_DEVICE_CHANGESTATE:
if (cmd->device_change_state.flags.phys_device) {
@@ -1653,12 +1644,12 @@ handle_command(struct controlvm_message inmsg, u64 channel_addr)
* save the hdr and cmd structures for later use
* when sending back the response to Command
*/
- err = my_device_changestate(&inmsg);
+ err = visorbus_device_changestate(&inmsg);
break;
}
break;
case CONTROLVM_DEVICE_DESTROY:
- err = my_device_destroy(&inmsg);
+ err = visorbus_device_destroy(&inmsg);
break;
case CONTROLVM_DEVICE_CONFIGURE:
/* no op just send a respond that we passed */
@@ -1793,6 +1784,11 @@ controlvm_periodic_work(struct work_struct *work)
/* parahotplug_worker */
parahotplug_process_list();
+/*
+ * The controlvm messages are sent in a bulk. If we start receiving messages, we
+ * want the polling to be fast. If we do not receive any message for
+ * MIN_IDLE_SECONDS, we can slow down the polling.
+ */
schedule_out:
if (time_after(jiffies, chipset_dev->most_recent_message_jiffies +
(HZ * MIN_IDLE_SECONDS))) {
@@ -1821,7 +1817,7 @@ visorchipset_init(struct acpi_device *acpi_device)
{
int err = -ENODEV;
u64 addr;
- uuid_le uuid = SPAR_CONTROLVM_CHANNEL_PROTOCOL_UUID;
+ uuid_le uuid = VISOR_CONTROLVM_CHANNEL_UUID;
struct visorchannel *controlvm_channel;
chipset_dev = kzalloc(sizeof(*chipset_dev), GFP_KERNEL);
@@ -1849,7 +1845,7 @@ visorchipset_init(struct acpi_device *acpi_device)
if (err < 0)
goto error_destroy_channel;
- if (!SPAR_CONTROLVM_CHANNEL_OK_CLIENT(
+ if (!VISOR_CONTROLVM_CHANNEL_OK_CLIENT(
visorchannel_get_header(controlvm_channel)))
goto error_delete_groups;
@@ -1928,10 +1924,10 @@ static __init int visorutil_spar_detect(void)
if (boot_cpu_has(X86_FEATURE_HYPERVISOR)) {
/* check the ID */
- cpuid(UNISYS_SPAR_LEAF_ID, &eax, &ebx, &ecx, &edx);
- return (ebx == UNISYS_SPAR_ID_EBX) &&
- (ecx == UNISYS_SPAR_ID_ECX) &&
- (edx == UNISYS_SPAR_ID_EDX);
+ cpuid(UNISYS_VISOR_LEAF_ID, &eax, &ebx, &ecx, &edx);
+ return (ebx == UNISYS_VISOR_ID_EBX) &&
+ (ecx == UNISYS_VISOR_ID_ECX) &&
+ (edx == UNISYS_VISOR_ID_EDX);
} else {
return 0;
}
diff --git a/drivers/staging/unisys/visorhba/visorhba_main.c b/drivers/staging/unisys/visorhba/visorhba_main.c
index 6997b16b4dcd..a6e7a6bbc428 100644
--- a/drivers/staging/unisys/visorhba/visorhba_main.c
+++ b/drivers/staging/unisys/visorhba/visorhba_main.c
@@ -37,14 +37,14 @@ static struct dentry *visorhba_debugfs_dir;
/* GUIDS for HBA channel type supported by this driver */
static struct visor_channeltype_descriptor visorhba_channel_types[] = {
/* Note that the only channel type we expect to be reported by the
- * bus driver is the SPAR_VHBA channel.
+ * bus driver is the VISOR_VHBA channel.
*/
- { SPAR_VHBA_CHANNEL_PROTOCOL_UUID, "sparvhba" },
+ { VISOR_VHBA_CHANNEL_UUID, "sparvhba" },
{ NULL_UUID_LE, NULL }
};
MODULE_DEVICE_TABLE(visorbus, visorhba_channel_types);
-MODULE_ALIAS("visorbus:" SPAR_VHBA_CHANNEL_PROTOCOL_UUID_STR);
+MODULE_ALIAS("visorbus:" VISOR_VHBA_CHANNEL_UUID_STR);
struct visordisk_info {
u32 valid;
@@ -657,7 +657,7 @@ static int info_debugfs_show(struct seq_file *seq, void *v)
seq_printf(seq, "phys_flags_addr = 0x%016llx\n",
phys_flags_addr);
seq_printf(seq, "FeatureFlags = %llu\n",
- (__le64)readq(devdata->flags_addr));
+ (u64)readq(devdata->flags_addr));
}
seq_printf(seq, "acquire_failed_cnt = %llu\n",
devdata->acquire_failed_cnt);
@@ -1060,8 +1060,7 @@ static int visorhba_probe(struct visor_device *dev)
if (!scsihost)
return -ENODEV;
- channel_offset = offsetof(struct spar_io_channel_protocol,
- vhba.max);
+ channel_offset = offsetof(struct visor_io_channel, vhba.max);
err = visorbus_read_channel(dev, channel_offset, &max,
sizeof(struct vhba_config_max));
if (err < 0)
@@ -1091,7 +1090,7 @@ static int visorhba_probe(struct visor_device *dev)
goto err_scsi_remove_host;
}
devdata->debugfs_info =
- debugfs_create_file("info", S_IRUSR | S_IRGRP,
+ debugfs_create_file("info", 0440,
devdata->debugfs_dir, devdata,
&info_debugfs_fops);
if (!devdata->debugfs_info) {
@@ -1105,12 +1104,12 @@ static int visorhba_probe(struct visor_device *dev)
devdata->serverchangingstate = false;
devdata->scsihost = scsihost;
- channel_offset = offsetof(struct spar_io_channel_protocol,
+ channel_offset = offsetof(struct visor_io_channel,
channel_header.features);
err = visorbus_read_channel(dev, channel_offset, &features, 8);
if (err)
goto err_debugfs_info;
- features |= ULTRA_IO_CHANNEL_IS_POLLING;
+ features |= VISOR_CHANNEL_IS_POLLING;
err = visorbus_write_channel(dev, channel_offset, &features, 8);
if (err)
goto err_debugfs_info;
@@ -1166,7 +1165,7 @@ static void visorhba_remove(struct visor_device *dev)
debugfs_remove_recursive(devdata->debugfs_dir);
}
-/* This is used to tell the visor bus driver which types of visor devices
+/* This is used to tell the visorbus driver which types of visor devices
* we support, and what functions to call when a visor device that we support
* is attached or removed.
*/
diff --git a/drivers/staging/unisys/visorinput/ultrainputreport.h b/drivers/staging/unisys/visorinput/ultrainputreport.h
index 53dde7c53809..a4baea53c518 100644
--- a/drivers/staging/unisys/visorinput/ultrainputreport.h
+++ b/drivers/staging/unisys/visorinput/ultrainputreport.h
@@ -17,26 +17,23 @@
#include <linux/types.h>
-/* Identifies mouse and keyboard activity which is specified by the firmware to
- * the host using the cmsimpleinput protocol. @ingroup coretypes
+/* These defines identify mouse and keyboard activity which is specified by the
+ * firmware to the host using the cmsimpleinput protocol. @ingroup coretypes
*/
-enum ultra_inputaction {
- inputaction_none = 0,
- inputaction_xy_motion = 1, /* only motion; arg1=x, arg2=y */
- inputaction_mouse_button_down = 2, /* arg1: 1=left,2=center,3=right */
- inputaction_mouse_button_up = 3, /* arg1: 1=left,2=center,3=right */
- inputaction_mouse_button_click = 4, /* arg1: 1=left,2=center,3=right */
- inputaction_mouse_button_dclick = 5, /* arg1: 1=left,2=center,
- * 3=right
- */
- inputaction_wheel_rotate_away = 6, /* arg1: wheel rotation away from
- * user
- */
- inputaction_wheel_rotate_toward = 7, /* arg1: wheel rotation toward
- * user
- */
- inputaction_set_max_xy = 8, /* set screen maxXY; arg1=x, arg2=y */
- inputaction_key_down = 64, /* arg1: scancode, as follows:
+#define INPUTACTION_XY_MOTION 1 /* only motion; arg1=x, arg2=y */
+#define INPUTACTION_MOUSE_BUTTON_DOWN 2 /* arg1: 1=left,2=center,3=right */
+#define INPUTACTION_MOUSE_BUTTON_UP 3 /* arg1: 1=left,2=center,3=right */
+#define INPUTACTION_MOUSE_BUTTON_CLICK 4 /* arg1: 1=left,2=center,3=right */
+#define INPUTACTION_MOUSE_BUTTON_DCLICK 5 /* arg1: 1=left,2=center,
+ * 3=right
+ */
+#define INPUTACTION_WHEEL_ROTATE_AWAY 6 /* arg1: wheel rotation away from
+ * user
+ */
+#define INPUTACTION_WHEEL_ROTATE_TOWARD 7 /* arg1: wheel rotation toward
+ * user
+ */
+#define INPUTACTION_KEY_DOWN 64 /* arg1: scancode, as follows:
* If arg1 <= 0xff, it's a 1-byte
* scancode and arg1 is that scancode.
* If arg1 > 0xff, it's a 2-byte
@@ -45,10 +42,10 @@ enum ultra_inputaction {
* high 8 bits. E.g., the right ALT key
* would appear as x'38e0'.
*/
- inputaction_key_up = 65, /* arg1: scancode (in same format as
+#define INPUTACTION_KEY_UP 65 /* arg1: scancode (in same format as
* inputaction_keyDown)
*/
- inputaction_set_locking_key_state = 66,
+#define INPUTACTION_SET_LOCKING_KEY_STATE 66
/* arg1: scancode (in same format
* as inputaction_keyDown);
* MUST refer to one of the
@@ -58,22 +55,20 @@ enum ultra_inputaction {
* in the LOCKED position
* (e.g., light is ON)
*/
- inputaction_key_down_up = 67, /* arg1: scancode (in same format
+#define INPUTACTION_KEY_DOWN_UP 67 /* arg1: scancode (in same format
* as inputaction_keyDown)
*/
- inputaction_last
-};
-struct ultra_inputactivity {
+struct visor_inputactivity {
u16 action;
u16 arg1;
u16 arg2;
u16 arg3;
} __packed;
-struct ultra_inputreport {
+struct visor_inputreport {
u64 seq_no;
- struct ultra_inputactivity activity;
+ struct visor_inputactivity activity;
} __packed;
#endif
diff --git a/drivers/staging/unisys/visorinput/visorinput.c b/drivers/staging/unisys/visorinput/visorinput.c
index cdd35437f0a0..45bc340d4e9d 100644
--- a/drivers/staging/unisys/visorinput/visorinput.c
+++ b/drivers/staging/unisys/visorinput/visorinput.c
@@ -33,17 +33,16 @@
#include "ultrainputreport.h"
/* Keyboard channel {c73416d0-b0b8-44af-b304-9d2ae99f1b3d} */
-#define SPAR_KEYBOARD_CHANNEL_PROTOCOL_UUID \
+#define VISOR_KEYBOARD_CHANNEL_UUID \
UUID_LE(0xc73416d0, 0xb0b8, 0x44af, \
0xb3, 0x4, 0x9d, 0x2a, 0xe9, 0x9f, 0x1b, 0x3d)
-#define SPAR_KEYBOARD_CHANNEL_PROTOCOL_UUID_STR "c73416d0-b0b8-44af-b304-9d2ae99f1b3d"
+#define VISOR_KEYBOARD_CHANNEL_UUID_STR "c73416d0-b0b8-44af-b304-9d2ae99f1b3d"
/* Mouse channel {addf07d4-94a9-46e2-81c3-61abcdbdbd87} */
-#define SPAR_MOUSE_CHANNEL_PROTOCOL_UUID \
+#define VISOR_MOUSE_CHANNEL_UUID \
UUID_LE(0xaddf07d4, 0x94a9, 0x46e2, \
0x81, 0xc3, 0x61, 0xab, 0xcd, 0xbd, 0xbd, 0x87)
-#define SPAR_MOUSE_CHANNEL_PROTOCOL_UUID_STR \
- "addf07d4-94a9-46e2-81c3-61abcdbdbd87"
+#define VISOR_MOUSE_CHANNEL_UUID_STR "addf07d4-94a9-46e2-81c3-61abcdbdbd87"
#define PIXELS_ACROSS_DEFAULT 800
#define PIXELS_DOWN_DEFAULT 600
@@ -70,10 +69,8 @@ struct visorinput_devdata {
unsigned char keycode_table[0];
};
-static const uuid_le spar_keyboard_channel_protocol_uuid =
- SPAR_KEYBOARD_CHANNEL_PROTOCOL_UUID;
-static const uuid_le spar_mouse_channel_protocol_uuid =
- SPAR_MOUSE_CHANNEL_PROTOCOL_UUID;
+static const uuid_le visor_keyboard_channel_uuid = VISOR_KEYBOARD_CHANNEL_UUID;
+static const uuid_le visor_mouse_channel_uuid = VISOR_MOUSE_CHANNEL_UUID;
/*
* Borrowed from drivers/input/keyboard/atakbd.c
@@ -456,9 +453,9 @@ visorinput_probe(struct visor_device *dev)
enum visorinput_device_type devtype;
guid = visorchannel_get_uuid(dev->visorchannel);
- if (uuid_le_cmp(guid, spar_mouse_channel_protocol_uuid) == 0)
+ if (uuid_le_cmp(guid, visor_mouse_channel_uuid) == 0)
devtype = visorinput_mouse;
- else if (uuid_le_cmp(guid, spar_keyboard_channel_protocol_uuid) == 0)
+ else if (uuid_le_cmp(guid, visor_keyboard_channel_uuid) == 0)
devtype = visorinput_keyboard;
else
return -ENODEV;
@@ -568,7 +565,7 @@ calc_button(int x)
static void
visorinput_channel_interrupt(struct visor_device *dev)
{
- struct ultra_inputreport r;
+ struct visor_inputreport r;
int scancode, keycode;
struct input_dev *visorinput_dev;
int xmotion, ymotion, button;
@@ -585,46 +582,46 @@ visorinput_channel_interrupt(struct visor_device *dev)
scancode = r.activity.arg1;
keycode = scancode_to_keycode(scancode);
switch (r.activity.action) {
- case inputaction_key_down:
+ case INPUTACTION_KEY_DOWN:
input_report_key(visorinput_dev, keycode, 1);
input_sync(visorinput_dev);
break;
- case inputaction_key_up:
+ case INPUTACTION_KEY_UP:
input_report_key(visorinput_dev, keycode, 0);
input_sync(visorinput_dev);
break;
- case inputaction_key_down_up:
+ case INPUTACTION_KEY_DOWN_UP:
input_report_key(visorinput_dev, keycode, 1);
input_sync(visorinput_dev);
input_report_key(visorinput_dev, keycode, 0);
input_sync(visorinput_dev);
break;
- case inputaction_set_locking_key_state:
+ case INPUTACTION_SET_LOCKING_KEY_STATE:
handle_locking_key(visorinput_dev, keycode,
r.activity.arg2);
break;
- case inputaction_xy_motion:
+ case INPUTACTION_XY_MOTION:
xmotion = r.activity.arg1;
ymotion = r.activity.arg2;
input_report_abs(visorinput_dev, ABS_X, xmotion);
input_report_abs(visorinput_dev, ABS_Y, ymotion);
input_sync(visorinput_dev);
break;
- case inputaction_mouse_button_down:
+ case INPUTACTION_MOUSE_BUTTON_DOWN:
button = calc_button(r.activity.arg1);
if (button < 0)
break;
input_report_key(visorinput_dev, button, 1);
input_sync(visorinput_dev);
break;
- case inputaction_mouse_button_up:
+ case INPUTACTION_MOUSE_BUTTON_UP:
button = calc_button(r.activity.arg1);
if (button < 0)
break;
input_report_key(visorinput_dev, button, 0);
input_sync(visorinput_dev);
break;
- case inputaction_mouse_button_click:
+ case INPUTACTION_MOUSE_BUTTON_CLICK:
button = calc_button(r.activity.arg1);
if (button < 0)
break;
@@ -634,7 +631,7 @@ visorinput_channel_interrupt(struct visor_device *dev)
input_report_key(visorinput_dev, button, 0);
input_sync(visorinput_dev);
break;
- case inputaction_mouse_button_dclick:
+ case INPUTACTION_MOUSE_BUTTON_DCLICK:
button = calc_button(r.activity.arg1);
if (button < 0)
break;
@@ -645,11 +642,11 @@ visorinput_channel_interrupt(struct visor_device *dev)
input_sync(visorinput_dev);
}
break;
- case inputaction_wheel_rotate_away:
+ case INPUTACTION_WHEEL_ROTATE_AWAY:
input_report_rel(visorinput_dev, REL_WHEEL, 1);
input_sync(visorinput_dev);
break;
- case inputaction_wheel_rotate_toward:
+ case INPUTACTION_WHEEL_ROTATE_TOWARD:
input_report_rel(visorinput_dev, REL_WHEEL, -1);
input_sync(visorinput_dev);
break;
@@ -730,8 +727,8 @@ out:
/* GUIDS for all channel types supported by this driver. */
static struct visor_channeltype_descriptor visorinput_channel_types[] = {
- { SPAR_KEYBOARD_CHANNEL_PROTOCOL_UUID, "keyboard"},
- { SPAR_MOUSE_CHANNEL_PROTOCOL_UUID, "mouse"},
+ { VISOR_KEYBOARD_CHANNEL_UUID, "keyboard"},
+ { VISOR_MOUSE_CHANNEL_UUID, "mouse"},
{ NULL_UUID_LE, NULL }
};
@@ -767,5 +764,5 @@ MODULE_AUTHOR("Unisys");
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("s-Par human input driver for virtual keyboard/mouse");
-MODULE_ALIAS("visorbus:" SPAR_MOUSE_CHANNEL_PROTOCOL_UUID_STR);
-MODULE_ALIAS("visorbus:" SPAR_KEYBOARD_CHANNEL_PROTOCOL_UUID_STR);
+MODULE_ALIAS("visorbus:" VISOR_MOUSE_CHANNEL_UUID_STR);
+MODULE_ALIAS("visorbus:" VISOR_KEYBOARD_CHANNEL_UUID_STR);
diff --git a/drivers/staging/unisys/visornic/visornic_main.c b/drivers/staging/unisys/visornic/visornic_main.c
index adebf224f73a..2891622eef18 100644
--- a/drivers/staging/unisys/visornic/visornic_main.c
+++ b/drivers/staging/unisys/visornic/visornic_main.c
@@ -39,9 +39,9 @@
/* GUIDS for director channel type supported by this driver. */
static struct visor_channeltype_descriptor visornic_channel_types[] = {
/* Note that the only channel type we expect to be reported by the
- * bus driver is the SPAR_VNIC channel.
+ * bus driver is the VISOR_VNIC channel.
*/
- { SPAR_VNIC_CHANNEL_PROTOCOL_UUID, "ultravnic" },
+ { VISOR_VNIC_CHANNEL_UUID, "ultravnic" },
{ NULL_UUID_LE, NULL }
};
MODULE_DEVICE_TABLE(visorbus, visornic_channel_types);
@@ -52,7 +52,7 @@ MODULE_DEVICE_TABLE(visorbus, visornic_channel_types);
* must be added to scripts/mode/file2alias.c, etc., to get this working
* properly.
*/
-MODULE_ALIAS("visorbus:" SPAR_VNIC_CHANNEL_PROTOCOL_UUID_STR);
+MODULE_ALIAS("visorbus:" VISOR_VNIC_CHANNEL_UUID_STR);
struct chanstat {
unsigned long got_rcv;
@@ -1807,8 +1807,7 @@ static int visornic_probe(struct visor_device *dev)
/* Get MAC address from channel and read it into the device. */
netdev->addr_len = ETH_ALEN;
- channel_offset = offsetof(struct spar_io_channel_protocol,
- vnic.macaddr);
+ channel_offset = offsetof(struct visor_io_channel, vnic.macaddr);
err = visorbus_read_channel(dev, channel_offset, netdev->dev_addr,
ETH_ALEN);
if (err < 0) {
@@ -1836,8 +1835,7 @@ static int visornic_probe(struct visor_device *dev)
atomic_set(&devdata->usage, 1);
/* Setup rcv bufs */
- channel_offset = offsetof(struct spar_io_channel_protocol,
- vnic.num_rcv_bufs);
+ channel_offset = offsetof(struct visor_io_channel, vnic.num_rcv_bufs);
err = visorbus_read_channel(dev, channel_offset,
&devdata->num_rcv_bufs, 4);
if (err) {
@@ -1884,8 +1882,7 @@ static int visornic_probe(struct visor_device *dev)
devdata->server_change_state = false;
/*set the default mtu */
- channel_offset = offsetof(struct spar_io_channel_protocol,
- vnic.mtu);
+ channel_offset = offsetof(struct visor_io_channel, vnic.mtu);
err = visorbus_read_channel(dev, channel_offset, &netdev->mtu, 4);
if (err) {
dev_err(&dev->device,
@@ -1906,7 +1903,7 @@ static int visornic_probe(struct visor_device *dev)
*/
mod_timer(&devdata->irq_poll_timer, msecs_to_jiffies(2));
- channel_offset = offsetof(struct spar_io_channel_protocol,
+ channel_offset = offsetof(struct visor_io_channel,
channel_header.features);
err = visorbus_read_channel(dev, channel_offset, &features, 8);
if (err) {
@@ -1916,8 +1913,8 @@ static int visornic_probe(struct visor_device *dev)
goto cleanup_napi_add;
}
- features |= ULTRA_IO_CHANNEL_IS_POLLING;
- features |= ULTRA_IO_DRIVER_SUPPORTS_ENHANCED_RCVBUF_CHECKING;
+ features |= VISOR_CHANNEL_IS_POLLING;
+ features |= VISOR_DRIVER_ENHANCED_RCVBUF_CHECKING;
err = visorbus_write_channel(dev, channel_offset, &features, 8);
if (err) {
dev_err(&dev->device,
@@ -2115,7 +2112,7 @@ static int visornic_resume(struct visor_device *dev,
return 0;
}
-/* This is used to tell the visor bus driver which types of visor devices
+/* This is used to tell the visorbus driver which types of visor devices
* we support, and what functions to call when a visor device that we support
* is attached or removed.
*/
diff --git a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_2835_arm.c b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_2835_arm.c
index d04db3f55519..0159ca4407d8 100644
--- a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_2835_arm.c
+++ b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_2835_arm.c
@@ -153,7 +153,6 @@ int vchiq_platform_init(struct platform_device *pdev, VCHIQ_STATE_T *state)
MAX_FRAGMENTS;
g_fragments_base = (char *)slot_mem + slot_mem_size;
- slot_mem_size += frag_mem_size;
g_free_fragments = g_fragments_base;
for (i = 0; i < (MAX_FRAGMENTS - 1); i++) {
@@ -365,7 +364,7 @@ vchiq_doorbell_irq(int irq, void *dev_id)
}
static void
-cleaup_pagelistinfo(struct vchiq_pagelist_info *pagelistinfo)
+cleanup_pagelistinfo(struct vchiq_pagelist_info *pagelistinfo)
{
if (pagelistinfo->scatterlist_mapped) {
dma_unmap_sg(g_dev, pagelistinfo->scatterlist,
@@ -460,6 +459,11 @@ create_pagelist(char __user *buf, size_t count, unsigned short type,
PAGE_SIZE));
size_t bytes = PAGE_SIZE - off;
+ if (!pg) {
+ cleanup_pagelistinfo(pagelistinfo);
+ return NULL;
+ }
+
if (bytes > length)
bytes = length;
pages[actual_pages] = pg;
@@ -470,7 +474,7 @@ create_pagelist(char __user *buf, size_t count, unsigned short type,
} else {
down_read(&task->mm->mmap_sem);
actual_pages = get_user_pages(
- (unsigned long)buf & ~(PAGE_SIZE - 1),
+ (unsigned long)buf & PAGE_MASK,
num_pages,
(type == PAGELIST_READ) ? FOLL_WRITE : 0,
pages,
@@ -489,7 +493,7 @@ create_pagelist(char __user *buf, size_t count, unsigned short type,
actual_pages--;
put_page(pages[actual_pages]);
}
- cleaup_pagelistinfo(pagelistinfo);
+ cleanup_pagelistinfo(pagelistinfo);
return NULL;
}
/* release user pages */
@@ -518,7 +522,7 @@ create_pagelist(char __user *buf, size_t count, unsigned short type,
pagelistinfo->dma_dir);
if (dma_buffers == 0) {
- cleaup_pagelistinfo(pagelistinfo);
+ cleanup_pagelistinfo(pagelistinfo);
return NULL;
}
@@ -555,7 +559,7 @@ create_pagelist(char __user *buf, size_t count, unsigned short type,
char *fragments;
if (down_interruptible(&g_free_fragments_sema) != 0) {
- cleaup_pagelistinfo(pagelistinfo);
+ cleanup_pagelistinfo(pagelistinfo);
return NULL;
}
@@ -577,7 +581,6 @@ static void
free_pagelist(struct vchiq_pagelist_info *pagelistinfo,
int actual)
{
- unsigned int i;
PAGELIST_T *pagelist = pagelistinfo->pagelist;
struct page **pages = pagelistinfo->pages;
unsigned int num_pages = pagelistinfo->num_pages;
@@ -633,9 +636,11 @@ free_pagelist(struct vchiq_pagelist_info *pagelistinfo,
/* Need to mark all the pages dirty. */
if (pagelist->type != PAGELIST_WRITE &&
pagelistinfo->pages_need_release) {
+ unsigned int i;
+
for (i = 0; i < num_pages; i++)
set_page_dirty(pages[i]);
}
- cleaup_pagelistinfo(pagelistinfo);
+ cleanup_pagelistinfo(pagelistinfo);
}
diff --git a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c
index e823f1d5d177..030bec855d86 100644
--- a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c
+++ b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c
@@ -2070,7 +2070,7 @@ dump_phys_mem(void *virt_addr, u32 num_bytes)
struct page **pages;
u8 *kmapped_virt_ptr;
- /* Align virtAddr and endVirtAddr to 16 byte boundaries. */
+ /* Align virt_addr and end_virt_addr to 16 byte boundaries. */
virt_addr = (void *)((unsigned long)virt_addr & ~0x0fuL);
end_virt_addr = (void *)(((unsigned long)end_virt_addr + 15uL) &
@@ -3276,12 +3276,12 @@ vchiq_dump_service_use_state(VCHIQ_STATE_T *state)
if (only_nonzero && !service_ptr->service_use_count)
continue;
- if (service_ptr->srvstate != VCHIQ_SRVSTATE_FREE) {
- service_data[j].fourcc = service_ptr->base.fourcc;
- service_data[j].clientid = service_ptr->client_id;
- service_data[j++].use_count = service_ptr->
- service_use_count;
- }
+ if (service_ptr->srvstate == VCHIQ_SRVSTATE_FREE)
+ continue;
+
+ service_data[j].fourcc = service_ptr->base.fourcc;
+ service_data[j].clientid = service_ptr->client_id;
+ service_data[j++].use_count = service_ptr->service_use_count;
}
read_unlock_bh(&arm_state->susp_res_lock);
diff --git a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_core.c b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_core.c
index 4f9e738abddf..486be990d7fc 100644
--- a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_core.c
+++ b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_core.c
@@ -175,7 +175,7 @@ find_service_by_handle(VCHIQ_SERVICE_HANDLE_T handle)
service = handle_to_service(handle);
if (service && (service->srvstate != VCHIQ_SRVSTATE_FREE) &&
(service->handle == handle)) {
- BUG_ON(service->ref_count == 0);
+ WARN_ON(service->ref_count == 0);
service->ref_count++;
} else
service = NULL;
@@ -197,7 +197,7 @@ find_service_by_port(VCHIQ_STATE_T *state, int localport)
spin_lock(&service_spinlock);
service = state->services[localport];
if (service && (service->srvstate != VCHIQ_SRVSTATE_FREE)) {
- BUG_ON(service->ref_count == 0);
+ WARN_ON(service->ref_count == 0);
service->ref_count++;
} else
service = NULL;
@@ -221,7 +221,7 @@ find_service_for_instance(VCHIQ_INSTANCE_T instance,
if (service && (service->srvstate != VCHIQ_SRVSTATE_FREE) &&
(service->handle == handle) &&
(service->instance == instance)) {
- BUG_ON(service->ref_count == 0);
+ WARN_ON(service->ref_count == 0);
service->ref_count++;
} else
service = NULL;
@@ -246,7 +246,7 @@ find_closed_service_for_instance(VCHIQ_INSTANCE_T instance,
(service->srvstate == VCHIQ_SRVSTATE_CLOSED)) &&
(service->handle == handle) &&
(service->instance == instance)) {
- BUG_ON(service->ref_count == 0);
+ WARN_ON(service->ref_count == 0);
service->ref_count++;
} else
service = NULL;
@@ -273,7 +273,7 @@ next_service_by_instance(VCHIQ_STATE_T *state, VCHIQ_INSTANCE_T instance,
if (srv && (srv->srvstate != VCHIQ_SRVSTATE_FREE) &&
(srv->instance == instance)) {
service = srv;
- BUG_ON(service->ref_count == 0);
+ WARN_ON(service->ref_count == 0);
service->ref_count++;
break;
}
@@ -289,9 +289,11 @@ void
lock_service(VCHIQ_SERVICE_T *service)
{
spin_lock(&service_spinlock);
- BUG_ON(!service || (service->ref_count == 0));
- if (service)
+ WARN_ON(!service);
+ if (service) {
+ WARN_ON(service->ref_count == 0);
service->ref_count++;
+ }
spin_unlock(&service_spinlock);
}
@@ -299,17 +301,24 @@ void
unlock_service(VCHIQ_SERVICE_T *service)
{
spin_lock(&service_spinlock);
- BUG_ON(!service || (service->ref_count == 0));
- if (service && service->ref_count) {
- service->ref_count--;
- if (!service->ref_count) {
- VCHIQ_STATE_T *state = service->state;
-
- BUG_ON(service->srvstate != VCHIQ_SRVSTATE_FREE);
- state->services[service->localport] = NULL;
- } else
- service = NULL;
+ if (!service) {
+ WARN(1, "%s: service is NULL\n", __func__);
+ goto unlock;
+ }
+ if (!service->ref_count) {
+ WARN(1, "%s: ref_count is zero\n", __func__);
+ goto unlock;
}
+ service->ref_count--;
+ if (!service->ref_count) {
+ VCHIQ_STATE_T *state = service->state;
+
+ WARN_ON(service->srvstate != VCHIQ_SRVSTATE_FREE);
+ state->services[service->localport] = NULL;
+ } else {
+ service = NULL;
+ }
+unlock:
spin_unlock(&service_spinlock);
if (service && service->userdata_term)
@@ -591,8 +600,10 @@ reserve_space(VCHIQ_STATE_T *state, size_t space, int is_blocking)
return NULL; /* No space available */
}
- BUG_ON(tx_pos ==
- (state->slot_queue_available * VCHIQ_SLOT_SIZE));
+ if (tx_pos == (state->slot_queue_available * VCHIQ_SLOT_SIZE)) {
+ pr_warn("%s: invalid tx_pos: %d\n", __func__, tx_pos);
+ return NULL;
+ }
slot_index = local->slot_queue[
SLOT_QUEUE_INDEX_FROM_POS(tx_pos) &
@@ -822,9 +833,14 @@ queue_message(VCHIQ_STATE_T *state, VCHIQ_SERVICE_T *service,
if (type == VCHIQ_MSG_DATA) {
int tx_end_index;
- BUG_ON(!service);
- BUG_ON((flags & (QMFLAGS_NO_MUTEX_LOCK |
- QMFLAGS_NO_MUTEX_UNLOCK)) != 0);
+ if (!service) {
+ WARN(1, "%s: service is NULL\n", __func__);
+ mutex_unlock(&state->slot_mutex);
+ return VCHIQ_ERROR;
+ }
+
+ WARN_ON((flags & (QMFLAGS_NO_MUTEX_LOCK |
+ QMFLAGS_NO_MUTEX_UNLOCK)) != 0);
if (service->closing) {
/* The service has been closed */
@@ -923,9 +939,8 @@ queue_message(VCHIQ_STATE_T *state, VCHIQ_SERVICE_T *service,
header, size, VCHIQ_MSG_SRCPORT(msgid),
VCHIQ_MSG_DSTPORT(msgid));
- BUG_ON(!service);
- BUG_ON((flags & (QMFLAGS_NO_MUTEX_LOCK |
- QMFLAGS_NO_MUTEX_UNLOCK)) != 0);
+ WARN_ON((flags & (QMFLAGS_NO_MUTEX_LOCK |
+ QMFLAGS_NO_MUTEX_UNLOCK)) != 0);
callback_result =
copy_message_data(copy_callback, context,
@@ -1376,7 +1391,6 @@ resolve_bulks(VCHIQ_SERVICE_T *service, VCHIQ_BULK_QUEUE_T *queue)
{
VCHIQ_STATE_T *state = service->state;
int resolved = 0;
- int rc;
while ((queue->process != queue->local_insert) &&
(queue->process != queue->remote_insert)) {
@@ -1392,8 +1406,7 @@ resolve_bulks(VCHIQ_SERVICE_T *service, VCHIQ_BULK_QUEUE_T *queue)
WARN_ON(!((int)(queue->local_insert - queue->process) > 0));
WARN_ON(!((int)(queue->remote_insert - queue->process) > 0));
- rc = mutex_lock_killable(&state->bulk_transfer_mutex);
- if (rc != 0)
+ if (mutex_lock_killable(&state->bulk_transfer_mutex))
break;
vchiq_transfer_bulk(bulk);
@@ -1952,9 +1965,14 @@ parse_rx_slots(VCHIQ_STATE_T *state)
mutex_unlock(&service->bulk_mutex);
break;
}
-
- BUG_ON(queue->process == queue->local_insert);
- BUG_ON(queue->process != queue->remote_insert);
+ if (queue->process != queue->remote_insert) {
+ pr_err("%s: p %x != ri %x\n",
+ __func__,
+ queue->process,
+ queue->remote_insert);
+ mutex_unlock(&service->bulk_mutex);
+ goto bail_not_ready;
+ }
bulk = &queue->bulks[
BULK_INDEX(queue->remote_insert)];
@@ -2139,7 +2157,6 @@ slot_handler_func(void *v)
vchiq_log_error(vchiq_core_log_level,
"Failed to send RESUME "
"message");
- BUG();
}
break;
@@ -2351,13 +2368,17 @@ vchiq_init_state(VCHIQ_STATE_T *state, VCHIQ_SLOT_ZERO_T *slot_zero,
VCHIQ_SHARED_STATE_T *remote;
VCHIQ_STATUS_T status;
char threadname[16];
- static int id;
int i;
vchiq_log_warning(vchiq_core_log_level,
"%s: slot_zero = %pK, is_master = %d",
__func__, slot_zero, is_master);
+ if (vchiq_states[0]) {
+ pr_err("%s: VCHIQ state already initialized\n", __func__);
+ return VCHIQ_ERROR;
+ }
+
/* Check the input configuration */
if (slot_zero->magic != VCHIQ_MAGIC) {
@@ -2439,7 +2460,6 @@ vchiq_init_state(VCHIQ_STATE_T *state, VCHIQ_SLOT_ZERO_T *slot_zero,
memset(state, 0, sizeof(VCHIQ_STATE_T));
- state->id = id++;
state->is_master = is_master;
/*
@@ -2558,8 +2578,7 @@ vchiq_init_state(VCHIQ_STATE_T *state, VCHIQ_SLOT_ZERO_T *slot_zero,
set_user_nice(state->sync_thread, -20);
wake_up_process(state->sync_thread);
- BUG_ON(state->id >= VCHIQ_MAX_STATES);
- vchiq_states[state->id] = state;
+ vchiq_states[0] = state;
/* Indicate readiness to the other side */
local->initialised = 1;
@@ -3185,7 +3204,7 @@ vchiq_close_service(VCHIQ_SERVICE_HANDLE_T handle)
if (current == service->state->slot_handler_thread) {
status = vchiq_close_service_internal(service,
0/*!close_recvd*/);
- BUG_ON(status == VCHIQ_RETRY);
+ WARN_ON(status == VCHIQ_RETRY);
} else {
/* Mark the service for termination by the slot handler */
request_poll(service->state, service, VCHIQ_POLL_TERMINATE);
@@ -3247,7 +3266,7 @@ vchiq_remove_service(VCHIQ_SERVICE_HANDLE_T handle)
status = vchiq_close_service_internal(service,
0/*!close_recvd*/);
- BUG_ON(status == VCHIQ_RETRY);
+ WARN_ON(status == VCHIQ_RETRY);
} else {
/* Mark the service for removal by the slot handler */
request_poll(service->state, service, VCHIQ_POLL_REMOVE);
diff --git a/drivers/staging/vme/devices/vme_pio2.h b/drivers/staging/vme/devices/vme_pio2.h
index 5577df3199e7..ac4a4bad4091 100644
--- a/drivers/staging/vme/devices/vme_pio2.h
+++ b/drivers/staging/vme/devices/vme_pio2.h
@@ -68,38 +68,38 @@ static const int PIO2_CHANNEL_BANK[32] = { 0, 0, 0, 0, 0, 0, 0, 0,
2, 2, 2, 2, 2, 2, 2, 2,
3, 3, 3, 3, 3, 3, 3, 3 };
-#define PIO2_CHANNEL0_BIT (1 << 0)
-#define PIO2_CHANNEL1_BIT (1 << 1)
-#define PIO2_CHANNEL2_BIT (1 << 2)
-#define PIO2_CHANNEL3_BIT (1 << 3)
-#define PIO2_CHANNEL4_BIT (1 << 4)
-#define PIO2_CHANNEL5_BIT (1 << 5)
-#define PIO2_CHANNEL6_BIT (1 << 6)
-#define PIO2_CHANNEL7_BIT (1 << 7)
-#define PIO2_CHANNEL8_BIT (1 << 0)
-#define PIO2_CHANNEL9_BIT (1 << 1)
-#define PIO2_CHANNEL10_BIT (1 << 2)
-#define PIO2_CHANNEL11_BIT (1 << 3)
-#define PIO2_CHANNEL12_BIT (1 << 4)
-#define PIO2_CHANNEL13_BIT (1 << 5)
-#define PIO2_CHANNEL14_BIT (1 << 6)
-#define PIO2_CHANNEL15_BIT (1 << 7)
-#define PIO2_CHANNEL16_BIT (1 << 0)
-#define PIO2_CHANNEL17_BIT (1 << 1)
-#define PIO2_CHANNEL18_BIT (1 << 2)
-#define PIO2_CHANNEL19_BIT (1 << 3)
-#define PIO2_CHANNEL20_BIT (1 << 4)
-#define PIO2_CHANNEL21_BIT (1 << 5)
-#define PIO2_CHANNEL22_BIT (1 << 6)
-#define PIO2_CHANNEL23_BIT (1 << 7)
-#define PIO2_CHANNEL24_BIT (1 << 0)
-#define PIO2_CHANNEL25_BIT (1 << 1)
-#define PIO2_CHANNEL26_BIT (1 << 2)
-#define PIO2_CHANNEL27_BIT (1 << 3)
-#define PIO2_CHANNEL28_BIT (1 << 4)
-#define PIO2_CHANNEL29_BIT (1 << 5)
-#define PIO2_CHANNEL30_BIT (1 << 6)
-#define PIO2_CHANNEL31_BIT (1 << 7)
+#define PIO2_CHANNEL0_BIT BIT(0)
+#define PIO2_CHANNEL1_BIT BIT(1)
+#define PIO2_CHANNEL2_BIT BIT(2)
+#define PIO2_CHANNEL3_BIT BIT(3)
+#define PIO2_CHANNEL4_BIT BIT(4)
+#define PIO2_CHANNEL5_BIT BIT(5)
+#define PIO2_CHANNEL6_BIT BIT(6)
+#define PIO2_CHANNEL7_BIT BIT(7)
+#define PIO2_CHANNEL8_BIT BIT(0)
+#define PIO2_CHANNEL9_BIT BIT(1)
+#define PIO2_CHANNEL10_BIT BIT(2)
+#define PIO2_CHANNEL11_BIT BIT(3)
+#define PIO2_CHANNEL12_BIT BIT(4)
+#define PIO2_CHANNEL13_BIT BIT(5)
+#define PIO2_CHANNEL14_BIT BIT(6)
+#define PIO2_CHANNEL15_BIT BIT(7)
+#define PIO2_CHANNEL16_BIT BIT(0)
+#define PIO2_CHANNEL17_BIT BIT(1)
+#define PIO2_CHANNEL18_BIT BIT(2)
+#define PIO2_CHANNEL19_BIT BIT(3)
+#define PIO2_CHANNEL20_BIT BIT(4)
+#define PIO2_CHANNEL21_BIT BIT(5)
+#define PIO2_CHANNEL22_BIT BIT(6)
+#define PIO2_CHANNEL23_BIT BIT(7)
+#define PIO2_CHANNEL24_BIT BIT(0)
+#define PIO2_CHANNEL25_BIT BIT(1)
+#define PIO2_CHANNEL26_BIT BIT(2)
+#define PIO2_CHANNEL27_BIT BIT(3)
+#define PIO2_CHANNEL28_BIT BIT(4)
+#define PIO2_CHANNEL29_BIT BIT(5)
+#define PIO2_CHANNEL30_BIT BIT(6)
+#define PIO2_CHANNEL31_BIT BIT(7)
static const int PIO2_CHANNEL_BIT[32] = { PIO2_CHANNEL0_BIT, PIO2_CHANNEL1_BIT,
PIO2_CHANNEL2_BIT, PIO2_CHANNEL3_BIT,
@@ -120,12 +120,12 @@ static const int PIO2_CHANNEL_BIT[32] = { PIO2_CHANNEL0_BIT, PIO2_CHANNEL1_BIT,
};
/* PIO2_REGS_INT_STAT_CNTR (0xc) */
-#define PIO2_COUNTER0 (1 << 0)
-#define PIO2_COUNTER1 (1 << 1)
-#define PIO2_COUNTER2 (1 << 2)
-#define PIO2_COUNTER3 (1 << 3)
-#define PIO2_COUNTER4 (1 << 4)
-#define PIO2_COUNTER5 (1 << 5)
+#define PIO2_COUNTER0 BIT(0)
+#define PIO2_COUNTER1 BIT(1)
+#define PIO2_COUNTER2 BIT(2)
+#define PIO2_COUNTER3 BIT(3)
+#define PIO2_COUNTER4 BIT(4)
+#define PIO2_COUNTER5 BIT(5)
static const int PIO2_COUNTER[6] = { PIO2_COUNTER0, PIO2_COUNTER1,
PIO2_COUNTER2, PIO2_COUNTER3,
@@ -133,8 +133,8 @@ static const int PIO2_COUNTER[6] = { PIO2_COUNTER0, PIO2_COUNTER1,
/* PIO2_REGS_CTRL (0x18) */
#define PIO2_VME_INT_MASK 0x7
-#define PIO2_LED (1 << 6)
-#define PIO2_LOOP (1 << 7)
+#define PIO2_LED BIT(6)
+#define PIO2_LOOP BIT(7)
/* PIO2_REGS_VME_VECTOR (0x19) */
#define PIO2_VME_VECTOR_SPUR 0x0
diff --git a/drivers/staging/vt6655/card.c b/drivers/staging/vt6655/card.c
index 5463cf869d1b..f5db2b3d9045 100644
--- a/drivers/staging/vt6655/card.c
+++ b/drivers/staging/vt6655/card.c
@@ -913,7 +913,7 @@ u64 CARDqGetTSFOffset(unsigned char byRxRate, u64 qwTSF1, u64 qwTSF2)
{
unsigned short wRxBcnTSFOffst;
- wRxBcnTSFOffst = cwRXBCNTSFOff[byRxRate%MAX_RATE];
+ wRxBcnTSFOffst = cwRXBCNTSFOff[byRxRate % MAX_RATE];
qwTSF2 += (u64)wRxBcnTSFOffst;
diff --git a/drivers/staging/vt6655/card.h b/drivers/staging/vt6655/card.h
index 44420b5a445f..1a04dbb57d42 100644
--- a/drivers/staging/vt6655/card.h
+++ b/drivers/staging/vt6655/card.h
@@ -63,26 +63,26 @@ typedef enum _CARD_STATUS_TYPE {
struct vnt_private;
-void CARDvSetRSPINF(struct vnt_private *, u8);
-void CARDvUpdateBasicTopRate(struct vnt_private *);
-bool CARDbIsOFDMinBasicRate(struct vnt_private *);
-void CARDvSetLoopbackMode(struct vnt_private *, unsigned short wLoopbackMode);
-bool CARDbSoftwareReset(struct vnt_private *);
-void CARDvSetFirstNextTBTT(struct vnt_private *,
+void CARDvSetRSPINF(struct vnt_private *priv, u8 bb_type);
+void CARDvUpdateBasicTopRate(struct vnt_private *priv);
+bool CARDbIsOFDMinBasicRate(struct vnt_private *priv);
+void CARDvSetLoopbackMode(struct vnt_private *priv, unsigned short wLoopbackMode);
+bool CARDbSoftwareReset(struct vnt_private *priv);
+void CARDvSetFirstNextTBTT(struct vnt_private *priv,
unsigned short wBeaconInterval);
-void CARDvUpdateNextTBTT(struct vnt_private *, u64 qwTSF,
+void CARDvUpdateNextTBTT(struct vnt_private *priv, u64 qwTSF,
unsigned short wBeaconInterval);
-bool CARDbGetCurrentTSF(struct vnt_private *, u64 *pqwCurrTSF);
+bool CARDbGetCurrentTSF(struct vnt_private *priv, u64 *pqwCurrTSF);
u64 CARDqGetNextTBTT(u64 qwTSF, unsigned short wBeaconInterval);
u64 CARDqGetTSFOffset(unsigned char byRxRate, u64 qwTSF1, u64 qwTSF2);
-unsigned char CARDbyGetPktType(struct vnt_private *);
-void CARDvSafeResetTx(struct vnt_private *);
-void CARDvSafeResetRx(struct vnt_private *);
-bool CARDbRadioPowerOff(struct vnt_private *);
-bool CARDbRadioPowerOn(struct vnt_private *);
-bool CARDbSetPhyParameter(struct vnt_private *, u8);
-bool CARDbUpdateTSF(struct vnt_private *, unsigned char byRxRate,
+unsigned char CARDbyGetPktType(struct vnt_private *priv);
+void CARDvSafeResetTx(struct vnt_private *priv);
+void CARDvSafeResetRx(struct vnt_private *priv);
+bool CARDbRadioPowerOff(struct vnt_private *priv);
+bool CARDbRadioPowerOn(struct vnt_private *priv);
+bool CARDbSetPhyParameter(struct vnt_private *priv, u8 bb_type);
+bool CARDbUpdateTSF(struct vnt_private *priv, unsigned char byRxRate,
u64 qwBSSTimestamp);
-bool CARDbSetBeaconPeriod(struct vnt_private *, unsigned short wBeaconInterval);
+bool CARDbSetBeaconPeriod(struct vnt_private *priv, unsigned short wBeaconInterval);
#endif /* __CARD_H__ */
diff --git a/drivers/staging/vt6655/channel.h b/drivers/staging/vt6655/channel.h
index 2621dfabff06..8fe70760e548 100644
--- a/drivers/staging/vt6655/channel.h
+++ b/drivers/staging/vt6655/channel.h
@@ -21,8 +21,8 @@
#include "card.h"
-void vnt_init_bands(struct vnt_private *);
+void vnt_init_bands(struct vnt_private *priv);
-bool set_channel(struct vnt_private *, struct ieee80211_channel *);
+bool set_channel(struct vnt_private *priv, struct ieee80211_channel *ch);
#endif /* _CHANNEL_H_ */
diff --git a/drivers/staging/vt6655/device_main.c b/drivers/staging/vt6655/device_main.c
index da0f71191009..9fcf2e223f71 100644
--- a/drivers/staging/vt6655/device_main.c
+++ b/drivers/staging/vt6655/device_main.c
@@ -157,7 +157,7 @@ static void vt6655_remove(struct pci_dev *pcid)
{
struct vnt_private *priv = pci_get_drvdata(pcid);
- if (priv == NULL)
+ if (!priv)
return;
device_free_info(priv);
}
@@ -453,7 +453,7 @@ static bool device_init_rings(struct vnt_private *priv)
priv->opts.tx_descs[0] * sizeof(struct vnt_tx_desc) +
priv->opts.tx_descs[1] * sizeof(struct vnt_tx_desc),
&priv->pool_dma, GFP_ATOMIC);
- if (vir_pool == NULL) {
+ if (!vir_pool) {
dev_err(&priv->pcid->dev, "allocate desc dma memory failed\n");
return false;
}
@@ -1018,7 +1018,6 @@ static void vnt_interrupt_process(struct vnt_private *priv)
}
/* TODO: adhoc PS mode */
-
}
if (isr & ISR_BNTX) {
@@ -1311,8 +1310,8 @@ static int vnt_config(struct ieee80211_hw *hw, u32 changed)
}
static void vnt_bss_info_changed(struct ieee80211_hw *hw,
- struct ieee80211_vif *vif, struct ieee80211_bss_conf *conf,
- u32 changed)
+ struct ieee80211_vif *vif,
+ struct ieee80211_bss_conf *conf, u32 changed)
{
struct vnt_private *priv = hw->priv;
@@ -1402,7 +1401,7 @@ static void vnt_bss_info_changed(struct ieee80211_hw *hw,
}
static u64 vnt_prepare_multicast(struct ieee80211_hw *hw,
- struct netdev_hw_addr_list *mc_list)
+ struct netdev_hw_addr_list *mc_list)
{
struct vnt_private *priv = hw->priv;
struct netdev_hw_addr *ha;
@@ -1421,7 +1420,8 @@ static u64 vnt_prepare_multicast(struct ieee80211_hw *hw,
}
static void vnt_configure(struct ieee80211_hw *hw,
- unsigned int changed_flags, unsigned int *total_flags, u64 multicast)
+ unsigned int changed_flags,
+ unsigned int *total_flags, u64 multicast)
{
struct vnt_private *priv = hw->priv;
u8 rx_mode = 0;
@@ -1482,8 +1482,8 @@ static void vnt_configure(struct ieee80211_hw *hw,
}
static int vnt_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
- struct ieee80211_vif *vif, struct ieee80211_sta *sta,
- struct ieee80211_key_conf *key)
+ struct ieee80211_vif *vif, struct ieee80211_sta *sta,
+ struct ieee80211_key_conf *key)
{
struct vnt_private *priv = hw->priv;
@@ -1702,7 +1702,6 @@ static int vt6655_suspend(struct pci_dev *pcid, pm_message_t state)
static int vt6655_resume(struct pci_dev *pcid)
{
-
pci_set_power_state(pcid, PCI_D0);
pci_enable_wake(pcid, PCI_D0, 0);
pci_restore_state(pcid);
diff --git a/drivers/staging/vt6655/key.c b/drivers/staging/vt6655/key.c
index dad9e292d4da..d7ede73a1a01 100644
--- a/drivers/staging/vt6655/key.c
+++ b/drivers/staging/vt6655/key.c
@@ -27,8 +27,8 @@
#include "mac.h"
static int vnt_set_keymode(struct ieee80211_hw *hw, u8 *mac_addr,
- struct ieee80211_key_conf *key, u32 key_type, u32 mode,
- bool onfly_latch)
+ struct ieee80211_key_conf *key, u32 key_type,
+ u32 mode, bool onfly_latch)
{
struct vnt_private *priv = hw->priv;
u8 broadcast[6] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
diff --git a/drivers/staging/vt6655/mac.h b/drivers/staging/vt6655/mac.h
index 33b758cb79d4..db401e32ae23 100644
--- a/drivers/staging/vt6655/mac.h
+++ b/drivers/staging/vt6655/mac.h
@@ -885,57 +885,57 @@ do { \
#define MACvSetRFLE_LatchBase(iobase) \
MACvWordRegBitsOn(iobase, MAC_REG_SOFTPWRCTL, SOFTPWRCTL_RFLEOPT)
-bool MACbIsRegBitsOn(struct vnt_private *, unsigned char byRegOfs,
+bool MACbIsRegBitsOn(struct vnt_private *priv, unsigned char byRegOfs,
unsigned char byTestBits);
-bool MACbIsRegBitsOff(struct vnt_private *, unsigned char byRegOfs,
+bool MACbIsRegBitsOff(struct vnt_private *priv, unsigned char byRegOfs,
unsigned char byTestBits);
-bool MACbIsIntDisable(struct vnt_private *);
+bool MACbIsIntDisable(struct vnt_private *priv);
-void MACvSetShortRetryLimit(struct vnt_private *, unsigned char byRetryLimit);
+void MACvSetShortRetryLimit(struct vnt_private *priv, unsigned char byRetryLimit);
-void MACvSetLongRetryLimit(struct vnt_private *, unsigned char byRetryLimit);
-void MACvGetLongRetryLimit(struct vnt_private *,
+void MACvSetLongRetryLimit(struct vnt_private *priv, unsigned char byRetryLimit);
+void MACvGetLongRetryLimit(struct vnt_private *priv,
unsigned char *pbyRetryLimit);
-void MACvSetLoopbackMode(struct vnt_private *, unsigned char byLoopbackMode);
+void MACvSetLoopbackMode(struct vnt_private *priv, unsigned char byLoopbackMode);
-void MACvSaveContext(struct vnt_private *, unsigned char *pbyCxtBuf);
-void MACvRestoreContext(struct vnt_private *, unsigned char *pbyCxtBuf);
+void MACvSaveContext(struct vnt_private *priv, unsigned char *pbyCxtBuf);
+void MACvRestoreContext(struct vnt_private *priv, unsigned char *pbyCxtBuf);
-bool MACbSoftwareReset(struct vnt_private *);
-bool MACbSafeSoftwareReset(struct vnt_private *);
-bool MACbSafeRxOff(struct vnt_private *);
-bool MACbSafeTxOff(struct vnt_private *);
-bool MACbSafeStop(struct vnt_private *);
-bool MACbShutdown(struct vnt_private *);
-void MACvInitialize(struct vnt_private *);
-void MACvSetCurrRx0DescAddr(struct vnt_private *,
+bool MACbSoftwareReset(struct vnt_private *priv);
+bool MACbSafeSoftwareReset(struct vnt_private *priv);
+bool MACbSafeRxOff(struct vnt_private *priv);
+bool MACbSafeTxOff(struct vnt_private *priv);
+bool MACbSafeStop(struct vnt_private *priv);
+bool MACbShutdown(struct vnt_private *priv);
+void MACvInitialize(struct vnt_private *priv);
+void MACvSetCurrRx0DescAddr(struct vnt_private *priv,
u32 curr_desc_addr);
-void MACvSetCurrRx1DescAddr(struct vnt_private *,
+void MACvSetCurrRx1DescAddr(struct vnt_private *priv,
u32 curr_desc_addr);
-void MACvSetCurrTXDescAddr(int iTxType, struct vnt_private *,
+void MACvSetCurrTXDescAddr(int iTxType, struct vnt_private *priv,
u32 curr_desc_addr);
-void MACvSetCurrTx0DescAddrEx(struct vnt_private *,
+void MACvSetCurrTx0DescAddrEx(struct vnt_private *priv,
u32 curr_desc_addr);
-void MACvSetCurrAC0DescAddrEx(struct vnt_private *,
+void MACvSetCurrAC0DescAddrEx(struct vnt_private *priv,
u32 curr_desc_addr);
-void MACvSetCurrSyncDescAddrEx(struct vnt_private *,
+void MACvSetCurrSyncDescAddrEx(struct vnt_private *priv,
u32 curr_desc_addr);
-void MACvSetCurrATIMDescAddrEx(struct vnt_private *,
+void MACvSetCurrATIMDescAddrEx(struct vnt_private *priv,
u32 curr_desc_addr);
-void MACvTimer0MicroSDelay(struct vnt_private *, unsigned int uDelay);
-void MACvOneShotTimer1MicroSec(struct vnt_private *, unsigned int uDelayTime);
+void MACvTimer0MicroSDelay(struct vnt_private *priv, unsigned int uDelay);
+void MACvOneShotTimer1MicroSec(struct vnt_private *priv, unsigned int uDelayTime);
-void MACvSetMISCFifo(struct vnt_private *, unsigned short wOffset,
+void MACvSetMISCFifo(struct vnt_private *priv, unsigned short wOffset,
u32 dwData);
-bool MACbPSWakeup(struct vnt_private *);
+bool MACbPSWakeup(struct vnt_private *priv);
-void MACvSetKeyEntry(struct vnt_private *, unsigned short wKeyCtl,
+void MACvSetKeyEntry(struct vnt_private *priv, unsigned short wKeyCtl,
unsigned int uEntryIdx, unsigned int uKeyIdx,
unsigned char *pbyAddr, u32 *pdwKey,
unsigned char byLocalID);
-void MACvDisableKeyEntry(struct vnt_private *, unsigned int uEntryIdx);
+void MACvDisableKeyEntry(struct vnt_private *priv, unsigned int uEntryIdx);
#endif /* __MAC_H__ */
diff --git a/drivers/staging/vt6655/power.h b/drivers/staging/vt6655/power.h
index dfcb0ca8b448..f360c5966523 100644
--- a/drivers/staging/vt6655/power.h
+++ b/drivers/staging/vt6655/power.h
@@ -31,20 +31,10 @@
#define PS_FAST_INTERVAL 1 /* Fast power saving listen interval */
#define PS_MAX_INTERVAL 4 /* MAX power saving listen interval */
-void
-PSvDisablePowerSaving(
- struct vnt_private *
-);
+void PSvDisablePowerSaving(struct vnt_private *priv);
-void
-PSvEnablePowerSaving(
- struct vnt_private *,
- unsigned short wListenInterval
-);
+void PSvEnablePowerSaving(struct vnt_private *priv, unsigned short wListenInterval);
-bool
-PSbIsNextTBTTWakeUp(
- struct vnt_private *
-);
+bool PSbIsNextTBTTWakeUp(struct vnt_private *priv);
#endif /* __POWER_H__ */
diff --git a/drivers/staging/vt6655/rf.h b/drivers/staging/vt6655/rf.h
index 37600093cab2..ba222301d49d 100644
--- a/drivers/staging/vt6655/rf.h
+++ b/drivers/staging/vt6655/rf.h
@@ -68,28 +68,28 @@
/*--------------------- Export Functions --------------------------*/
-bool IFRFbWriteEmbedded(struct vnt_private *, unsigned long dwData);
-bool RFbSelectChannel(struct vnt_private *, unsigned char byRFType, u16);
+bool IFRFbWriteEmbedded(struct vnt_private *priv, unsigned long dwData);
+bool RFbSelectChannel(struct vnt_private *priv, unsigned char byRFType, u16 byChannel);
bool RFbInit(
- struct vnt_private *
+ struct vnt_private *priv
);
-bool RFvWriteWakeProgSyn(struct vnt_private *, unsigned char byRFType, u16);
-bool RFbSetPower(struct vnt_private *, unsigned int rate, u16);
+bool RFvWriteWakeProgSyn(struct vnt_private *priv, unsigned char byRFType, u16 uChannel);
+bool RFbSetPower(struct vnt_private *priv, unsigned int rate, u16 uCH);
bool RFbRawSetPower(
- struct vnt_private *,
+ struct vnt_private *priv,
unsigned char byPwr,
unsigned int rate
);
void
RFvRSSITodBm(
- struct vnt_private *,
+ struct vnt_private *priv,
unsigned char byCurrRSSI,
long *pldBm
);
/* {{ RobertYu: 20050104 */
-bool RFbAL7230SelectChannelPostProcess(struct vnt_private *, u16, u16);
+bool RFbAL7230SelectChannelPostProcess(struct vnt_private *priv, u16 byOldChannel, u16 byNewChannel);
/* }} RobertYu */
#endif /* __RF_H__ */
diff --git a/drivers/staging/vt6656/card.c b/drivers/staging/vt6656/card.c
index 0e5a99375099..c61422ea8846 100644
--- a/drivers/staging/vt6656/card.c
+++ b/drivers/staging/vt6656/card.c
@@ -359,35 +359,18 @@ void vnt_update_ifs(struct vnt_private *priv)
priv->sifs = C_SIFS_A;
priv->difs = C_SIFS_A + 2 * C_SLOT_SHORT;
max_min = 4;
- } else if (priv->packet_type == PK_TYPE_11B) {
- priv->slot = C_SLOT_LONG;
- priv->sifs = C_SIFS_BG;
- priv->difs = C_SIFS_BG + 2 * C_SLOT_LONG;
- max_min = 5;
- } else {/* PK_TYPE_11GA & PK_TYPE_11GB */
- bool ofdm_rate = false;
- unsigned int ii = 0;
-
+ } else {
priv->sifs = C_SIFS_BG;
- if (priv->short_slot_time)
+ if (priv->short_slot_time) {
priv->slot = C_SLOT_SHORT;
- else
+ max_min = 4;
+ } else {
priv->slot = C_SLOT_LONG;
-
- priv->difs = C_SIFS_BG + 2 * priv->slot;
-
- for (ii = RATE_54M; ii >= RATE_6M; ii--) {
- if (priv->basic_rates & ((u32)(0x1 << ii))) {
- ofdm_rate = true;
- break;
- }
+ max_min = 5;
}
- if (ofdm_rate)
- max_min = 4;
- else
- max_min = 5;
+ priv->difs = C_SIFS_BG + 2 * priv->slot;
}
priv->eifs = C_EIFS;
diff --git a/drivers/staging/vt6656/main_usb.c b/drivers/staging/vt6656/main_usb.c
index 028f54b453d0..095b85567306 100644
--- a/drivers/staging/vt6656/main_usb.c
+++ b/drivers/staging/vt6656/main_usb.c
@@ -513,6 +513,9 @@ static int vnt_start(struct ieee80211_hw *hw)
goto free_all;
}
+ if (vnt_key_init_table(priv))
+ goto free_all;
+
priv->int_interval = 1; /* bInterval is set to 1 */
vnt_int_start_interrupt(priv);
@@ -634,7 +637,6 @@ static int vnt_config(struct ieee80211_hw *hw, u32 changed)
{
struct vnt_private *priv = hw->priv;
struct ieee80211_conf *conf = &hw->conf;
- u8 bb_type;
if (changed & IEEE80211_CONF_CHANGE_PS) {
if (conf->flags & IEEE80211_CONF_PS)
@@ -648,15 +650,9 @@ static int vnt_config(struct ieee80211_hw *hw, u32 changed)
vnt_set_channel(priv, conf->chandef.chan->hw_value);
if (conf->chandef.chan->band == NL80211_BAND_5GHZ)
- bb_type = BB_TYPE_11A;
+ priv->bb_type = BB_TYPE_11A;
else
- bb_type = BB_TYPE_11G;
-
- if (priv->bb_type != bb_type) {
- priv->bb_type = bb_type;
-
- vnt_set_bss_mode(priv);
- }
+ priv->bb_type = BB_TYPE_11G;
}
if (changed & IEEE80211_CONF_CHANGE_POWER) {
@@ -687,6 +683,7 @@ static void vnt_bss_info_changed(struct ieee80211_hw *hw,
priv->basic_rates = conf->basic_rates;
vnt_update_top_rates(priv);
+ vnt_set_bss_mode(priv);
dev_dbg(&priv->usb->dev, "basic rates %x\n", conf->basic_rates);
}
@@ -715,6 +712,7 @@ static void vnt_bss_info_changed(struct ieee80211_hw *hw,
priv->short_slot_time = false;
vnt_set_short_slot_time(priv);
+ vnt_update_ifs(priv);
vnt_set_vga_gain_offset(priv, priv->bb_vga[0]);
vnt_update_pre_ed_threshold(priv, false);
}
@@ -846,7 +844,6 @@ static void vnt_sw_scan_start(struct ieee80211_hw *hw,
{
struct vnt_private *priv = hw->priv;
- vnt_set_bss_mode(priv);
/* Set max sensitivity*/
vnt_update_pre_ed_threshold(priv, true);
}
diff --git a/drivers/staging/vt6656/rxtx.c b/drivers/staging/vt6656/rxtx.c
index 63413492e61d..a44abcce6fb4 100644
--- a/drivers/staging/vt6656/rxtx.c
+++ b/drivers/staging/vt6656/rxtx.c
@@ -114,7 +114,7 @@ static __le16 vnt_time_stamp_off(struct vnt_private *priv, u16 rate)
}
static u32 vnt_get_rsvtime(struct vnt_private *priv, u8 pkt_type,
- u32 frame_length, u16 rate, int need_ack)
+ u32 frame_length, u16 rate, int need_ack)
{
u32 data_time, ack_time;
@@ -135,30 +135,37 @@ static u32 vnt_get_rsvtime(struct vnt_private *priv, u8 pkt_type,
}
static __le16 vnt_rxtx_rsvtime_le16(struct vnt_private *priv, u8 pkt_type,
- u32 frame_length, u16 rate, int need_ack)
+ u32 frame_length, u16 rate, int need_ack)
{
return cpu_to_le16((u16)vnt_get_rsvtime(priv, pkt_type,
frame_length, rate, need_ack));
}
-static __le16 vnt_get_rtscts_rsvtime_le(struct vnt_private *priv,
- u8 rsv_type, u8 pkt_type, u32 frame_length, u16 current_rate)
+static __le16 vnt_get_rtscts_rsvtime_le(struct vnt_private *priv, u8 rsv_type,
+ u8 pkt_type, u32 frame_length,
+ u16 current_rate)
{
u32 rrv_time, rts_time, cts_time, ack_time, data_time;
- rrv_time = rts_time = cts_time = ack_time = data_time = 0;
+ rrv_time = 0;
+ rts_time = 0;
+ cts_time = 0;
+ ack_time = 0;
data_time = vnt_get_frame_time(priv->preamble_type, pkt_type,
frame_length, current_rate);
if (rsv_type == 0) {
- rts_time = vnt_get_frame_time(priv->preamble_type,
- pkt_type, 20, priv->top_cck_basic_rate);
- cts_time = ack_time = vnt_get_frame_time(priv->preamble_type,
- pkt_type, 14, priv->top_cck_basic_rate);
+ rts_time = vnt_get_frame_time(priv->preamble_type, pkt_type,
+ 20, priv->top_cck_basic_rate);
+ ack_time = vnt_get_frame_time(priv->preamble_type,
+ pkt_type, 14,
+ priv->top_cck_basic_rate);
+ cts_time = ack_time;
+
} else if (rsv_type == 1) {
- rts_time = vnt_get_frame_time(priv->preamble_type,
- pkt_type, 20, priv->top_cck_basic_rate);
+ rts_time = vnt_get_frame_time(priv->preamble_type, pkt_type,
+ 20, priv->top_cck_basic_rate);
cts_time = vnt_get_frame_time(priv->preamble_type, pkt_type,
14, priv->top_cck_basic_rate);
ack_time = vnt_get_frame_time(priv->preamble_type, pkt_type,
@@ -166,8 +173,11 @@ static __le16 vnt_get_rtscts_rsvtime_le(struct vnt_private *priv,
} else if (rsv_type == 2) {
rts_time = vnt_get_frame_time(priv->preamble_type, pkt_type,
20, priv->top_ofdm_basic_rate);
- cts_time = ack_time = vnt_get_frame_time(priv->preamble_type,
- pkt_type, 14, priv->top_ofdm_basic_rate);
+ ack_time = vnt_get_frame_time(priv->preamble_type,
+ pkt_type, 14,
+ priv->top_ofdm_basic_rate);
+ cts_time = ack_time;
+
} else if (rsv_type == 3) {
cts_time = vnt_get_frame_time(priv->preamble_type, pkt_type,
14, priv->top_cck_basic_rate);
@@ -184,18 +194,20 @@ static __le16 vnt_get_rtscts_rsvtime_le(struct vnt_private *priv,
return cpu_to_le16((u16)rrv_time);
}
-static __le16 vnt_get_duration_le(struct vnt_private *priv,
- u8 pkt_type, int need_ack)
+static __le16 vnt_get_duration_le(struct vnt_private *priv, u8 pkt_type,
+ int need_ack)
{
u32 ack_time = 0;
if (need_ack) {
if (pkt_type == PK_TYPE_11B)
ack_time = vnt_get_frame_time(priv->preamble_type,
- pkt_type, 14, priv->top_cck_basic_rate);
+ pkt_type, 14,
+ priv->top_cck_basic_rate);
else
ack_time = vnt_get_frame_time(priv->preamble_type,
- pkt_type, 14, priv->top_ofdm_basic_rate);
+ pkt_type, 14,
+ priv->top_ofdm_basic_rate);
return cpu_to_le16((u16)(priv->sifs + ack_time));
}
@@ -216,8 +228,8 @@ static __le16 vnt_get_rtscts_duration_le(struct vnt_usb_send_context *context,
case RTSDUR_BA:
case RTSDUR_BA_F0:
case RTSDUR_BA_F1:
- cts_time = vnt_get_frame_time(priv->preamble_type,
- pkt_type, 14, priv->top_cck_basic_rate);
+ cts_time = vnt_get_frame_time(priv->preamble_type, pkt_type,
+ 14, priv->top_cck_basic_rate);
dur_time = cts_time + 2 * priv->sifs +
vnt_get_rsvtime(priv, pkt_type,
frame_length, rate, need_ack);
@@ -226,8 +238,8 @@ static __le16 vnt_get_rtscts_duration_le(struct vnt_usb_send_context *context,
case RTSDUR_AA:
case RTSDUR_AA_F0:
case RTSDUR_AA_F1:
- cts_time = vnt_get_frame_time(priv->preamble_type,
- pkt_type, 14, priv->top_ofdm_basic_rate);
+ cts_time = vnt_get_frame_time(priv->preamble_type, pkt_type,
+ 14, priv->top_ofdm_basic_rate);
dur_time = cts_time + 2 * priv->sifs +
vnt_get_rsvtime(priv, pkt_type,
frame_length, rate, need_ack);
@@ -248,7 +260,7 @@ static __le16 vnt_get_rtscts_duration_le(struct vnt_usb_send_context *context,
}
static u16 vnt_mac_hdr_pos(struct vnt_usb_send_context *tx_context,
- struct ieee80211_hdr *hdr)
+ struct ieee80211_hdr *hdr)
{
u8 *head = tx_context->data + offsetof(struct vnt_tx_buffer, fifo_head);
u8 *hdr_pos = (u8 *)hdr;
@@ -263,7 +275,6 @@ static u16 vnt_mac_hdr_pos(struct vnt_usb_send_context *tx_context,
static u16 vnt_rxtx_datahead_g(struct vnt_usb_send_context *tx_context,
struct vnt_tx_datahead_g *buf)
{
-
struct vnt_private *priv = tx_context->priv;
struct ieee80211_hdr *hdr =
(struct ieee80211_hdr *)tx_context->skb->data;
@@ -274,7 +285,7 @@ static u16 vnt_rxtx_datahead_g(struct vnt_usb_send_context *tx_context,
/* Get SignalField,ServiceField,Length */
vnt_get_phy_field(priv, frame_len, rate, tx_context->pkt_type, &buf->a);
vnt_get_phy_field(priv, frame_len, priv->top_cck_basic_rate,
- PK_TYPE_11B, &buf->b);
+ PK_TYPE_11B, &buf->b);
/* Get Duration and TimeStamp */
if (ieee80211_is_pspoll(hdr->frame_control)) {
@@ -310,7 +321,7 @@ static u16 vnt_rxtx_datahead_g_fb(struct vnt_usb_send_context *tx_context,
vnt_get_phy_field(priv, frame_len, rate, tx_context->pkt_type, &buf->a);
vnt_get_phy_field(priv, frame_len, priv->top_cck_basic_rate,
- PK_TYPE_11B, &buf->b);
+ PK_TYPE_11B, &buf->b);
/* Get Duration and TimeStamp */
buf->duration_a = vnt_get_duration_le(priv, tx_context->pkt_type,
@@ -387,7 +398,7 @@ static u16 vnt_rxtx_datahead_ab(struct vnt_usb_send_context *tx_context,
}
static int vnt_fill_ieee80211_rts(struct vnt_usb_send_context *tx_context,
- struct ieee80211_rts *rts, __le16 duration)
+ struct ieee80211_rts *rts, __le16 duration)
{
struct ieee80211_hdr *hdr =
(struct ieee80211_hdr *)tx_context->skb->data;
@@ -499,8 +510,8 @@ static u16 vnt_rxtx_rts_a_fb_head(struct vnt_usb_send_context *tx_context,
u16 current_rate = tx_context->tx_rate;
u16 rts_frame_len = 20;
- vnt_get_phy_field(priv, rts_frame_len,
- priv->top_ofdm_basic_rate, tx_context->pkt_type, &buf->a);
+ vnt_get_phy_field(priv, rts_frame_len, priv->top_ofdm_basic_rate,
+ tx_context->pkt_type, &buf->a);
buf->duration = vnt_get_rtscts_duration_le(tx_context, RTSDUR_AA,
tx_context->pkt_type,
@@ -683,11 +694,10 @@ static u16 vnt_rxtx_ab(struct vnt_usb_send_context *tx_context,
}
static u16 vnt_generate_tx_parameter(struct vnt_usb_send_context *tx_context,
- struct vnt_tx_buffer *tx_buffer,
- struct vnt_mic_hdr **mic_hdr, u32 need_mic,
- bool need_rts)
+ struct vnt_tx_buffer *tx_buffer,
+ struct vnt_mic_hdr **mic_hdr, u32 need_mic,
+ bool need_rts)
{
-
if (tx_context->pkt_type == PK_TYPE_11GB ||
tx_context->pkt_type == PK_TYPE_11GA) {
if (need_rts) {
@@ -712,8 +722,9 @@ static u16 vnt_generate_tx_parameter(struct vnt_usb_send_context *tx_context,
}
static void vnt_fill_txkey(struct vnt_usb_send_context *tx_context,
- u8 *key_buffer, struct ieee80211_key_conf *tx_key, struct sk_buff *skb,
- u16 payload_len, struct vnt_mic_hdr *mic_hdr)
+ u8 *key_buffer, struct ieee80211_key_conf *tx_key,
+ struct sk_buff *skb, u16 payload_len,
+ struct vnt_mic_hdr *mic_hdr)
{
struct ieee80211_hdr *hdr = tx_context->hdr;
u64 pn64;
@@ -774,14 +785,12 @@ static void vnt_fill_txkey(struct vnt_usb_send_context *tx_context,
if (ieee80211_has_a4(hdr->frame_control))
ether_addr_copy(mic_hdr->addr4, hdr->addr4);
-
memcpy(key_buffer, tx_key->key, WLAN_KEY_LEN_CCMP);
break;
default:
break;
}
-
}
int vnt_tx_packet(struct vnt_private *priv, struct sk_buff *skb)
@@ -807,7 +816,7 @@ int vnt_tx_packet(struct vnt_private *priv, struct sk_buff *skb)
current_rate = rate->hw_value;
if (priv->current_rate != current_rate &&
- !(priv->hw->conf.flags & IEEE80211_CONF_OFFCHANNEL)) {
+ !(priv->hw->conf.flags & IEEE80211_CONF_OFFCHANNEL)) {
priv->current_rate = current_rate;
vnt_schedule_command(priv, WLAN_CMD_SETPOWER);
}
@@ -964,7 +973,7 @@ int vnt_tx_packet(struct vnt_private *priv, struct sk_buff *skb)
tx_key = info->control.hw_key;
if (tx_key->keylen > 0)
vnt_fill_txkey(tx_context, tx_buffer_head->tx_key,
- tx_key, skb, tx_body_size, mic_hdr);
+ tx_key, skb, tx_body_size, mic_hdr);
}
priv->seq_counter = (le16_to_cpu(hdr->seq_ctrl) &
@@ -991,8 +1000,7 @@ int vnt_tx_packet(struct vnt_private *priv, struct sk_buff *skb)
return 0;
}
-static int vnt_beacon_xmit(struct vnt_private *priv,
- struct sk_buff *skb)
+static int vnt_beacon_xmit(struct vnt_private *priv, struct sk_buff *skb)
{
struct vnt_beacon_buffer *beacon_buffer;
struct vnt_tx_short_buf_head *short_head;
@@ -1101,7 +1109,7 @@ int vnt_beacon_make(struct vnt_private *priv, struct ieee80211_vif *vif)
}
int vnt_beacon_enable(struct vnt_private *priv, struct ieee80211_vif *vif,
- struct ieee80211_bss_conf *conf)
+ struct ieee80211_bss_conf *conf)
{
vnt_mac_reg_bits_off(priv, MAC_REG_TCR, TCR_AUTOBCNTX);
diff --git a/drivers/staging/wilc1000/host_interface.c b/drivers/staging/wilc1000/host_interface.c
index c3a8af081880..2568dfc15181 100644
--- a/drivers/staging/wilc1000/host_interface.c
+++ b/drivers/staging/wilc1000/host_interface.c
@@ -329,25 +329,53 @@ static void handle_set_channel(struct wilc_vif *vif,
netdev_err(vif->ndev, "Failed to set channel\n");
}
-static void handle_set_wfi_drv_handler(struct wilc_vif *vif,
- struct drv_handler *hif_drv_handler)
+static int handle_set_wfi_drv_handler(struct wilc_vif *vif,
+ struct drv_handler *hif_drv_handler)
{
int ret = 0;
struct wid wid;
+ u8 *currbyte, *buffer;
+ struct host_if_drv *hif_drv = NULL;
+
+ if (!vif->hif_drv)
+ return -EINVAL;
+
+ if (!hif_drv_handler)
+ return -EINVAL;
+
+ hif_drv = vif->hif_drv;
+
+ buffer = kzalloc(DRV_HANDLER_SIZE, GFP_KERNEL);
+ if (!buffer)
+ return -ENOMEM;
+
+ currbyte = buffer;
+ *currbyte = hif_drv->driver_handler_id & DRV_HANDLER_MASK;
+ currbyte++;
+ *currbyte = (u32)0 & DRV_HANDLER_MASK;
+ currbyte++;
+ *currbyte = (u32)0 & DRV_HANDLER_MASK;
+ currbyte++;
+ *currbyte = (u32)0 & DRV_HANDLER_MASK;
+ currbyte++;
+ *currbyte = (hif_drv_handler->name | (hif_drv_handler->mode << 1));
wid.id = (u16)WID_SET_DRV_HANDLER;
wid.type = WID_STR;
- wid.val = (s8 *)hif_drv_handler;
- wid.size = sizeof(*hif_drv_handler);
+ wid.val = (s8 *)buffer;
+ wid.size = DRV_HANDLER_SIZE;
ret = wilc_send_config_pkt(vif, SET_CFG, &wid, 1,
- hif_drv_handler->handler);
-
- if (!hif_drv_handler->handler)
- complete(&hif_driver_comp);
-
- if (ret)
+ hif_drv->driver_handler_id);
+ if (ret) {
netdev_err(vif->ndev, "Failed to set driver handler\n");
+ complete(&hif_driver_comp);
+ kfree(buffer);
+ return ret;
+ }
+ complete(&hif_driver_comp);
+ kfree(buffer);
+ return 0;
}
static void handle_set_operation_mode(struct wilc_vif *vif,
@@ -1188,7 +1216,7 @@ static s32 Handle_ConnectTimeout(struct wilc_vif *vif)
result = wilc_send_config_pkt(vif, SET_CFG, &wid, 1,
wilc_get_vif_idx(vif));
if (result)
- netdev_err(vif->ndev, "Failed to send dissconect\n");
+ netdev_err(vif->ndev, "Failed to send disconnect\n");
hif_drv->usr_conn_req.ssid_len = 0;
kfree(hif_drv->usr_conn_req.ssid);
@@ -2052,23 +2080,9 @@ static u32 WILC_HostIf_PackStaParam(u8 *pu8Buffer,
pu8CurrByte += pstrStationParam->rates_len;
*pu8CurrByte++ = pstrStationParam->ht_supported;
- *pu8CurrByte++ = pstrStationParam->ht_capa_info & 0xFF;
- *pu8CurrByte++ = (pstrStationParam->ht_capa_info >> 8) & 0xFF;
-
- *pu8CurrByte++ = pstrStationParam->ht_ampdu_params;
- memcpy(pu8CurrByte, pstrStationParam->ht_supp_mcs_set,
- WILC_SUPP_MCS_SET_SIZE);
- pu8CurrByte += WILC_SUPP_MCS_SET_SIZE;
-
- *pu8CurrByte++ = pstrStationParam->ht_ext_params & 0xFF;
- *pu8CurrByte++ = (pstrStationParam->ht_ext_params >> 8) & 0xFF;
-
- *pu8CurrByte++ = pstrStationParam->ht_tx_bf_cap & 0xFF;
- *pu8CurrByte++ = (pstrStationParam->ht_tx_bf_cap >> 8) & 0xFF;
- *pu8CurrByte++ = (pstrStationParam->ht_tx_bf_cap >> 16) & 0xFF;
- *pu8CurrByte++ = (pstrStationParam->ht_tx_bf_cap >> 24) & 0xFF;
-
- *pu8CurrByte++ = pstrStationParam->ht_ante_sel;
+ memcpy(pu8CurrByte, &pstrStationParam->ht_capa,
+ sizeof(struct ieee80211_ht_cap));
+ pu8CurrByte += sizeof(struct ieee80211_ht_cap);
*pu8CurrByte++ = pstrStationParam->flags_mask & 0xFF;
*pu8CurrByte++ = (pstrStationParam->flags_mask >> 8) & 0xFF;
@@ -2403,9 +2417,9 @@ static void Handle_SetMulticastFilter(struct wilc_vif *vif,
pu8CurrByte = wid.val;
*pu8CurrByte++ = (strHostIfSetMulti->enabled & 0xFF);
- *pu8CurrByte++ = 0;
- *pu8CurrByte++ = 0;
- *pu8CurrByte++ = 0;
+ *pu8CurrByte++ = ((strHostIfSetMulti->enabled >> 8) & 0xFF);
+ *pu8CurrByte++ = ((strHostIfSetMulti->enabled >> 16) & 0xFF);
+ *pu8CurrByte++ = ((strHostIfSetMulti->enabled >> 24) & 0xFF);
*pu8CurrByte++ = (strHostIfSetMulti->cnt & 0xFF);
*pu8CurrByte++ = ((strHostIfSetMulti->cnt >> 8) & 0xFF);
@@ -2463,6 +2477,7 @@ static void host_if_work(struct work_struct *work)
{
struct host_if_msg *msg;
struct wilc *wilc;
+ int ret = 0;
msg = container_of(work, struct host_if_msg, work);
wilc = msg->vif->wilc;
@@ -2568,7 +2583,7 @@ static void host_if_work(struct work_struct *work)
break;
case HOST_IF_MSG_SET_WFIDRV_HANDLER:
- handle_set_wfi_drv_handler(msg->vif, &msg->body.drv);
+ ret = handle_set_wfi_drv_handler(msg->vif, &msg->body.drv);
break;
case HOST_IF_MSG_SET_OPERATION_MODE:
@@ -2622,6 +2637,8 @@ static void host_if_work(struct work_struct *work)
break;
}
free_msg:
+ if (ret)
+ netdev_err(msg->vif->ndev, "Host cmd %d failed\n", msg->id);
kfree(msg);
complete(&hif_thread_comp);
}
@@ -3099,7 +3116,8 @@ int wilc_set_mac_chnl_num(struct wilc_vif *vif, u8 channel)
return 0;
}
-int wilc_set_wfi_drv_handler(struct wilc_vif *vif, int index, u8 mac_idx)
+int wilc_set_wfi_drv_handler(struct wilc_vif *vif, int index, u8 mode,
+ u8 ifc_id)
{
int result = 0;
struct host_if_msg msg;
@@ -3107,7 +3125,8 @@ int wilc_set_wfi_drv_handler(struct wilc_vif *vif, int index, u8 mac_idx)
memset(&msg, 0, sizeof(struct host_if_msg));
msg.id = HOST_IF_MSG_SET_WFIDRV_HANDLER;
msg.body.drv.handler = index;
- msg.body.drv.mac_idx = mac_idx;
+ msg.body.drv.mode = mode;
+ msg.body.drv.name = ifc_id;
msg.vif = vif;
result = wilc_enqueue_cmd(&msg);
@@ -3330,6 +3349,7 @@ int wilc_init(struct net_device *dev, struct host_if_drv **hif_drv_handler)
for (i = 0; i < wilc->vif_num; i++)
if (dev == wilc->vif[i]->ndev) {
wilc->vif[i]->hif_drv = hif_drv;
+ hif_drv->driver_handler_id = i + 1;
break;
}
@@ -3403,7 +3423,7 @@ int wilc_deinit(struct wilc_vif *vif)
del_timer_sync(&periodic_rssi);
del_timer_sync(&hif_drv->remain_on_ch_timer);
- wilc_set_wfi_drv_handler(vif, 0, 0);
+ wilc_set_wfi_drv_handler(vif, 0, 0, 0);
wait_for_completion(&hif_driver_comp);
if (hif_drv->usr_scan_req.scan_result) {
diff --git a/drivers/staging/wilc1000/host_interface.h b/drivers/staging/wilc1000/host_interface.h
index f36d3b5a0370..1ce5ead318c7 100644
--- a/drivers/staging/wilc1000/host_interface.h
+++ b/drivers/staging/wilc1000/host_interface.h
@@ -1,6 +1,6 @@
#ifndef HOST_INT_H
#define HOST_INT_H
-
+#include <linux/ieee80211.h>
#include "coreconfigurator.h"
#define IP_ALEN 4
@@ -47,10 +47,11 @@
#define ETH_ALEN 6
#define PMKID_LEN 16
#define WILC_MAX_NUM_PMKIDS 16
-#define WILC_SUPP_MCS_SET_SIZE 16
#define WILC_ADD_STA_LENGTH 40
#define SCAN_EVENT_DONE_ABORTED
#define NUM_CONCURRENT_IFC 2
+#define DRV_HANDLER_SIZE 5
+#define DRV_HANDLER_MASK 0x000000FF
struct rf_info {
u8 link_speed;
@@ -217,7 +218,8 @@ struct user_conn_req {
struct drv_handler {
u32 handler;
- u8 mac_idx;
+ u8 mode;
+ u8 name;
};
struct op_mode {
@@ -281,6 +283,7 @@ struct host_if_drv {
struct timer_list remain_on_ch_timer;
bool IFC_UP;
+ int driver_handler_id;
};
struct add_sta_param {
@@ -289,12 +292,7 @@ struct add_sta_param {
u8 rates_len;
const u8 *rates;
bool ht_supported;
- u16 ht_capa_info;
- u8 ht_ampdu_params;
- u8 ht_supp_mcs_set[16];
- u16 ht_ext_params;
- u32 ht_tx_bf_cap;
- u8 ht_ante_sel;
+ struct ieee80211_ht_cap ht_capa;
u16 flags_mask;
u16 flags_set;
};
@@ -354,7 +352,8 @@ int wilc_remain_on_channel(struct wilc_vif *vif, u32 session_id,
void *user_arg);
int wilc_listen_state_expired(struct wilc_vif *vif, u32 session_id);
int wilc_frame_register(struct wilc_vif *vif, u16 frame_type, bool reg);
-int wilc_set_wfi_drv_handler(struct wilc_vif *vif, int index, u8 mac_idx);
+int wilc_set_wfi_drv_handler(struct wilc_vif *vif, int index, u8 mode,
+ u8 ifc_id);
int wilc_set_operation_mode(struct wilc_vif *vif, u32 mode);
int wilc_get_statistics(struct wilc_vif *vif, struct rf_info *stats);
void wilc_resolve_disconnect_aberration(struct wilc_vif *vif);
diff --git a/drivers/staging/wilc1000/linux_wlan.c b/drivers/staging/wilc1000/linux_wlan.c
index d6d803416be2..308708450830 100644
--- a/drivers/staging/wilc1000/linux_wlan.c
+++ b/drivers/staging/wilc1000/linux_wlan.c
@@ -858,34 +858,15 @@ static int wilc_mac_open(struct net_device *ndev)
for (i = 0; i < wl->vif_num; i++) {
if (ndev == wl->vif[i]->ndev) {
- if (vif->iftype == AP_MODE) {
- wilc_set_wfi_drv_handler(vif,
- wilc_get_vif_idx(vif),
- 0);
- } else if (!wilc_wlan_get_num_conn_ifcs(wl)) {
- wilc_set_wfi_drv_handler(vif,
- wilc_get_vif_idx(vif),
- wl->open_ifcs);
- } else {
- if (memcmp(wl->vif[i ^ 1]->bssid,
- wl->vif[i ^ 1]->src_addr, 6))
- wilc_set_wfi_drv_handler(vif,
- wilc_get_vif_idx(vif),
- 0);
- else
- wilc_set_wfi_drv_handler(vif,
- wilc_get_vif_idx(vif),
- 1);
- }
+ wilc_set_wfi_drv_handler(vif, wilc_get_vif_idx(vif),
+ vif->iftype, vif->ifc_id);
wilc_set_operation_mode(vif, vif->iftype);
-
- wilc_get_mac_address(vif, mac_add);
- netdev_dbg(ndev, "Mac address: %pM\n", mac_add);
- memcpy(wl->vif[i]->src_addr, mac_add, ETH_ALEN);
-
break;
}
}
+ wilc_get_mac_address(vif, mac_add);
+ netdev_dbg(ndev, "Mac address: %pM\n", mac_add);
+ memcpy(wl->vif[i]->src_addr, mac_add, ETH_ALEN);
memcpy(ndev->dev_addr, wl->vif[i]->src_addr, ETH_ALEN);
@@ -1246,11 +1227,13 @@ int wilc_netdev_init(struct wilc **wilc, struct device *dev, int io_type,
vif = netdev_priv(ndev);
memset(vif, 0, sizeof(struct wilc_vif));
- if (i == 0)
+ if (i == 0) {
strcpy(ndev->name, "wlan%d");
- else
+ vif->ifc_id = 1;
+ } else {
strcpy(ndev->name, "p2p%d");
-
+ vif->ifc_id = 0;
+ }
vif->wilc = *wilc;
vif->ndev = ndev;
wl->vif[i] = vif;
diff --git a/drivers/staging/wilc1000/wilc_debugfs.c b/drivers/staging/wilc1000/wilc_debugfs.c
index 7d32de930576..ce54864569c7 100644
--- a/drivers/staging/wilc1000/wilc_debugfs.c
+++ b/drivers/staging/wilc1000/wilc_debugfs.c
@@ -20,7 +20,7 @@
static struct dentry *wilc_dir;
/*
- * --------------------------------------------------------------------------------
+ * ----------------------------------------------------------------------------
*/
#define DEBUG BIT(0)
#define INFO BIT(1)
@@ -32,10 +32,11 @@ static atomic_t WILC_DEBUG_LEVEL = ATOMIC_INIT(ERR);
EXPORT_SYMBOL_GPL(WILC_DEBUG_LEVEL);
/*
- * --------------------------------------------------------------------------------
+ * ----------------------------------------------------------------------------
*/
-static ssize_t wilc_debug_level_read(struct file *file, char __user *userbuf, size_t count, loff_t *ppos)
+static ssize_t wilc_debug_level_read(struct file *file, char __user *userbuf,
+ size_t count, loff_t *ppos)
{
char buf[128];
int res = 0;
@@ -44,13 +45,15 @@ static ssize_t wilc_debug_level_read(struct file *file, char __user *userbuf, si
if (*ppos > 0)
return 0;
- res = scnprintf(buf, sizeof(buf), "Debug Level: %x\n", atomic_read(&WILC_DEBUG_LEVEL));
+ res = scnprintf(buf, sizeof(buf), "Debug Level: %x\n",
+ atomic_read(&WILC_DEBUG_LEVEL));
return simple_read_from_buffer(userbuf, count, ppos, buf, res);
}
-static ssize_t wilc_debug_level_write(struct file *filp, const char __user *buf,
- size_t count, loff_t *ppos)
+static ssize_t wilc_debug_level_write(struct file *filp,
+ const char __user *buf, size_t count,
+ loff_t *ppos)
{
int flag = 0;
int ret;
@@ -60,7 +63,8 @@ static ssize_t wilc_debug_level_write(struct file *filp, const char __user *buf,
return ret;
if (flag > DBG_LEVEL_ALL) {
- pr_info("%s, value (0x%08x) is out of range, stay previous flag (0x%08x)\n", __func__, flag, atomic_read(&WILC_DEBUG_LEVEL));
+ pr_info("%s, value (0x%08x) is out of range, stay previous flag (0x%08x)\n",
+ __func__, flag, atomic_read(&WILC_DEBUG_LEVEL));
return -EINVAL;
}
@@ -75,7 +79,7 @@ static ssize_t wilc_debug_level_write(struct file *filp, const char __user *buf,
}
/*
- * --------------------------------------------------------------------------------
+ * ----------------------------------------------------------------------------
*/
#define FOPS(_open, _read, _write, _poll) { \
@@ -94,7 +98,12 @@ struct wilc_debugfs_info_t {
};
static struct wilc_debugfs_info_t debugfs_info[] = {
- { "wilc_debug_level", 0666, (DEBUG | ERR), FOPS(NULL, wilc_debug_level_read, wilc_debug_level_write, NULL), },
+ {
+ "wilc_debug_level",
+ 0666,
+ (DEBUG | ERR),
+ FOPS(NULL, wilc_debug_level_read, wilc_debug_level_write, NULL),
+ },
};
static int __init wilc_debugfs_init(void)
@@ -122,4 +131,3 @@ static void __exit wilc_debugfs_remove(void)
module_exit(wilc_debugfs_remove);
#endif
-
diff --git a/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c b/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c
index 44a12bdd6a46..68fd5b3b8b2d 100644
--- a/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c
+++ b/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c
@@ -84,7 +84,6 @@ static const struct wiphy_wowlan_support wowlan_support = {
#define TCP_ACK_FILTER_LINK_SPEED_THRESH 54
#define DEFAULT_LINK_SPEED 72
-
#define IS_MANAGMEMENT 0x100
#define IS_MANAGMEMENT_CALLBACK 0x080
#define IS_MGMT_STATUS_SUCCES 0x040
@@ -163,12 +162,12 @@ static struct ieee80211_supported_band WILC_WFI_band_2ghz = {
.n_bitrates = ARRAY_SIZE(ieee80211_bitrates),
};
-
struct add_key_params {
u8 key_idx;
bool pairwise;
u8 *mac_addr;
};
+
static struct add_key_params g_add_gtk_key_params;
static struct wilc_wfi_key g_key_gtk_params;
static struct add_key_params g_add_ptk_key_params;
@@ -281,7 +280,6 @@ static void remove_network_from_shadow(unsigned long arg)
unsigned long now = jiffies;
int i, j;
-
for (i = 0; i < last_scanned_cnt; i++) {
if (time_after(now, last_scanned_shadow[i].time_scan +
(unsigned long)(SCAN_RESULT_EXPIRE))) {
@@ -526,7 +524,6 @@ static void CfgConnectResult(enum conn_event enuConnDisconnEvent,
memcpy(priv->au8AssociatedBss, pstrConnectInfo->bssid, ETH_ALEN);
-
for (i = 0; i < last_scanned_cnt; i++) {
if (memcmp(last_scanned_shadow[i].bssid,
pstrConnectInfo->bssid,
@@ -626,7 +623,6 @@ static int scan(struct wiphy *wiphy, struct cfg80211_scan_request *request)
return -ENOMEM;
strHiddenNetwork.n_ssids = request->n_ssids;
-
for (i = 0; i < request->n_ssids; i++) {
if (request->ssids[i].ssid_len != 0) {
strHiddenNetwork.net_info[i].ssid = kmalloc(request->ssids[i].ssid_len, GFP_KERNEL);
@@ -927,8 +923,6 @@ static int add_key(struct wiphy *wiphy, struct net_device *netdev, u8 key_index,
priv->wilc_ptk[key_index]->seq = NULL;
}
-
-
if (!pairwise) {
if (params->cipher == WLAN_CIPHER_SUITE_TKIP)
u8gmode = ENCRYPT_ENABLED | WPA | TKIP;
@@ -968,7 +962,6 @@ static int add_key(struct wiphy *wiphy, struct net_device *netdev, u8 key_index,
else
u8pmode = priv->wilc_groupkey | AES;
-
if (params->key_len > 16 && params->cipher == WLAN_CIPHER_SUITE_TKIP) {
pu8TxMic = params->key + 24;
pu8RxMic = params->key + 16;
@@ -1153,7 +1146,6 @@ static int get_key(struct wiphy *wiphy, struct net_device *netdev, u8 key_index,
priv = wiphy_priv(wiphy);
-
if (!pairwise) {
key_params.key = priv->wilc_gtk[key_index]->key;
key_params.cipher = priv->wilc_gtk[key_index]->cipher;
@@ -1298,7 +1290,6 @@ static int set_pmksa(struct wiphy *wiphy, struct net_device *netdev,
vif = netdev_priv(priv->dev);
-
for (i = 0; i < priv->pmkid_list.numpmkid; i++) {
if (!memcmp(pmksa->bssid, priv->pmkid_list.pmkidlist[i].bssid,
ETH_ALEN)) {
@@ -1511,7 +1502,6 @@ void WILC_WFI_p2p_rx(struct net_device *dev, u8 *buff, u32 size)
}
}
-
if ((buff[P2P_PUB_ACTION_SUBTYPE] == GO_NEG_REQ || buff[P2P_PUB_ACTION_SUBTYPE] == GO_NEG_RSP) && (wilc_ie)) {
cfg80211_rx_mgmt(priv->wdev, s32Freq, 0, buff, size - 7, 0);
return;
@@ -1533,7 +1523,6 @@ static void WILC_WFI_mgmt_tx_complete(void *priv, int status)
{
struct p2p_mgmt_data *pv_data = priv;
-
kfree(pv_data->buff);
kfree(pv_data);
}
@@ -1653,7 +1642,6 @@ static int mgmt_tx(struct wiphy *wiphy,
memcpy(mgmt_tx->buff, buf, len);
mgmt_tx->size = len;
-
if (ieee80211_is_probe_resp(mgmt->frame_control)) {
wilc_set_mac_chnl_num(vif, chan->hw_value);
curr_channel = chan->hw_value;
@@ -1832,7 +1820,6 @@ static int set_power_mgmt(struct wiphy *wiphy, struct net_device *dev,
if (wilc_enable_ps)
wilc_set_power_mgmt(vif, enabled, timeout);
-
return 0;
}
@@ -1887,7 +1874,7 @@ static int change_virtual_intf(struct wiphy *wiphy, struct net_device *dev,
if (wl->initialized) {
wilc_set_wfi_drv_handler(vif, wilc_get_vif_idx(vif),
- 0);
+ 0, vif->ifc_id);
wilc_set_operation_mode(vif, AP_MODE);
wilc_set_power_mgmt(vif, 0, 0);
}
@@ -2003,14 +1990,7 @@ static int add_station(struct wiphy *wiphy, struct net_device *dev,
strStaParams.ht_supported = false;
} else {
strStaParams.ht_supported = true;
- strStaParams.ht_capa_info = params->ht_capa->cap_info;
- strStaParams.ht_ampdu_params = params->ht_capa->ampdu_params_info;
- memcpy(strStaParams.ht_supp_mcs_set,
- &params->ht_capa->mcs,
- WILC_SUPP_MCS_SET_SIZE);
- strStaParams.ht_ext_params = params->ht_capa->extended_ht_cap_info;
- strStaParams.ht_tx_bf_cap = params->ht_capa->tx_BF_cap_info;
- strStaParams.ht_ante_sel = params->ht_capa->antenna_selection_info;
+ strStaParams.ht_capa = *params->ht_capa;
}
strStaParams.flags_mask = params->sta_flags_mask;
@@ -2075,14 +2055,7 @@ static int change_station(struct wiphy *wiphy, struct net_device *dev,
strStaParams.ht_supported = false;
} else {
strStaParams.ht_supported = true;
- strStaParams.ht_capa_info = params->ht_capa->cap_info;
- strStaParams.ht_ampdu_params = params->ht_capa->ampdu_params_info;
- memcpy(strStaParams.ht_supp_mcs_set,
- &params->ht_capa->mcs,
- WILC_SUPP_MCS_SET_SIZE);
- strStaParams.ht_ext_params = params->ht_capa->extended_ht_cap_info;
- strStaParams.ht_tx_bf_cap = params->ht_capa->tx_BF_cap_info;
- strStaParams.ht_ante_sel = params->ht_capa->antenna_selection_info;
+ strStaParams.ht_capa = *params->ht_capa;
}
strStaParams.flags_mask = params->sta_flags_mask;
@@ -2108,7 +2081,6 @@ static struct wireless_dev *add_virtual_intf(struct wiphy *wiphy,
priv = wiphy_priv(wiphy);
vif = netdev_priv(priv->wdev->netdev);
-
if (type == NL80211_IFTYPE_MONITOR) {
new_ifc = WILC_WFI_init_mon_interface(name, vif->ndev);
if (new_ifc) {
diff --git a/drivers/staging/wilc1000/wilc_wfi_netdevice.h b/drivers/staging/wilc1000/wilc_wfi_netdevice.h
index d431673bc46c..c89bf4301096 100644
--- a/drivers/staging/wilc1000/wilc_wfi_netdevice.h
+++ b/drivers/staging/wilc1000/wilc_wfi_netdevice.h
@@ -158,6 +158,7 @@ struct wilc_vif {
struct host_if_drv *hif_drv;
struct net_device *ndev;
u8 mode;
+ u8 ifc_id;
};
struct wilc {
diff --git a/drivers/staging/wilc1000/wilc_wlan_if.h b/drivers/staging/wilc1000/wilc_wlan_if.h
index 439ac6f8d533..f4d60057a06e 100644
--- a/drivers/staging/wilc1000/wilc_wlan_if.h
+++ b/drivers/staging/wilc1000/wilc_wlan_if.h
@@ -845,7 +845,7 @@ typedef enum {
WID_MODEL_NAME = 0x3027, /*Added for CAPI tool */
WID_MODEL_NUM = 0x3028, /*Added for CAPI tool */
WID_DEVICE_NAME = 0x3029, /*Added for CAPI tool */
- WID_SET_DRV_HANDLER = 0x3030,
+ WID_SET_DRV_HANDLER = 0x3079,
/* NMAC String WID list */
WID_11N_P_ACTION_REQ = 0x3080,
diff --git a/drivers/staging/wlan-ng/hfa384x.h b/drivers/staging/wlan-ng/hfa384x.h
index 310e2c454590..018db2299d0c 100644
--- a/drivers/staging/wlan-ng/hfa384x.h
+++ b/drivers/staging/wlan-ng/hfa384x.h
@@ -353,12 +353,12 @@
/*-------------------------------------------------------------*/
/* Commonly used basic types */
struct hfa384x_bytestr {
- u16 len;
+ __le16 len;
u8 data[0];
} __packed;
struct hfa384x_bytestr32 {
- u16 len;
+ __le16 len;
u8 data[32];
} __packed;
@@ -399,8 +399,8 @@ struct hfa384x_caplevel {
/*-- Configuration Record: HostScanRequest (data portion only) --*/
struct hfa384x_host_scan_request_data {
- u16 channel_list;
- u16 tx_rate;
+ __le16 channel_list;
+ __le16 tx_rate;
struct hfa384x_bytestr32 ssid;
} __packed;
@@ -419,7 +419,7 @@ struct hfa384x_authenticate_station_data {
/*-- Configuration Record: WPAData (data portion only) --*/
struct hfa384x_wpa_data {
- u16 datalen;
+ __le16 datalen;
u8 data[0]; /* max 80 */
} __packed;
@@ -682,16 +682,16 @@ struct hfa384x_ch_info_result {
/*-- Inquiry Frame, Diagnose: Host Scan Results & Subfields--*/
struct hfa384x_hscan_result_sub {
- u16 chid;
- u16 anl;
- u16 sl;
+ __le16 chid;
+ __le16 anl;
+ __le16 sl;
u8 bssid[WLAN_BSSID_LEN];
- u16 bcnint;
- u16 capinfo;
+ __le16 bcnint;
+ __le16 capinfo;
struct hfa384x_bytestr32 ssid;
u8 supprates[10]; /* 802.11 info element */
u16 proberesp_rate;
- u16 atim;
+ __le16 atim;
} __packed;
struct hfa384x_hscan_result {
diff --git a/drivers/staging/wlan-ng/hfa384x_usb.c b/drivers/staging/wlan-ng/hfa384x_usb.c
index a812e55ba1b0..d3d1958675ed 100644
--- a/drivers/staging/wlan-ng/hfa384x_usb.c
+++ b/drivers/staging/wlan-ng/hfa384x_usb.c
@@ -1840,15 +1840,15 @@ int hfa384x_drvr_flashdl_enable(struct hfa384x *hw)
if (result)
return result;
- hw->bufinfo.page = le16_to_cpu(hw->bufinfo.page);
- hw->bufinfo.offset = le16_to_cpu(hw->bufinfo.offset);
- hw->bufinfo.len = le16_to_cpu(hw->bufinfo.len);
+ le16_to_cpus(&hw->bufinfo.page);
+ le16_to_cpus(&hw->bufinfo.offset);
+ le16_to_cpus(&hw->bufinfo.len);
result = hfa384x_drvr_getconfig16(hw, HFA384x_RID_MAXLOADTIME,
&hw->dltimeout);
if (result)
return result;
- hw->dltimeout = le16_to_cpu(hw->dltimeout);
+ le16_to_cpus(&hw->dltimeout);
pr_debug("flashdl_enable\n");
@@ -2644,8 +2644,7 @@ int hfa384x_drvr_txframe(struct hfa384x *hw, struct sk_buff *skb,
HFA384x_TX_MACPORT_SET(0) | HFA384x_TX_STRUCTYPE_SET(1) |
HFA384x_TX_TXEX_SET(0) | HFA384x_TX_TXOK_SET(0);
#endif
- hw->txbuff.txfrm.desc.tx_control =
- cpu_to_le16(hw->txbuff.txfrm.desc.tx_control);
+ cpu_to_le16s(&hw->txbuff.txfrm.desc.tx_control);
/* copy the header over to the txdesc */
memcpy(&hw->txbuff.txfrm.desc.frame_control, p80211_hdr,
@@ -3380,8 +3379,8 @@ static void hfa384x_usbin_rx(struct wlandevice *wlandev, struct sk_buff *skb)
u16 fc;
/* Byte order convert once up front. */
- usbin->rxfrm.desc.status = le16_to_cpu(usbin->rxfrm.desc.status);
- usbin->rxfrm.desc.time = le32_to_cpu(usbin->rxfrm.desc.time);
+ le16_to_cpus(&usbin->rxfrm.desc.status);
+ le32_to_cpus(&usbin->rxfrm.desc.time);
/* Now handle frame based on port# */
switch (HFA384x_RXSTATUS_MACPORT_GET(usbin->rxfrm.desc.status)) {
@@ -3576,8 +3575,7 @@ static void hfa384x_int_rxmonitor(struct wlandevice *wlandev,
static void hfa384x_usbin_info(struct wlandevice *wlandev,
union hfa384x_usbin *usbin)
{
- usbin->infofrm.info.framelen =
- le16_to_cpu(usbin->infofrm.info.framelen);
+ le16_to_cpus(&usbin->infofrm.info.framelen);
prism2sta_ev_info(wlandev, &usbin->infofrm.info);
}
diff --git a/drivers/staging/wlan-ng/prism2fw.c b/drivers/staging/wlan-ng/prism2fw.c
index afd877fb4557..1a0c786c7616 100644
--- a/drivers/staging/wlan-ng/prism2fw.c
+++ b/drivers/staging/wlan-ng/prism2fw.c
@@ -617,28 +617,28 @@ static int mkpdrlist(struct pda *pda)
HFA384x_PDR_NICID) {
memcpy(&nicid, &pda->rec[pda->nrec]->data.nicid,
sizeof(nicid));
- nicid.id = le16_to_cpu(nicid.id);
- nicid.variant = le16_to_cpu(nicid.variant);
- nicid.major = le16_to_cpu(nicid.major);
- nicid.minor = le16_to_cpu(nicid.minor);
+ le16_to_cpus(&nicid.id);
+ le16_to_cpus(&nicid.variant);
+ le16_to_cpus(&nicid.major);
+ le16_to_cpus(&nicid.minor);
}
if (le16_to_cpu(pda->rec[pda->nrec]->code) ==
HFA384x_PDR_MFISUPRANGE) {
memcpy(&rfid, &pda->rec[pda->nrec]->data.mfisuprange,
sizeof(rfid));
- rfid.id = le16_to_cpu(rfid.id);
- rfid.variant = le16_to_cpu(rfid.variant);
- rfid.bottom = le16_to_cpu(rfid.bottom);
- rfid.top = le16_to_cpu(rfid.top);
+ le16_to_cpus(&rfid.id);
+ le16_to_cpus(&rfid.variant);
+ le16_to_cpus(&rfid.bottom);
+ le16_to_cpus(&rfid.top);
}
if (le16_to_cpu(pda->rec[pda->nrec]->code) ==
HFA384x_PDR_CFISUPRANGE) {
memcpy(&macid, &pda->rec[pda->nrec]->data.cfisuprange,
sizeof(macid));
- macid.id = le16_to_cpu(macid.id);
- macid.variant = le16_to_cpu(macid.variant);
- macid.bottom = le16_to_cpu(macid.bottom);
- macid.top = le16_to_cpu(macid.top);
+ le16_to_cpus(&macid.id);
+ le16_to_cpus(&macid.variant);
+ le16_to_cpus(&macid.bottom);
+ le16_to_cpus(&macid.top);
}
(pda->nrec)++;
diff --git a/drivers/staging/wlan-ng/prism2mgmt.c b/drivers/staging/wlan-ng/prism2mgmt.c
index e23a0d0e7b09..c4aa9e7e7003 100644
--- a/drivers/staging/wlan-ng/prism2mgmt.c
+++ b/drivers/staging/wlan-ng/prism2mgmt.c
@@ -170,7 +170,7 @@ int prism2mgmt_scan(struct wlandevice *wlandev, void *msgp)
hw->ident_sta_fw.variant) >
HFA384x_FIRMWARE_VERSION(1, 5, 0)) {
if (msg->scantype.data != P80211ENUM_scantype_active)
- word = cpu_to_le16(msg->maxchanneltime.data);
+ word = msg->maxchanneltime.data;
else
word = 0;
@@ -213,7 +213,7 @@ int prism2mgmt_scan(struct wlandevice *wlandev, void *msgp)
goto exit;
}
if (word == HFA384x_PORTSTATUS_DISABLED) {
- u16 wordbuf[17];
+ __le16 wordbuf[17];
result = hfa384x_drvr_setconfig16(hw,
HFA384x_RID_CNFROAMINGMODE,
diff --git a/drivers/staging/wlan-ng/prism2mib.c b/drivers/staging/wlan-ng/prism2mib.c
index 28df1f3d6f4a..e41207d97309 100644
--- a/drivers/staging/wlan-ng/prism2mib.c
+++ b/drivers/staging/wlan-ng/prism2mib.c
@@ -774,7 +774,7 @@ void prism2mgmt_pstr2bytestr(struct hfa384x_bytestr *bytestr,
void prism2mgmt_bytestr2pstr(struct hfa384x_bytestr *bytestr,
struct p80211pstrd *pstr)
{
- pstr->len = (u8)(le16_to_cpu((u16)(bytestr->len)));
+ pstr->len = (u8)(le16_to_cpu(bytestr->len));
memcpy(pstr->data, bytestr->data, pstr->len);
}
diff --git a/drivers/staging/wlan-ng/prism2sta.c b/drivers/staging/wlan-ng/prism2sta.c
index 9c2b4ef2de58..e16da34389cd 100644
--- a/drivers/staging/wlan-ng/prism2sta.c
+++ b/drivers/staging/wlan-ng/prism2sta.c
@@ -603,10 +603,10 @@ static int prism2sta_getcardinfo(struct wlandevice *wlandev)
}
/* get all the nic id fields in host byte order */
- hw->ident_nic.id = le16_to_cpu(hw->ident_nic.id);
- hw->ident_nic.variant = le16_to_cpu(hw->ident_nic.variant);
- hw->ident_nic.major = le16_to_cpu(hw->ident_nic.major);
- hw->ident_nic.minor = le16_to_cpu(hw->ident_nic.minor);
+ le16_to_cpus(&hw->ident_nic.id);
+ le16_to_cpus(&hw->ident_nic.variant);
+ le16_to_cpus(&hw->ident_nic.major);
+ le16_to_cpus(&hw->ident_nic.minor);
netdev_info(wlandev->netdev, "ident: nic h/w: id=0x%02x %d.%d.%d\n",
hw->ident_nic.id, hw->ident_nic.major,
@@ -622,10 +622,10 @@ static int prism2sta_getcardinfo(struct wlandevice *wlandev)
}
/* get all the private fw id fields in host byte order */
- hw->ident_pri_fw.id = le16_to_cpu(hw->ident_pri_fw.id);
- hw->ident_pri_fw.variant = le16_to_cpu(hw->ident_pri_fw.variant);
- hw->ident_pri_fw.major = le16_to_cpu(hw->ident_pri_fw.major);
- hw->ident_pri_fw.minor = le16_to_cpu(hw->ident_pri_fw.minor);
+ le16_to_cpus(&hw->ident_pri_fw.id);
+ le16_to_cpus(&hw->ident_pri_fw.variant);
+ le16_to_cpus(&hw->ident_pri_fw.major);
+ le16_to_cpus(&hw->ident_pri_fw.minor);
netdev_info(wlandev->netdev, "ident: pri f/w: id=0x%02x %d.%d.%d\n",
hw->ident_pri_fw.id, hw->ident_pri_fw.major,
@@ -648,10 +648,10 @@ static int prism2sta_getcardinfo(struct wlandevice *wlandev)
}
/* get all the station fw id fields in host byte order */
- hw->ident_sta_fw.id = le16_to_cpu(hw->ident_sta_fw.id);
- hw->ident_sta_fw.variant = le16_to_cpu(hw->ident_sta_fw.variant);
- hw->ident_sta_fw.major = le16_to_cpu(hw->ident_sta_fw.major);
- hw->ident_sta_fw.minor = le16_to_cpu(hw->ident_sta_fw.minor);
+ le16_to_cpus(&hw->ident_sta_fw.id);
+ le16_to_cpus(&hw->ident_sta_fw.variant);
+ le16_to_cpus(&hw->ident_sta_fw.major);
+ le16_to_cpus(&hw->ident_sta_fw.minor);
/* strip out the 'special' variant bits */
hw->mm_mods = hw->ident_sta_fw.variant & GENMASK(15, 14);
@@ -683,11 +683,11 @@ static int prism2sta_getcardinfo(struct wlandevice *wlandev)
/* get all the Compatibility range, modem interface supplier
* fields in byte order
*/
- hw->cap_sup_mfi.role = le16_to_cpu(hw->cap_sup_mfi.role);
- hw->cap_sup_mfi.id = le16_to_cpu(hw->cap_sup_mfi.id);
- hw->cap_sup_mfi.variant = le16_to_cpu(hw->cap_sup_mfi.variant);
- hw->cap_sup_mfi.bottom = le16_to_cpu(hw->cap_sup_mfi.bottom);
- hw->cap_sup_mfi.top = le16_to_cpu(hw->cap_sup_mfi.top);
+ le16_to_cpus(&hw->cap_sup_mfi.role);
+ le16_to_cpus(&hw->cap_sup_mfi.id);
+ le16_to_cpus(&hw->cap_sup_mfi.variant);
+ le16_to_cpus(&hw->cap_sup_mfi.bottom);
+ le16_to_cpus(&hw->cap_sup_mfi.top);
netdev_info(wlandev->netdev,
"MFI:SUP:role=0x%02x:id=0x%02x:var=0x%02x:b/t=%d/%d\n",
@@ -707,11 +707,11 @@ static int prism2sta_getcardinfo(struct wlandevice *wlandev)
/* get all the Compatibility range, controller interface supplier
* fields in byte order
*/
- hw->cap_sup_cfi.role = le16_to_cpu(hw->cap_sup_cfi.role);
- hw->cap_sup_cfi.id = le16_to_cpu(hw->cap_sup_cfi.id);
- hw->cap_sup_cfi.variant = le16_to_cpu(hw->cap_sup_cfi.variant);
- hw->cap_sup_cfi.bottom = le16_to_cpu(hw->cap_sup_cfi.bottom);
- hw->cap_sup_cfi.top = le16_to_cpu(hw->cap_sup_cfi.top);
+ le16_to_cpus(&hw->cap_sup_cfi.role);
+ le16_to_cpus(&hw->cap_sup_cfi.id);
+ le16_to_cpus(&hw->cap_sup_cfi.variant);
+ le16_to_cpus(&hw->cap_sup_cfi.bottom);
+ le16_to_cpus(&hw->cap_sup_cfi.top);
netdev_info(wlandev->netdev,
"CFI:SUP:role=0x%02x:id=0x%02x:var=0x%02x:b/t=%d/%d\n",
@@ -731,11 +731,11 @@ static int prism2sta_getcardinfo(struct wlandevice *wlandev)
/* get all the Compatibility range, primary firmware supplier
* fields in byte order
*/
- hw->cap_sup_pri.role = le16_to_cpu(hw->cap_sup_pri.role);
- hw->cap_sup_pri.id = le16_to_cpu(hw->cap_sup_pri.id);
- hw->cap_sup_pri.variant = le16_to_cpu(hw->cap_sup_pri.variant);
- hw->cap_sup_pri.bottom = le16_to_cpu(hw->cap_sup_pri.bottom);
- hw->cap_sup_pri.top = le16_to_cpu(hw->cap_sup_pri.top);
+ le16_to_cpus(&hw->cap_sup_pri.role);
+ le16_to_cpus(&hw->cap_sup_pri.id);
+ le16_to_cpus(&hw->cap_sup_pri.variant);
+ le16_to_cpus(&hw->cap_sup_pri.bottom);
+ le16_to_cpus(&hw->cap_sup_pri.top);
netdev_info(wlandev->netdev,
"PRI:SUP:role=0x%02x:id=0x%02x:var=0x%02x:b/t=%d/%d\n",
@@ -755,11 +755,11 @@ static int prism2sta_getcardinfo(struct wlandevice *wlandev)
/* get all the Compatibility range, station firmware supplier
* fields in byte order
*/
- hw->cap_sup_sta.role = le16_to_cpu(hw->cap_sup_sta.role);
- hw->cap_sup_sta.id = le16_to_cpu(hw->cap_sup_sta.id);
- hw->cap_sup_sta.variant = le16_to_cpu(hw->cap_sup_sta.variant);
- hw->cap_sup_sta.bottom = le16_to_cpu(hw->cap_sup_sta.bottom);
- hw->cap_sup_sta.top = le16_to_cpu(hw->cap_sup_sta.top);
+ le16_to_cpus(&hw->cap_sup_sta.role);
+ le16_to_cpus(&hw->cap_sup_sta.id);
+ le16_to_cpus(&hw->cap_sup_sta.variant);
+ le16_to_cpus(&hw->cap_sup_sta.bottom);
+ le16_to_cpus(&hw->cap_sup_sta.top);
if (hw->cap_sup_sta.id == 0x04) {
netdev_info(wlandev->netdev,
@@ -787,11 +787,11 @@ static int prism2sta_getcardinfo(struct wlandevice *wlandev)
/* get all the Compatibility range, primary f/w actor, CFI supplier
* fields in byte order
*/
- hw->cap_act_pri_cfi.role = le16_to_cpu(hw->cap_act_pri_cfi.role);
- hw->cap_act_pri_cfi.id = le16_to_cpu(hw->cap_act_pri_cfi.id);
- hw->cap_act_pri_cfi.variant = le16_to_cpu(hw->cap_act_pri_cfi.variant);
- hw->cap_act_pri_cfi.bottom = le16_to_cpu(hw->cap_act_pri_cfi.bottom);
- hw->cap_act_pri_cfi.top = le16_to_cpu(hw->cap_act_pri_cfi.top);
+ le16_to_cpus(&hw->cap_act_pri_cfi.role);
+ le16_to_cpus(&hw->cap_act_pri_cfi.id);
+ le16_to_cpus(&hw->cap_act_pri_cfi.variant);
+ le16_to_cpus(&hw->cap_act_pri_cfi.bottom);
+ le16_to_cpus(&hw->cap_act_pri_cfi.top);
netdev_info(wlandev->netdev,
"PRI-CFI:ACT:role=0x%02x:id=0x%02x:var=0x%02x:b/t=%d/%d\n",
@@ -811,11 +811,11 @@ static int prism2sta_getcardinfo(struct wlandevice *wlandev)
/* get all the Compatibility range, station f/w actor, CFI supplier
* fields in byte order
*/
- hw->cap_act_sta_cfi.role = le16_to_cpu(hw->cap_act_sta_cfi.role);
- hw->cap_act_sta_cfi.id = le16_to_cpu(hw->cap_act_sta_cfi.id);
- hw->cap_act_sta_cfi.variant = le16_to_cpu(hw->cap_act_sta_cfi.variant);
- hw->cap_act_sta_cfi.bottom = le16_to_cpu(hw->cap_act_sta_cfi.bottom);
- hw->cap_act_sta_cfi.top = le16_to_cpu(hw->cap_act_sta_cfi.top);
+ le16_to_cpus(&hw->cap_act_sta_cfi.role);
+ le16_to_cpus(&hw->cap_act_sta_cfi.id);
+ le16_to_cpus(&hw->cap_act_sta_cfi.variant);
+ le16_to_cpus(&hw->cap_act_sta_cfi.bottom);
+ le16_to_cpus(&hw->cap_act_sta_cfi.top);
netdev_info(wlandev->netdev,
"STA-CFI:ACT:role=0x%02x:id=0x%02x:var=0x%02x:b/t=%d/%d\n",
@@ -835,11 +835,11 @@ static int prism2sta_getcardinfo(struct wlandevice *wlandev)
/* get all the Compatibility range, station f/w actor, MFI supplier
* fields in byte order
*/
- hw->cap_act_sta_mfi.role = le16_to_cpu(hw->cap_act_sta_mfi.role);
- hw->cap_act_sta_mfi.id = le16_to_cpu(hw->cap_act_sta_mfi.id);
- hw->cap_act_sta_mfi.variant = le16_to_cpu(hw->cap_act_sta_mfi.variant);
- hw->cap_act_sta_mfi.bottom = le16_to_cpu(hw->cap_act_sta_mfi.bottom);
- hw->cap_act_sta_mfi.top = le16_to_cpu(hw->cap_act_sta_mfi.top);
+ le16_to_cpus(&hw->cap_act_sta_mfi.role);
+ le16_to_cpus(&hw->cap_act_sta_mfi.id);
+ le16_to_cpus(&hw->cap_act_sta_mfi.variant);
+ le16_to_cpus(&hw->cap_act_sta_mfi.bottom);
+ le16_to_cpus(&hw->cap_act_sta_mfi.top);
netdev_info(wlandev->netdev,
"STA-MFI:ACT:role=0x%02x:id=0x%02x:var=0x%02x:b/t=%d/%d\n",
@@ -1478,8 +1478,8 @@ static void prism2sta_inf_assocstatus(struct wlandevice *wlandev,
int i;
memcpy(&rec, &inf->info.assocstatus, sizeof(rec));
- rec.assocstatus = le16_to_cpu(rec.assocstatus);
- rec.reason = le16_to_cpu(rec.reason);
+ le16_to_cpus(&rec.assocstatus);
+ le16_to_cpus(&rec.reason);
/*
* Find the address in the list of authenticated stations.
@@ -1748,7 +1748,7 @@ static void prism2sta_inf_psusercnt(struct wlandevice *wlandev,
void prism2sta_ev_info(struct wlandevice *wlandev,
struct hfa384x_inf_frame *inf)
{
- inf->infotype = le16_to_cpu(inf->infotype);
+ le16_to_cpus(&inf->infotype);
/* Dispatch */
switch (inf->infotype) {
case HFA384x_IT_HANDOVERADDR:
diff --git a/drivers/staging/xgifb/vb_table.h b/drivers/staging/xgifb/vb_table.h
index f9f98e06e6d5..31dd52c513df 100644
--- a/drivers/staging/xgifb/vb_table.h
+++ b/drivers/staging/xgifb/vb_table.h
@@ -2448,15 +2448,15 @@ static const struct XGI301C_Tap4TimingStruct PALTap4Timing[] = {
}
},
{0xFFFF, {
- 0x04, 0x1A, 0x04, 0x7E, 0x02, 0x1B, 0x05, 0x7E, /* ; C0-C7 */
- 0x01, 0x1A, 0x07, 0x7E, 0x00, 0x1A, 0x09, 0x7D, /* ; C8-CF */
- 0x7F, 0x19, 0x0B, 0x7D, 0x7E, 0x18, 0x0D, 0x7D, /* ; D0-D7 */
- 0x7D, 0x17, 0x10, 0x7C, 0x7D, 0x15, 0x12, 0x7C, /* ; D8-DF */
- 0x7C, 0x14, 0x14, 0x7C, 0x7C, 0x12, 0x15, 0x7D, /* ; E0-E7 */
- 0x7C, 0x10, 0x17, 0x7D, 0x7C, 0x0D, 0x18, 0x7F, /* ; EA-EF */
- 0x7D, 0x0B, 0x19, 0x7F, 0x7D, 0x09, 0x1A, 0x00, /* ; F0-F7 */
- 0x7D, 0x07, 0x1A, 0x02, 0x7E, 0x05, 0x1B, 0x02 /* ; F8-FF */
- }
+ 0x04, 0x1A, 0x04, 0x7E, 0x02, 0x1B, 0x05, 0x7E, /* ; C0-C7 */
+ 0x01, 0x1A, 0x07, 0x7E, 0x00, 0x1A, 0x09, 0x7D, /* ; C8-CF */
+ 0x7F, 0x19, 0x0B, 0x7D, 0x7E, 0x18, 0x0D, 0x7D, /* ; D0-D7 */
+ 0x7D, 0x17, 0x10, 0x7C, 0x7D, 0x15, 0x12, 0x7C, /* ; D8-DF */
+ 0x7C, 0x14, 0x14, 0x7C, 0x7C, 0x12, 0x15, 0x7D, /* ; E0-E7 */
+ 0x7C, 0x10, 0x17, 0x7D, 0x7C, 0x0D, 0x18, 0x7F, /* ; EA-EF */
+ 0x7D, 0x0B, 0x19, 0x7F, 0x7D, 0x09, 0x1A, 0x00, /* ; F0-F7 */
+ 0x7D, 0x07, 0x1A, 0x02, 0x7E, 0x05, 0x1B, 0x02 /* ; F8-FF */
+ }
}
};
diff --git a/drivers/target/iscsi/iscsi_target.c b/drivers/target/iscsi/iscsi_target.c
index 26a9bcd5ee6a..3fdca2cdd8da 100644
--- a/drivers/target/iscsi/iscsi_target.c
+++ b/drivers/target/iscsi/iscsi_target.c
@@ -1279,6 +1279,18 @@ iscsit_get_immediate_data(struct iscsi_cmd *cmd, struct iscsi_scsi_req *hdr,
*/
if (dump_payload)
goto after_immediate_data;
+ /*
+ * Check for underflow case where both EDTL and immediate data payload
+ * exceeds what is presented by CDB's TRANSFER LENGTH, and what has
+ * already been set in target_cmd_size_check() as se_cmd->data_length.
+ *
+ * For this special case, fail the command and dump the immediate data
+ * payload.
+ */
+ if (cmd->first_burst_len > cmd->se_cmd.data_length) {
+ cmd->sense_reason = TCM_INVALID_CDB_FIELD;
+ goto after_immediate_data;
+ }
immed_ret = iscsit_handle_immediate_data(cmd, hdr,
cmd->first_burst_len);
@@ -3790,6 +3802,8 @@ int iscsi_target_tx_thread(void *arg)
{
int ret = 0;
struct iscsi_conn *conn = arg;
+ bool conn_freed = false;
+
/*
* Allow ourselves to be interrupted by SIGINT so that a
* connection recovery / failure event can be triggered externally.
@@ -3815,12 +3829,14 @@ get_immediate:
goto transport_err;
ret = iscsit_handle_response_queue(conn);
- if (ret == 1)
+ if (ret == 1) {
goto get_immediate;
- else if (ret == -ECONNRESET)
+ } else if (ret == -ECONNRESET) {
+ conn_freed = true;
goto out;
- else if (ret < 0)
+ } else if (ret < 0) {
goto transport_err;
+ }
}
transport_err:
@@ -3830,8 +3846,13 @@ transport_err:
* responsible for cleaning up the early connection failure.
*/
if (conn->conn_state != TARG_CONN_STATE_IN_LOGIN)
- iscsit_take_action_for_connection_exit(conn);
+ iscsit_take_action_for_connection_exit(conn, &conn_freed);
out:
+ if (!conn_freed) {
+ while (!kthread_should_stop()) {
+ msleep(100);
+ }
+ }
return 0;
}
@@ -4004,6 +4025,7 @@ int iscsi_target_rx_thread(void *arg)
{
int rc;
struct iscsi_conn *conn = arg;
+ bool conn_freed = false;
/*
* Allow ourselves to be interrupted by SIGINT so that a
@@ -4016,7 +4038,7 @@ int iscsi_target_rx_thread(void *arg)
*/
rc = wait_for_completion_interruptible(&conn->rx_login_comp);
if (rc < 0 || iscsi_target_check_conn_state(conn))
- return 0;
+ goto out;
if (!conn->conn_transport->iscsit_get_rx_pdu)
return 0;
@@ -4025,7 +4047,15 @@ int iscsi_target_rx_thread(void *arg)
if (!signal_pending(current))
atomic_set(&conn->transport_failed, 1);
- iscsit_take_action_for_connection_exit(conn);
+ iscsit_take_action_for_connection_exit(conn, &conn_freed);
+
+out:
+ if (!conn_freed) {
+ while (!kthread_should_stop()) {
+ msleep(100);
+ }
+ }
+
return 0;
}
@@ -4405,8 +4435,11 @@ static void iscsit_logout_post_handler_closesession(
* always sleep waiting for RX/TX thread shutdown to complete
* within iscsit_close_connection().
*/
- if (!conn->conn_transport->rdma_shutdown)
+ if (!conn->conn_transport->rdma_shutdown) {
sleep = cmpxchg(&conn->tx_thread_active, true, false);
+ if (!sleep)
+ return;
+ }
atomic_set(&conn->conn_logout_remove, 0);
complete(&conn->conn_logout_comp);
@@ -4422,8 +4455,11 @@ static void iscsit_logout_post_handler_samecid(
{
int sleep = 1;
- if (!conn->conn_transport->rdma_shutdown)
+ if (!conn->conn_transport->rdma_shutdown) {
sleep = cmpxchg(&conn->tx_thread_active, true, false);
+ if (!sleep)
+ return;
+ }
atomic_set(&conn->conn_logout_remove, 0);
complete(&conn->conn_logout_comp);
diff --git a/drivers/target/iscsi/iscsi_target_erl0.c b/drivers/target/iscsi/iscsi_target_erl0.c
index 9a96e17bf7cd..7fe2aa73cff6 100644
--- a/drivers/target/iscsi/iscsi_target_erl0.c
+++ b/drivers/target/iscsi/iscsi_target_erl0.c
@@ -930,8 +930,10 @@ static void iscsit_handle_connection_cleanup(struct iscsi_conn *conn)
}
}
-void iscsit_take_action_for_connection_exit(struct iscsi_conn *conn)
+void iscsit_take_action_for_connection_exit(struct iscsi_conn *conn, bool *conn_freed)
{
+ *conn_freed = false;
+
spin_lock_bh(&conn->state_lock);
if (atomic_read(&conn->connection_exit)) {
spin_unlock_bh(&conn->state_lock);
@@ -942,6 +944,7 @@ void iscsit_take_action_for_connection_exit(struct iscsi_conn *conn)
if (conn->conn_state == TARG_CONN_STATE_IN_LOGOUT) {
spin_unlock_bh(&conn->state_lock);
iscsit_close_connection(conn);
+ *conn_freed = true;
return;
}
@@ -955,4 +958,5 @@ void iscsit_take_action_for_connection_exit(struct iscsi_conn *conn)
spin_unlock_bh(&conn->state_lock);
iscsit_handle_connection_cleanup(conn);
+ *conn_freed = true;
}
diff --git a/drivers/target/iscsi/iscsi_target_erl0.h b/drivers/target/iscsi/iscsi_target_erl0.h
index 60e69e2af6ed..3822d9cd1230 100644
--- a/drivers/target/iscsi/iscsi_target_erl0.h
+++ b/drivers/target/iscsi/iscsi_target_erl0.h
@@ -15,6 +15,6 @@ extern int iscsit_stop_time2retain_timer(struct iscsi_session *);
extern void iscsit_connection_reinstatement_rcfr(struct iscsi_conn *);
extern void iscsit_cause_connection_reinstatement(struct iscsi_conn *, int);
extern void iscsit_fall_back_to_erl0(struct iscsi_session *);
-extern void iscsit_take_action_for_connection_exit(struct iscsi_conn *);
+extern void iscsit_take_action_for_connection_exit(struct iscsi_conn *, bool *);
#endif /*** ISCSI_TARGET_ERL0_H ***/
diff --git a/drivers/target/iscsi/iscsi_target_login.c b/drivers/target/iscsi/iscsi_target_login.c
index 66238477137b..92b96b51d506 100644
--- a/drivers/target/iscsi/iscsi_target_login.c
+++ b/drivers/target/iscsi/iscsi_target_login.c
@@ -1464,5 +1464,9 @@ int iscsi_target_login_thread(void *arg)
break;
}
+ while (!kthread_should_stop()) {
+ msleep(100);
+ }
+
return 0;
}
diff --git a/drivers/target/iscsi/iscsi_target_nego.c b/drivers/target/iscsi/iscsi_target_nego.c
index 7ccc9c1cbfd1..6f88b31242b0 100644
--- a/drivers/target/iscsi/iscsi_target_nego.c
+++ b/drivers/target/iscsi/iscsi_target_nego.c
@@ -493,14 +493,60 @@ static void iscsi_target_restore_sock_callbacks(struct iscsi_conn *conn)
static int iscsi_target_do_login(struct iscsi_conn *, struct iscsi_login *);
-static bool iscsi_target_sk_state_check(struct sock *sk)
+static bool __iscsi_target_sk_check_close(struct sock *sk)
{
if (sk->sk_state == TCP_CLOSE_WAIT || sk->sk_state == TCP_CLOSE) {
- pr_debug("iscsi_target_sk_state_check: TCP_CLOSE_WAIT|TCP_CLOSE,"
+ pr_debug("__iscsi_target_sk_check_close: TCP_CLOSE_WAIT|TCP_CLOSE,"
"returning FALSE\n");
- return false;
+ return true;
}
- return true;
+ return false;
+}
+
+static bool iscsi_target_sk_check_close(struct iscsi_conn *conn)
+{
+ bool state = false;
+
+ if (conn->sock) {
+ struct sock *sk = conn->sock->sk;
+
+ read_lock_bh(&sk->sk_callback_lock);
+ state = (__iscsi_target_sk_check_close(sk) ||
+ test_bit(LOGIN_FLAGS_CLOSED, &conn->login_flags));
+ read_unlock_bh(&sk->sk_callback_lock);
+ }
+ return state;
+}
+
+static bool iscsi_target_sk_check_flag(struct iscsi_conn *conn, unsigned int flag)
+{
+ bool state = false;
+
+ if (conn->sock) {
+ struct sock *sk = conn->sock->sk;
+
+ read_lock_bh(&sk->sk_callback_lock);
+ state = test_bit(flag, &conn->login_flags);
+ read_unlock_bh(&sk->sk_callback_lock);
+ }
+ return state;
+}
+
+static bool iscsi_target_sk_check_and_clear(struct iscsi_conn *conn, unsigned int flag)
+{
+ bool state = false;
+
+ if (conn->sock) {
+ struct sock *sk = conn->sock->sk;
+
+ write_lock_bh(&sk->sk_callback_lock);
+ state = (__iscsi_target_sk_check_close(sk) ||
+ test_bit(LOGIN_FLAGS_CLOSED, &conn->login_flags));
+ if (!state)
+ clear_bit(flag, &conn->login_flags);
+ write_unlock_bh(&sk->sk_callback_lock);
+ }
+ return state;
}
static void iscsi_target_login_drop(struct iscsi_conn *conn, struct iscsi_login *login)
@@ -540,6 +586,20 @@ static void iscsi_target_do_login_rx(struct work_struct *work)
pr_debug("entering iscsi_target_do_login_rx, conn: %p, %s:%d\n",
conn, current->comm, current->pid);
+ /*
+ * If iscsi_target_do_login_rx() has been invoked by ->sk_data_ready()
+ * before initial PDU processing in iscsi_target_start_negotiation()
+ * has completed, go ahead and retry until it's cleared.
+ *
+ * Otherwise if the TCP connection drops while this is occuring,
+ * iscsi_target_start_negotiation() will detect the failure, call
+ * cancel_delayed_work_sync(&conn->login_work), and cleanup the
+ * remaining iscsi connection resources from iscsi_np process context.
+ */
+ if (iscsi_target_sk_check_flag(conn, LOGIN_FLAGS_INITIAL_PDU)) {
+ schedule_delayed_work(&conn->login_work, msecs_to_jiffies(10));
+ return;
+ }
spin_lock(&tpg->tpg_state_lock);
state = (tpg->tpg_state == TPG_STATE_ACTIVE);
@@ -547,26 +607,12 @@ static void iscsi_target_do_login_rx(struct work_struct *work)
if (!state) {
pr_debug("iscsi_target_do_login_rx: tpg_state != TPG_STATE_ACTIVE\n");
- iscsi_target_restore_sock_callbacks(conn);
- iscsi_target_login_drop(conn, login);
- iscsit_deaccess_np(np, tpg, tpg_np);
- return;
+ goto err;
}
- if (conn->sock) {
- struct sock *sk = conn->sock->sk;
-
- read_lock_bh(&sk->sk_callback_lock);
- state = iscsi_target_sk_state_check(sk);
- read_unlock_bh(&sk->sk_callback_lock);
-
- if (!state) {
- pr_debug("iscsi_target_do_login_rx, TCP state CLOSE\n");
- iscsi_target_restore_sock_callbacks(conn);
- iscsi_target_login_drop(conn, login);
- iscsit_deaccess_np(np, tpg, tpg_np);
- return;
- }
+ if (iscsi_target_sk_check_close(conn)) {
+ pr_debug("iscsi_target_do_login_rx, TCP state CLOSE\n");
+ goto err;
}
conn->login_kworker = current;
@@ -584,34 +630,29 @@ static void iscsi_target_do_login_rx(struct work_struct *work)
flush_signals(current);
conn->login_kworker = NULL;
- if (rc < 0) {
- iscsi_target_restore_sock_callbacks(conn);
- iscsi_target_login_drop(conn, login);
- iscsit_deaccess_np(np, tpg, tpg_np);
- return;
- }
+ if (rc < 0)
+ goto err;
pr_debug("iscsi_target_do_login_rx after rx_login_io, %p, %s:%d\n",
conn, current->comm, current->pid);
rc = iscsi_target_do_login(conn, login);
if (rc < 0) {
- iscsi_target_restore_sock_callbacks(conn);
- iscsi_target_login_drop(conn, login);
- iscsit_deaccess_np(np, tpg, tpg_np);
+ goto err;
} else if (!rc) {
- if (conn->sock) {
- struct sock *sk = conn->sock->sk;
-
- write_lock_bh(&sk->sk_callback_lock);
- clear_bit(LOGIN_FLAGS_READ_ACTIVE, &conn->login_flags);
- write_unlock_bh(&sk->sk_callback_lock);
- }
+ if (iscsi_target_sk_check_and_clear(conn, LOGIN_FLAGS_READ_ACTIVE))
+ goto err;
} else if (rc == 1) {
iscsi_target_nego_release(conn);
iscsi_post_login_handler(np, conn, zero_tsih);
iscsit_deaccess_np(np, tpg, tpg_np);
}
+ return;
+
+err:
+ iscsi_target_restore_sock_callbacks(conn);
+ iscsi_target_login_drop(conn, login);
+ iscsit_deaccess_np(np, tpg, tpg_np);
}
static void iscsi_target_do_cleanup(struct work_struct *work)
@@ -659,31 +700,54 @@ static void iscsi_target_sk_state_change(struct sock *sk)
orig_state_change(sk);
return;
}
+ state = __iscsi_target_sk_check_close(sk);
+ pr_debug("__iscsi_target_sk_close_change: state: %d\n", state);
+
if (test_bit(LOGIN_FLAGS_READ_ACTIVE, &conn->login_flags)) {
pr_debug("Got LOGIN_FLAGS_READ_ACTIVE=1 sk_state_change"
" conn: %p\n", conn);
+ if (state)
+ set_bit(LOGIN_FLAGS_CLOSED, &conn->login_flags);
write_unlock_bh(&sk->sk_callback_lock);
orig_state_change(sk);
return;
}
- if (test_and_set_bit(LOGIN_FLAGS_CLOSED, &conn->login_flags)) {
+ if (test_bit(LOGIN_FLAGS_CLOSED, &conn->login_flags)) {
pr_debug("Got LOGIN_FLAGS_CLOSED=1 sk_state_change conn: %p\n",
conn);
write_unlock_bh(&sk->sk_callback_lock);
orig_state_change(sk);
return;
}
+ /*
+ * If the TCP connection has dropped, go ahead and set LOGIN_FLAGS_CLOSED,
+ * but only queue conn->login_work -> iscsi_target_do_login_rx()
+ * processing if LOGIN_FLAGS_INITIAL_PDU has already been cleared.
+ *
+ * When iscsi_target_do_login_rx() runs, iscsi_target_sk_check_close()
+ * will detect the dropped TCP connection from delayed workqueue context.
+ *
+ * If LOGIN_FLAGS_INITIAL_PDU is still set, which means the initial
+ * iscsi_target_start_negotiation() is running, iscsi_target_do_login()
+ * via iscsi_target_sk_check_close() or iscsi_target_start_negotiation()
+ * via iscsi_target_sk_check_and_clear() is responsible for detecting the
+ * dropped TCP connection in iscsi_np process context, and cleaning up
+ * the remaining iscsi connection resources.
+ */
+ if (state) {
+ pr_debug("iscsi_target_sk_state_change got failed state\n");
+ set_bit(LOGIN_FLAGS_CLOSED, &conn->login_flags);
+ state = test_bit(LOGIN_FLAGS_INITIAL_PDU, &conn->login_flags);
+ write_unlock_bh(&sk->sk_callback_lock);
- state = iscsi_target_sk_state_check(sk);
- write_unlock_bh(&sk->sk_callback_lock);
-
- pr_debug("iscsi_target_sk_state_change: state: %d\n", state);
+ orig_state_change(sk);
- if (!state) {
- pr_debug("iscsi_target_sk_state_change got failed state\n");
- schedule_delayed_work(&conn->login_cleanup_work, 0);
+ if (!state)
+ schedule_delayed_work(&conn->login_work, 0);
return;
}
+ write_unlock_bh(&sk->sk_callback_lock);
+
orig_state_change(sk);
}
@@ -946,6 +1010,15 @@ static int iscsi_target_do_login(struct iscsi_conn *conn, struct iscsi_login *lo
if (iscsi_target_handle_csg_one(conn, login) < 0)
return -1;
if (login_rsp->flags & ISCSI_FLAG_LOGIN_TRANSIT) {
+ /*
+ * Check to make sure the TCP connection has not
+ * dropped asynchronously while session reinstatement
+ * was occuring in this kthread context, before
+ * transitioning to full feature phase operation.
+ */
+ if (iscsi_target_sk_check_close(conn))
+ return -1;
+
login->tsih = conn->sess->tsih;
login->login_complete = 1;
iscsi_target_restore_sock_callbacks(conn);
@@ -972,21 +1045,6 @@ static int iscsi_target_do_login(struct iscsi_conn *conn, struct iscsi_login *lo
break;
}
- if (conn->sock) {
- struct sock *sk = conn->sock->sk;
- bool state;
-
- read_lock_bh(&sk->sk_callback_lock);
- state = iscsi_target_sk_state_check(sk);
- read_unlock_bh(&sk->sk_callback_lock);
-
- if (!state) {
- pr_debug("iscsi_target_do_login() failed state for"
- " conn: %p\n", conn);
- return -1;
- }
- }
-
return 0;
}
@@ -1255,10 +1313,22 @@ int iscsi_target_start_negotiation(
write_lock_bh(&sk->sk_callback_lock);
set_bit(LOGIN_FLAGS_READY, &conn->login_flags);
+ set_bit(LOGIN_FLAGS_INITIAL_PDU, &conn->login_flags);
write_unlock_bh(&sk->sk_callback_lock);
}
-
+ /*
+ * If iscsi_target_do_login returns zero to signal more PDU
+ * exchanges are required to complete the login, go ahead and
+ * clear LOGIN_FLAGS_INITIAL_PDU but only if the TCP connection
+ * is still active.
+ *
+ * Otherwise if TCP connection dropped asynchronously, go ahead
+ * and perform connection cleanup now.
+ */
ret = iscsi_target_do_login(conn, login);
+ if (!ret && iscsi_target_sk_check_and_clear(conn, LOGIN_FLAGS_INITIAL_PDU))
+ ret = -1;
+
if (ret < 0) {
cancel_delayed_work_sync(&conn->login_work);
cancel_delayed_work_sync(&conn->login_cleanup_work);
diff --git a/drivers/target/target_core_iblock.c b/drivers/target/target_core_iblock.c
index bb069ebe4aa6..c05d38016556 100644
--- a/drivers/target/target_core_iblock.c
+++ b/drivers/target/target_core_iblock.c
@@ -93,7 +93,7 @@ static int iblock_configure_device(struct se_device *dev)
return -EINVAL;
}
- ib_dev->ibd_bio_set = bioset_create(IBLOCK_BIO_POOL_SIZE, 0);
+ ib_dev->ibd_bio_set = bioset_create(IBLOCK_BIO_POOL_SIZE, 0, BIOSET_NEED_BVECS);
if (!ib_dev->ibd_bio_set) {
pr_err("IBLOCK: Unable to create bioset\n");
goto out;
@@ -296,8 +296,8 @@ static void iblock_bio_done(struct bio *bio)
struct se_cmd *cmd = bio->bi_private;
struct iblock_req *ibr = cmd->priv;
- if (bio->bi_error) {
- pr_err("bio error: %p, err: %d\n", bio, bio->bi_error);
+ if (bio->bi_status) {
+ pr_err("bio error: %p, err: %d\n", bio, bio->bi_status);
/*
* Bump the ib_bio_err_cnt and release bio.
*/
@@ -354,11 +354,11 @@ static void iblock_end_io_flush(struct bio *bio)
{
struct se_cmd *cmd = bio->bi_private;
- if (bio->bi_error)
- pr_err("IBLOCK: cache flush failed: %d\n", bio->bi_error);
+ if (bio->bi_status)
+ pr_err("IBLOCK: cache flush failed: %d\n", bio->bi_status);
if (cmd) {
- if (bio->bi_error)
+ if (bio->bi_status)
target_complete_cmd(cmd, SAM_STAT_CHECK_CONDITION);
else
target_complete_cmd(cmd, SAM_STAT_GOOD);
diff --git a/drivers/target/target_core_internal.h b/drivers/target/target_core_internal.h
index 9ab7090f7c83..0912de7c0cf8 100644
--- a/drivers/target/target_core_internal.h
+++ b/drivers/target/target_core_internal.h
@@ -136,7 +136,7 @@ int init_se_kmem_caches(void);
void release_se_kmem_caches(void);
u32 scsi_get_new_index(scsi_index_t);
void transport_subsystem_check_init(void);
-void transport_cmd_finish_abort(struct se_cmd *, int);
+int transport_cmd_finish_abort(struct se_cmd *, int);
unsigned char *transport_dump_cmd_direction(struct se_cmd *);
void transport_dump_dev_state(struct se_device *, char *, int *);
void transport_dump_dev_info(struct se_device *, struct se_lun *,
diff --git a/drivers/target/target_core_pscsi.c b/drivers/target/target_core_pscsi.c
index 3e4abb13f8ea..ceec0211e84e 100644
--- a/drivers/target/target_core_pscsi.c
+++ b/drivers/target/target_core_pscsi.c
@@ -55,7 +55,7 @@ static inline struct pscsi_dev_virt *PSCSI_DEV(struct se_device *dev)
}
static sense_reason_t pscsi_execute_cmd(struct se_cmd *cmd);
-static void pscsi_req_done(struct request *, int);
+static void pscsi_req_done(struct request *, blk_status_t);
/* pscsi_attach_hba():
*
@@ -992,8 +992,6 @@ pscsi_execute_cmd(struct se_cmd *cmd)
goto fail;
}
- scsi_req_init(req);
-
if (sgl) {
ret = pscsi_map_sg(cmd, sgl, sgl_nents, req);
if (ret)
@@ -1045,7 +1043,7 @@ static sector_t pscsi_get_blocks(struct se_device *dev)
return 0;
}
-static void pscsi_req_done(struct request *req, int uptodate)
+static void pscsi_req_done(struct request *req, blk_status_t status)
{
struct se_cmd *cmd = req->end_io_data;
struct pscsi_plugin_task *pt = cmd->priv;
diff --git a/drivers/target/target_core_tmr.c b/drivers/target/target_core_tmr.c
index dce1e1b47316..13f47bf4d16b 100644
--- a/drivers/target/target_core_tmr.c
+++ b/drivers/target/target_core_tmr.c
@@ -75,7 +75,7 @@ void core_tmr_release_req(struct se_tmr_req *tmr)
kfree(tmr);
}
-static void core_tmr_handle_tas_abort(struct se_cmd *cmd, int tas)
+static int core_tmr_handle_tas_abort(struct se_cmd *cmd, int tas)
{
unsigned long flags;
bool remove = true, send_tas;
@@ -91,7 +91,7 @@ static void core_tmr_handle_tas_abort(struct se_cmd *cmd, int tas)
transport_send_task_abort(cmd);
}
- transport_cmd_finish_abort(cmd, remove);
+ return transport_cmd_finish_abort(cmd, remove);
}
static int target_check_cdb_and_preempt(struct list_head *list,
@@ -184,8 +184,8 @@ void core_tmr_abort_task(
cancel_work_sync(&se_cmd->work);
transport_wait_for_tasks(se_cmd);
- transport_cmd_finish_abort(se_cmd, true);
- target_put_sess_cmd(se_cmd);
+ if (!transport_cmd_finish_abort(se_cmd, true))
+ target_put_sess_cmd(se_cmd);
printk("ABORT_TASK: Sending TMR_FUNCTION_COMPLETE for"
" ref_tag: %llu\n", ref_tag);
@@ -281,8 +281,8 @@ static void core_tmr_drain_tmr_list(
cancel_work_sync(&cmd->work);
transport_wait_for_tasks(cmd);
- transport_cmd_finish_abort(cmd, 1);
- target_put_sess_cmd(cmd);
+ if (!transport_cmd_finish_abort(cmd, 1))
+ target_put_sess_cmd(cmd);
}
}
@@ -380,8 +380,8 @@ static void core_tmr_drain_state_list(
cancel_work_sync(&cmd->work);
transport_wait_for_tasks(cmd);
- core_tmr_handle_tas_abort(cmd, tas);
- target_put_sess_cmd(cmd);
+ if (!core_tmr_handle_tas_abort(cmd, tas))
+ target_put_sess_cmd(cmd);
}
}
diff --git a/drivers/target/target_core_transport.c b/drivers/target/target_core_transport.c
index 37f57357d4a0..f1b3a46bdcaf 100644
--- a/drivers/target/target_core_transport.c
+++ b/drivers/target/target_core_transport.c
@@ -651,9 +651,10 @@ static void transport_lun_remove_cmd(struct se_cmd *cmd)
percpu_ref_put(&lun->lun_ref);
}
-void transport_cmd_finish_abort(struct se_cmd *cmd, int remove)
+int transport_cmd_finish_abort(struct se_cmd *cmd, int remove)
{
bool ack_kref = (cmd->se_cmd_flags & SCF_ACK_KREF);
+ int ret = 0;
if (cmd->se_cmd_flags & SCF_SE_LUN_CMD)
transport_lun_remove_cmd(cmd);
@@ -665,9 +666,11 @@ void transport_cmd_finish_abort(struct se_cmd *cmd, int remove)
cmd->se_tfo->aborted_task(cmd);
if (transport_cmd_check_stop_to_fabric(cmd))
- return;
+ return 1;
if (remove && ack_kref)
- transport_put_cmd(cmd);
+ ret = transport_put_cmd(cmd);
+
+ return ret;
}
static void target_complete_failure_work(struct work_struct *work)
@@ -1160,15 +1163,28 @@ target_cmd_size_check(struct se_cmd *cmd, unsigned int size)
if (cmd->unknown_data_length) {
cmd->data_length = size;
} else if (size != cmd->data_length) {
- pr_warn("TARGET_CORE[%s]: Expected Transfer Length:"
+ pr_warn_ratelimited("TARGET_CORE[%s]: Expected Transfer Length:"
" %u does not match SCSI CDB Length: %u for SAM Opcode:"
" 0x%02x\n", cmd->se_tfo->get_fabric_name(),
cmd->data_length, size, cmd->t_task_cdb[0]);
- if (cmd->data_direction == DMA_TO_DEVICE &&
- cmd->se_cmd_flags & SCF_SCSI_DATA_CDB) {
- pr_err("Rejecting underflow/overflow WRITE data\n");
- return TCM_INVALID_CDB_FIELD;
+ if (cmd->data_direction == DMA_TO_DEVICE) {
+ if (cmd->se_cmd_flags & SCF_SCSI_DATA_CDB) {
+ pr_err_ratelimited("Rejecting underflow/overflow"
+ " for WRITE data CDB\n");
+ return TCM_INVALID_CDB_FIELD;
+ }
+ /*
+ * Some fabric drivers like iscsi-target still expect to
+ * always reject overflow writes. Reject this case until
+ * full fabric driver level support for overflow writes
+ * is introduced tree-wide.
+ */
+ if (size > cmd->data_length) {
+ pr_err_ratelimited("Rejecting overflow for"
+ " WRITE control CDB\n");
+ return TCM_INVALID_CDB_FIELD;
+ }
}
/*
* Reject READ_* or WRITE_* with overflow/underflow for
diff --git a/drivers/target/target_core_user.c b/drivers/target/target_core_user.c
index 9045837f748b..beb5f098f32d 100644
--- a/drivers/target/target_core_user.c
+++ b/drivers/target/target_core_user.c
@@ -97,7 +97,7 @@ struct tcmu_hba {
struct tcmu_dev {
struct list_head node;
-
+ struct kref kref;
struct se_device se_dev;
char *name;
@@ -969,6 +969,7 @@ static struct se_device *tcmu_alloc_device(struct se_hba *hba, const char *name)
udev = kzalloc(sizeof(struct tcmu_dev), GFP_KERNEL);
if (!udev)
return NULL;
+ kref_init(&udev->kref);
udev->name = kstrdup(name, GFP_KERNEL);
if (!udev->name) {
@@ -1145,6 +1146,24 @@ static int tcmu_open(struct uio_info *info, struct inode *inode)
return 0;
}
+static void tcmu_dev_call_rcu(struct rcu_head *p)
+{
+ struct se_device *dev = container_of(p, struct se_device, rcu_head);
+ struct tcmu_dev *udev = TCMU_DEV(dev);
+
+ kfree(udev->uio_info.name);
+ kfree(udev->name);
+ kfree(udev);
+}
+
+static void tcmu_dev_kref_release(struct kref *kref)
+{
+ struct tcmu_dev *udev = container_of(kref, struct tcmu_dev, kref);
+ struct se_device *dev = &udev->se_dev;
+
+ call_rcu(&dev->rcu_head, tcmu_dev_call_rcu);
+}
+
static int tcmu_release(struct uio_info *info, struct inode *inode)
{
struct tcmu_dev *udev = container_of(info, struct tcmu_dev, uio_info);
@@ -1152,7 +1171,8 @@ static int tcmu_release(struct uio_info *info, struct inode *inode)
clear_bit(TCMU_DEV_BIT_OPEN, &udev->flags);
pr_debug("close\n");
-
+ /* release ref from configure */
+ kref_put(&udev->kref, tcmu_dev_kref_release);
return 0;
}
@@ -1272,6 +1292,12 @@ static int tcmu_configure_device(struct se_device *dev)
dev->dev_attrib.hw_max_sectors = 128;
dev->dev_attrib.hw_queue_depth = 128;
+ /*
+ * Get a ref incase userspace does a close on the uio device before
+ * LIO has initiated tcmu_free_device.
+ */
+ kref_get(&udev->kref);
+
ret = tcmu_netlink_event(TCMU_CMD_ADDED_DEVICE, udev->uio_info.name,
udev->uio_info.uio_dev->minor);
if (ret)
@@ -1284,11 +1310,13 @@ static int tcmu_configure_device(struct se_device *dev)
return 0;
err_netlink:
+ kref_put(&udev->kref, tcmu_dev_kref_release);
uio_unregister_device(&udev->uio_info);
err_register:
vfree(udev->mb_addr);
err_vzalloc:
kfree(info->name);
+ info->name = NULL;
return ret;
}
@@ -1302,14 +1330,6 @@ static int tcmu_check_and_free_pending_cmd(struct tcmu_cmd *cmd)
return -EINVAL;
}
-static void tcmu_dev_call_rcu(struct rcu_head *p)
-{
- struct se_device *dev = container_of(p, struct se_device, rcu_head);
- struct tcmu_dev *udev = TCMU_DEV(dev);
-
- kfree(udev);
-}
-
static bool tcmu_dev_configured(struct tcmu_dev *udev)
{
return udev->uio_info.uio_dev ? true : false;
@@ -1364,10 +1384,10 @@ static void tcmu_free_device(struct se_device *dev)
udev->uio_info.uio_dev->minor);
uio_unregister_device(&udev->uio_info);
- kfree(udev->uio_info.name);
- kfree(udev->name);
}
- call_rcu(&dev->rcu_head, tcmu_dev_call_rcu);
+
+ /* release ref from init */
+ kref_put(&udev->kref, tcmu_dev_kref_release);
}
enum {
diff --git a/drivers/thermal/broadcom/Kconfig b/drivers/thermal/broadcom/Kconfig
index ab08af4654ef..42c098e86f84 100644
--- a/drivers/thermal/broadcom/Kconfig
+++ b/drivers/thermal/broadcom/Kconfig
@@ -9,8 +9,9 @@ config BCM2835_THERMAL
config BCM_NS_THERMAL
tristate "Northstar thermal driver"
depends on ARCH_BCM_IPROC || COMPILE_TEST
+ default y if ARCH_BCM_IPROC
help
- Northstar is a family of SoCs that includes e.g. BCM4708, BCM47081,
- BCM4709 and BCM47094. It contains DMU (Device Management Unit) block
- with a thermal sensor that allows checking CPU temperature. This
- driver provides support for it.
+ Support for the Northstar and Northstar Plus family of SoCs (e.g.
+ BCM4708, BCM4709, BCM5301x, BCM95852X, etc). It contains DMU (Device
+ Management Unit) block with a thermal sensor that allows checking CPU
+ temperature.
diff --git a/drivers/thermal/int340x_thermal/int3400_thermal.c b/drivers/thermal/int340x_thermal/int3400_thermal.c
index 9413c4abf0b9..a9ec94ed7a42 100644
--- a/drivers/thermal/int340x_thermal/int3400_thermal.c
+++ b/drivers/thermal/int340x_thermal/int3400_thermal.c
@@ -23,7 +23,7 @@ enum int3400_thermal_uuid {
INT3400_THERMAL_MAXIMUM_UUID,
};
-static u8 *int3400_thermal_uuids[INT3400_THERMAL_MAXIMUM_UUID] = {
+static char *int3400_thermal_uuids[INT3400_THERMAL_MAXIMUM_UUID] = {
"42A441D6-AE6A-462b-A84B-4A8CE79027D3",
"3A95C389-E4B8-4629-A526-C52C88626BAE",
"97C68AE7-15FA-499c-B8C9-5DA81D606E0A",
@@ -141,10 +141,10 @@ static int int3400_thermal_get_uuids(struct int3400_thermal_priv *priv)
}
for (j = 0; j < INT3400_THERMAL_MAXIMUM_UUID; j++) {
- u8 uuid[16];
+ guid_t guid;
- acpi_str_to_uuid(int3400_thermal_uuids[j], uuid);
- if (!strncmp(uuid, objb->buffer.pointer, 16)) {
+ guid_parse(int3400_thermal_uuids[j], &guid);
+ if (guid_equal((guid_t *)objb->buffer.pointer, &guid)) {
priv->uuid_bitmap |= (1 << j);
break;
}
diff --git a/drivers/thermal/max77620_thermal.c b/drivers/thermal/max77620_thermal.c
index e9a1fe342760..159bbcee8821 100644
--- a/drivers/thermal/max77620_thermal.c
+++ b/drivers/thermal/max77620_thermal.c
@@ -104,8 +104,6 @@ static int max77620_thermal_probe(struct platform_device *pdev)
return -EINVAL;
}
- pdev->dev.of_node = pdev->dev.parent->of_node;
-
mtherm->dev = &pdev->dev;
mtherm->rmap = dev_get_regmap(pdev->dev.parent, NULL);
if (!mtherm->rmap) {
@@ -113,6 +111,12 @@ static int max77620_thermal_probe(struct platform_device *pdev)
return -ENODEV;
}
+ /*
+ * The reference taken to the parent's node which will be balanced on
+ * reprobe or on platform-device release.
+ */
+ device_set_of_node_from_dev(&pdev->dev, pdev->dev.parent);
+
mtherm->tz_device = devm_thermal_zone_of_sensor_register(&pdev->dev, 0,
mtherm, &max77620_thermal_ops);
if (IS_ERR(mtherm->tz_device)) {
diff --git a/drivers/thermal/qoriq_thermal.c b/drivers/thermal/qoriq_thermal.c
index 644ba526d9ea..4362a69ac88d 100644
--- a/drivers/thermal/qoriq_thermal.c
+++ b/drivers/thermal/qoriq_thermal.c
@@ -195,7 +195,6 @@ static struct thermal_zone_of_device_ops tmu_tz_ops = {
static int qoriq_tmu_probe(struct platform_device *pdev)
{
int ret;
- const struct thermal_trip *trip;
struct qoriq_tmu_data *data;
struct device_node *np = pdev->dev.of_node;
u32 site = 0;
@@ -243,8 +242,6 @@ static int qoriq_tmu_probe(struct platform_device *pdev)
goto err_tmu;
}
- trip = of_thermal_get_trip_points(data->tz);
-
/* Enable monitoring */
site |= 0x1 << (15 - data->sensor_id);
tmu_write(data, site | TMR_ME | TMR_ALPF, &data->regs->tmr);
diff --git a/drivers/thermal/thermal_core.c b/drivers/thermal/thermal_core.c
index b21b9cc2c8d6..5a51c740e372 100644
--- a/drivers/thermal/thermal_core.c
+++ b/drivers/thermal/thermal_core.c
@@ -359,7 +359,7 @@ static DECLARE_DELAYED_WORK(thermal_emergency_poweroff_work,
* This may be called from any critical situation to trigger a system shutdown
* after a known period of time. By default this is not scheduled.
*/
-void thermal_emergency_poweroff(void)
+static void thermal_emergency_poweroff(void)
{
int poweroff_delay_ms = CONFIG_THERMAL_EMERGENCY_POWEROFF_DELAY_MS;
/*
diff --git a/drivers/thermal/ti-soc-thermal/ti-bandgap.c b/drivers/thermal/ti-soc-thermal/ti-bandgap.c
index ba9c302454fb..696ab3046b87 100644
--- a/drivers/thermal/ti-soc-thermal/ti-bandgap.c
+++ b/drivers/thermal/ti-soc-thermal/ti-bandgap.c
@@ -1010,7 +1010,7 @@ ti_bandgap_force_single_read(struct ti_bandgap *bgp, int id)
}
/**
- * ti_bandgap_set_continous_mode() - One time enabling of continuous mode
+ * ti_bandgap_set_continuous_mode() - One time enabling of continuous mode
* @bgp: pointer to struct ti_bandgap
*
* Call this function only if HAS(MODE_CONFIG) is set. As this driver may
@@ -1214,22 +1214,18 @@ static struct ti_bandgap *ti_bandgap_build(struct platform_device *pdev)
}
bgp = devm_kzalloc(&pdev->dev, sizeof(*bgp), GFP_KERNEL);
- if (!bgp) {
- dev_err(&pdev->dev, "Unable to allocate mem for driver ref\n");
+ if (!bgp)
return ERR_PTR(-ENOMEM);
- }
of_id = of_match_device(of_ti_bandgap_match, &pdev->dev);
if (of_id)
bgp->conf = of_id->data;
/* register shadow for context save and restore */
- bgp->regval = devm_kzalloc(&pdev->dev, sizeof(*bgp->regval) *
- bgp->conf->sensor_count, GFP_KERNEL);
- if (!bgp->regval) {
- dev_err(&pdev->dev, "Unable to allocate mem for driver ref\n");
+ bgp->regval = devm_kcalloc(&pdev->dev, bgp->conf->sensor_count,
+ sizeof(*bgp->regval), GFP_KERNEL);
+ if (!bgp->regval)
return ERR_PTR(-ENOMEM);
- }
i = 0;
do {
diff --git a/drivers/tty/Makefile b/drivers/tty/Makefile
index f02becdb3e33..8689279afdf1 100644
--- a/drivers/tty/Makefile
+++ b/drivers/tty/Makefile
@@ -1,6 +1,7 @@
obj-$(CONFIG_TTY) += tty_io.o n_tty.o tty_ioctl.o tty_ldisc.o \
tty_buffer.o tty_port.o tty_mutex.o \
- tty_ldsem.o tty_baudrate.o tty_jobctrl.o
+ tty_ldsem.o tty_baudrate.o tty_jobctrl.o \
+ n_null.o
obj-$(CONFIG_LEGACY_PTYS) += pty.o
obj-$(CONFIG_UNIX98_PTYS) += pty.o
obj-$(CONFIG_AUDIT) += tty_audit.o
diff --git a/drivers/tty/amiserial.c b/drivers/tty/amiserial.c
index dea16bb8c46a..9820e20993db 100644
--- a/drivers/tty/amiserial.c
+++ b/drivers/tty/amiserial.c
@@ -570,18 +570,6 @@ static int startup(struct tty_struct *tty, struct serial_state *info)
info->xmit.head = info->xmit.tail = 0;
/*
- * Set up the tty->alt_speed kludge
- */
- if ((port->flags & ASYNC_SPD_MASK) == ASYNC_SPD_HI)
- tty->alt_speed = 57600;
- if ((port->flags & ASYNC_SPD_MASK) == ASYNC_SPD_VHI)
- tty->alt_speed = 115200;
- if ((port->flags & ASYNC_SPD_MASK) == ASYNC_SPD_SHI)
- tty->alt_speed = 230400;
- if ((port->flags & ASYNC_SPD_MASK) == ASYNC_SPD_WARP)
- tty->alt_speed = 460800;
-
- /*
* and set the speed of the serial port
*/
change_speed(tty, info, NULL);
@@ -1084,14 +1072,9 @@ static int set_serial_info(struct tty_struct *tty, struct serial_state *state,
check_and_exit:
if (tty_port_initialized(port)) {
if (change_spd) {
- if ((port->flags & ASYNC_SPD_MASK) == ASYNC_SPD_HI)
- tty->alt_speed = 57600;
- if ((port->flags & ASYNC_SPD_MASK) == ASYNC_SPD_VHI)
- tty->alt_speed = 115200;
- if ((port->flags & ASYNC_SPD_MASK) == ASYNC_SPD_SHI)
- tty->alt_speed = 230400;
- if ((port->flags & ASYNC_SPD_MASK) == ASYNC_SPD_WARP)
- tty->alt_speed = 460800;
+ /* warn about deprecation unless clearing */
+ if (new_serial.flags & ASYNC_SPD_MASK)
+ dev_warn_ratelimited(tty->dev, "use of SPD flags is deprecated\n");
change_speed(tty, state, NULL);
}
} else
diff --git a/drivers/tty/cyclades.c b/drivers/tty/cyclades.c
index 104f09c58163..d272bc4e7fb5 100644
--- a/drivers/tty/cyclades.c
+++ b/drivers/tty/cyclades.c
@@ -1975,18 +1975,6 @@ static void cy_set_line_char(struct cyclades_port *info, struct tty_struct *tty)
cflag = tty->termios.c_cflag;
iflag = tty->termios.c_iflag;
- /*
- * Set up the tty->alt_speed kludge
- */
- if ((info->port.flags & ASYNC_SPD_MASK) == ASYNC_SPD_HI)
- tty->alt_speed = 57600;
- if ((info->port.flags & ASYNC_SPD_MASK) == ASYNC_SPD_VHI)
- tty->alt_speed = 115200;
- if ((info->port.flags & ASYNC_SPD_MASK) == ASYNC_SPD_SHI)
- tty->alt_speed = 230400;
- if ((info->port.flags & ASYNC_SPD_MASK) == ASYNC_SPD_WARP)
- tty->alt_speed = 460800;
-
card = info->card;
channel = info->line - card->first_line;
@@ -2295,12 +2283,16 @@ cy_set_serial_info(struct cyclades_port *info, struct tty_struct *tty,
struct serial_struct __user *new_info)
{
struct serial_struct new_serial;
+ int old_flags;
int ret;
if (copy_from_user(&new_serial, new_info, sizeof(new_serial)))
return -EFAULT;
mutex_lock(&info->port.mutex);
+
+ old_flags = info->port.flags;
+
if (!capable(CAP_SYS_ADMIN)) {
if (new_serial.close_delay != info->port.close_delay ||
new_serial.baud_base != info->baud ||
@@ -2332,6 +2324,11 @@ cy_set_serial_info(struct cyclades_port *info, struct tty_struct *tty,
check_and_exit:
if (tty_port_initialized(&info->port)) {
+ if ((new_serial.flags ^ old_flags) & ASYNC_SPD_MASK) {
+ /* warn about deprecation unless clearing */
+ if (new_serial.flags & ASYNC_SPD_MASK)
+ dev_warn_ratelimited(tty->dev, "use of SPD flags is deprecated\n");
+ }
cy_set_line_char(info, tty);
ret = 0;
} else {
diff --git a/drivers/tty/ehv_bytechan.c b/drivers/tty/ehv_bytechan.c
index 7ac9bcdf1e61..61fe8d6fd24e 100644
--- a/drivers/tty/ehv_bytechan.c
+++ b/drivers/tty/ehv_bytechan.c
@@ -764,7 +764,7 @@ static int __init ehv_bc_init(void)
ehv_bc_driver = alloc_tty_driver(count);
if (!ehv_bc_driver) {
ret = -ENOMEM;
- goto error;
+ goto err_free_bcs;
}
ehv_bc_driver->driver_name = "ehv-bc";
@@ -778,24 +778,23 @@ static int __init ehv_bc_init(void)
ret = tty_register_driver(ehv_bc_driver);
if (ret) {
pr_err("ehv-bc: could not register tty driver (ret=%i)\n", ret);
- goto error;
+ goto err_put_tty_driver;
}
ret = platform_driver_register(&ehv_bc_tty_driver);
if (ret) {
pr_err("ehv-bc: could not register platform driver (ret=%i)\n",
ret);
- goto error;
+ goto err_deregister_tty_driver;
}
return 0;
-error:
- if (ehv_bc_driver) {
- tty_unregister_driver(ehv_bc_driver);
- put_tty_driver(ehv_bc_driver);
- }
-
+err_deregister_tty_driver:
+ tty_unregister_driver(ehv_bc_driver);
+err_put_tty_driver:
+ put_tty_driver(ehv_bc_driver);
+err_free_bcs:
kfree(bcs);
return ret;
diff --git a/drivers/tty/hvc/Kconfig b/drivers/tty/hvc/Kconfig
index 574da15fe618..b8d5ea0ae26b 100644
--- a/drivers/tty/hvc/Kconfig
+++ b/drivers/tty/hvc/Kconfig
@@ -44,7 +44,7 @@ config HVC_RTAS
config HVC_IUCV
bool "z/VM IUCV Hypervisor console support (VM only)"
- depends on S390
+ depends on S390 && NET
select HVC_DRIVER
select IUCV
default y
diff --git a/drivers/tty/hvc/hvcs.c b/drivers/tty/hvc/hvcs.c
index 096ea5f511bd..79cc5beea2da 100644
--- a/drivers/tty/hvc/hvcs.c
+++ b/drivers/tty/hvc/hvcs.c
@@ -1241,8 +1241,7 @@ static void hvcs_close(struct tty_struct *tty, struct file *filp)
free_irq(irq, hvcsd);
return;
} else if (hvcsd->port.count < 0) {
- printk(KERN_ERR "HVCS: vty-server@%X open_count: %d"
- " is missmanaged.\n",
+ printk(KERN_ERR "HVCS: vty-server@%X open_count: %d is mismanaged.\n",
hvcsd->vdev->unit_address, hvcsd->port.count);
}
diff --git a/drivers/tty/n_gsm.c b/drivers/tty/n_gsm.c
index 2667a205a5ab..363a8ca824ad 100644
--- a/drivers/tty/n_gsm.c
+++ b/drivers/tty/n_gsm.c
@@ -2015,6 +2015,33 @@ static void gsm_error(struct gsm_mux *gsm,
gsm->io_error++;
}
+static int gsm_disconnect(struct gsm_mux *gsm)
+{
+ struct gsm_dlci *dlci = gsm->dlci[0];
+ struct gsm_control *gc;
+
+ if (!dlci)
+ return 0;
+
+ /* In theory disconnecting DLCI 0 is sufficient but for some
+ modems this is apparently not the case. */
+ gc = gsm_control_send(gsm, CMD_CLD, NULL, 0);
+ if (gc)
+ gsm_control_wait(gsm, gc);
+
+ del_timer_sync(&gsm->t2_timer);
+ /* Now we are sure T2 has stopped */
+
+ gsm_dlci_begin_close(dlci);
+ wait_event_interruptible(gsm->event,
+ dlci->state == DLCI_CLOSED);
+
+ if (signal_pending(current))
+ return -EINTR;
+
+ return 0;
+}
+
/**
* gsm_cleanup_mux - generic GSM protocol cleanup
* @gsm: our mux
@@ -2029,7 +2056,6 @@ static void gsm_cleanup_mux(struct gsm_mux *gsm)
int i;
struct gsm_dlci *dlci = gsm->dlci[0];
struct gsm_msg *txq, *ntxq;
- struct gsm_control *gc;
gsm->dead = 1;
@@ -2045,21 +2071,11 @@ static void gsm_cleanup_mux(struct gsm_mux *gsm)
if (i == MAX_MUX)
return;
- /* In theory disconnecting DLCI 0 is sufficient but for some
- modems this is apparently not the case. */
- if (dlci) {
- gc = gsm_control_send(gsm, CMD_CLD, NULL, 0);
- if (gc)
- gsm_control_wait(gsm, gc);
- }
del_timer_sync(&gsm->t2_timer);
/* Now we are sure T2 has stopped */
- if (dlci) {
+ if (dlci)
dlci->dead = 1;
- gsm_dlci_begin_close(dlci);
- wait_event_interruptible(gsm->event,
- dlci->state == DLCI_CLOSED);
- }
+
/* Free up any link layer users */
mutex_lock(&gsm->mutex);
for (i = 0; i < NUM_DLCI; i++)
@@ -2519,12 +2535,12 @@ static int gsmld_config(struct tty_struct *tty, struct gsm_mux *gsm,
*/
if (need_close || need_restart) {
- gsm_dlci_begin_close(gsm->dlci[0]);
- /* This will timeout if the link is down due to N2 expiring */
- wait_event_interruptible(gsm->event,
- gsm->dlci[0]->state == DLCI_CLOSED);
- if (signal_pending(current))
- return -EINTR;
+ int ret;
+
+ ret = gsm_disconnect(gsm);
+
+ if (ret)
+ return ret;
}
if (need_restart)
gsm_cleanup_mux(gsm);
diff --git a/drivers/tty/n_null.c b/drivers/tty/n_null.c
new file mode 100644
index 000000000000..d63261c36e42
--- /dev/null
+++ b/drivers/tty/n_null.c
@@ -0,0 +1,80 @@
+#include <linux/types.h>
+#include <linux/errno.h>
+#include <linux/tty.h>
+#include <linux/module.h>
+
+/*
+ * n_null.c - Null line discipline used in the failure path
+ *
+ * Copyright (C) Intel 2017
+ *
+ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ */
+
+static int n_null_open(struct tty_struct *tty)
+{
+ return 0;
+}
+
+static void n_null_close(struct tty_struct *tty)
+{
+}
+
+static ssize_t n_null_read(struct tty_struct *tty, struct file *file,
+ unsigned char __user * buf, size_t nr)
+{
+ return -EOPNOTSUPP;
+}
+
+static ssize_t n_null_write(struct tty_struct *tty, struct file *file,
+ const unsigned char *buf, size_t nr)
+{
+ return -EOPNOTSUPP;
+}
+
+static void n_null_receivebuf(struct tty_struct *tty,
+ const unsigned char *cp, char *fp,
+ int cnt)
+{
+}
+
+static struct tty_ldisc_ops null_ldisc = {
+ .owner = THIS_MODULE,
+ .magic = TTY_LDISC_MAGIC,
+ .name = "n_null",
+ .open = n_null_open,
+ .close = n_null_close,
+ .read = n_null_read,
+ .write = n_null_write,
+ .receive_buf = n_null_receivebuf
+};
+
+static int __init n_null_init(void)
+{
+ BUG_ON(tty_register_ldisc(N_NULL, &null_ldisc));
+ return 0;
+}
+
+static void __exit n_null_exit(void)
+{
+ tty_unregister_ldisc(N_NULL);
+}
+
+module_init(n_null_init);
+module_exit(n_null_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Alan Cox");
+MODULE_ALIAS_LDISC(N_NULL);
+MODULE_DESCRIPTION("Null ldisc driver");
diff --git a/drivers/tty/pty.c b/drivers/tty/pty.c
index 65799575c666..d1399aac05a1 100644
--- a/drivers/tty/pty.c
+++ b/drivers/tty/pty.c
@@ -24,6 +24,9 @@
#include <linux/slab.h>
#include <linux/mutex.h>
#include <linux/poll.h>
+#include <linux/mount.h>
+#include <linux/file.h>
+#include <linux/ioctl.h>
#undef TTY_DEBUG_HANGUP
#ifdef TTY_DEBUG_HANGUP
@@ -66,8 +69,13 @@ static void pty_close(struct tty_struct *tty, struct file *filp)
#ifdef CONFIG_UNIX98_PTYS
if (tty->driver == ptm_driver) {
mutex_lock(&devpts_mutex);
- if (tty->link->driver_data)
- devpts_pty_kill(tty->link->driver_data);
+ if (tty->link->driver_data) {
+ struct path *path = tty->link->driver_data;
+
+ devpts_pty_kill(path->dentry);
+ path_put(path);
+ kfree(path);
+ }
mutex_unlock(&devpts_mutex);
}
#endif
@@ -440,6 +448,48 @@ err:
return retval;
}
+/**
+ * pty_open_peer - open the peer of a pty
+ * @tty: the peer of the pty being opened
+ *
+ * Open the cached dentry in tty->link, providing a safe way for userspace
+ * to get the slave end of a pty (where they have the master fd and cannot
+ * access or trust the mount namespace /dev/pts was mounted inside).
+ */
+static struct file *pty_open_peer(struct tty_struct *tty, int flags)
+{
+ if (tty->driver->subtype != PTY_TYPE_MASTER)
+ return ERR_PTR(-EIO);
+ return dentry_open(tty->link->driver_data, flags, current_cred());
+}
+
+static int pty_get_peer(struct tty_struct *tty, int flags)
+{
+ int fd = -1;
+ struct file *filp = NULL;
+ int retval = -EINVAL;
+
+ fd = get_unused_fd_flags(0);
+ if (fd < 0) {
+ retval = fd;
+ goto err;
+ }
+
+ filp = pty_open_peer(tty, flags);
+ if (IS_ERR(filp)) {
+ retval = PTR_ERR(filp);
+ goto err_put;
+ }
+
+ fd_install(fd, filp);
+ return fd;
+
+err_put:
+ put_unused_fd(fd);
+err:
+ return retval;
+}
+
static void pty_cleanup(struct tty_struct *tty)
{
tty_port_put(tty->port);
@@ -481,6 +531,16 @@ static int pty_bsd_ioctl(struct tty_struct *tty,
return -ENOIOCTLCMD;
}
+static long pty_bsd_compat_ioctl(struct tty_struct *tty,
+ unsigned int cmd, unsigned long arg)
+{
+ /*
+ * PTY ioctls don't require any special translation between 32-bit and
+ * 64-bit userspace, they are already compatible.
+ */
+ return pty_bsd_ioctl(tty, cmd, arg);
+}
+
static int legacy_count = CONFIG_LEGACY_PTY_COUNT;
/*
* not really modular, but the easiest way to keep compat with existing
@@ -502,6 +562,7 @@ static const struct tty_operations master_pty_ops_bsd = {
.chars_in_buffer = pty_chars_in_buffer,
.unthrottle = pty_unthrottle,
.ioctl = pty_bsd_ioctl,
+ .compat_ioctl = pty_bsd_compat_ioctl,
.cleanup = pty_cleanup,
.resize = pty_resize,
.remove = pty_remove
@@ -602,6 +663,8 @@ static int pty_unix98_ioctl(struct tty_struct *tty,
return pty_get_pktmode(tty, (int __user *)arg);
case TIOCGPTN: /* Get PT Number */
return put_user(tty->index, (unsigned int __user *)arg);
+ case TIOCGPTPEER: /* Open the other end */
+ return pty_get_peer(tty, (int) arg);
case TIOCSIG: /* Send signal to other side of pty */
return pty_signal(tty, (int) arg);
}
@@ -609,6 +672,16 @@ static int pty_unix98_ioctl(struct tty_struct *tty,
return -ENOIOCTLCMD;
}
+static long pty_unix98_compat_ioctl(struct tty_struct *tty,
+ unsigned int cmd, unsigned long arg)
+{
+ /*
+ * PTY ioctls don't require any special translation between 32-bit and
+ * 64-bit userspace, they are already compatible.
+ */
+ return pty_unix98_ioctl(tty, cmd, arg);
+}
+
/**
* ptm_unix98_lookup - find a pty master
* @driver: ptm driver
@@ -681,6 +754,7 @@ static const struct tty_operations ptm_unix98_ops = {
.chars_in_buffer = pty_chars_in_buffer,
.unthrottle = pty_unthrottle,
.ioctl = pty_unix98_ioctl,
+ .compat_ioctl = pty_unix98_compat_ioctl,
.resize = pty_resize,
.cleanup = pty_cleanup
};
@@ -718,6 +792,7 @@ static int ptmx_open(struct inode *inode, struct file *filp)
{
struct pts_fs_info *fsi;
struct tty_struct *tty;
+ struct path *pts_path;
struct dentry *dentry;
int retval;
int index;
@@ -771,16 +846,26 @@ static int ptmx_open(struct inode *inode, struct file *filp)
retval = PTR_ERR(dentry);
goto err_release;
}
- tty->link->driver_data = dentry;
+ /* We need to cache a fake path for TIOCGPTPEER. */
+ pts_path = kmalloc(sizeof(struct path), GFP_KERNEL);
+ if (!pts_path)
+ goto err_release;
+ pts_path->mnt = filp->f_path.mnt;
+ pts_path->dentry = dentry;
+ path_get(pts_path);
+ tty->link->driver_data = pts_path;
retval = ptm_driver->ops->open(tty, filp);
if (retval)
- goto err_release;
+ goto err_path_put;
tty_debug_hangup(tty, "opening (count=%d)\n", tty->count);
tty_unlock(tty);
return 0;
+err_path_put:
+ path_put(pts_path);
+ kfree(pts_path);
err_release:
tty_unlock(tty);
// This will also put-ref the fsi
diff --git a/drivers/tty/rocket.c b/drivers/tty/rocket.c
index b51a877da986..20d79a6007d5 100644
--- a/drivers/tty/rocket.c
+++ b/drivers/tty/rocket.c
@@ -947,18 +947,6 @@ static int rp_open(struct tty_struct *tty, struct file *filp)
tty_port_set_initialized(&info->port, 1);
- /*
- * Set up the tty->alt_speed kludge
- */
- if ((info->flags & ROCKET_SPD_MASK) == ROCKET_SPD_HI)
- tty->alt_speed = 57600;
- if ((info->flags & ROCKET_SPD_MASK) == ROCKET_SPD_VHI)
- tty->alt_speed = 115200;
- if ((info->flags & ROCKET_SPD_MASK) == ROCKET_SPD_SHI)
- tty->alt_speed = 230400;
- if ((info->flags & ROCKET_SPD_MASK) == ROCKET_SPD_WARP)
- tty->alt_speed = 460800;
-
configure_r_port(tty, info, NULL);
if (C_BAUD(tty)) {
sSetDTR(cp);
@@ -1219,23 +1207,20 @@ static int set_config(struct tty_struct *tty, struct r_port *info,
return -EPERM;
}
info->flags = ((info->flags & ~ROCKET_USR_MASK) | (new_serial.flags & ROCKET_USR_MASK));
- configure_r_port(tty, info, NULL);
mutex_unlock(&info->port.mutex);
return 0;
}
+ if ((new_serial.flags ^ info->flags) & ROCKET_SPD_MASK) {
+ /* warn about deprecation, unless clearing */
+ if (new_serial.flags & ROCKET_SPD_MASK)
+ dev_warn_ratelimited(tty->dev, "use of SPD flags is deprecated\n");
+ }
+
info->flags = ((info->flags & ~ROCKET_FLAGS) | (new_serial.flags & ROCKET_FLAGS));
info->port.close_delay = new_serial.close_delay;
info->port.closing_wait = new_serial.closing_wait;
- if ((info->flags & ROCKET_SPD_MASK) == ROCKET_SPD_HI)
- tty->alt_speed = 57600;
- if ((info->flags & ROCKET_SPD_MASK) == ROCKET_SPD_VHI)
- tty->alt_speed = 115200;
- if ((info->flags & ROCKET_SPD_MASK) == ROCKET_SPD_SHI)
- tty->alt_speed = 230400;
- if ((info->flags & ROCKET_SPD_MASK) == ROCKET_SPD_WARP)
- tty->alt_speed = 460800;
mutex_unlock(&info->port.mutex);
configure_r_port(tty, info, NULL);
diff --git a/drivers/tty/serdev/core.c b/drivers/tty/serdev/core.c
index e454162d8c6e..ae1aaa0075d1 100644
--- a/drivers/tty/serdev/core.c
+++ b/drivers/tty/serdev/core.c
@@ -122,6 +122,18 @@ void serdev_device_write_wakeup(struct serdev_device *serdev)
}
EXPORT_SYMBOL_GPL(serdev_device_write_wakeup);
+int serdev_device_write_buf(struct serdev_device *serdev,
+ const unsigned char *buf, size_t count)
+{
+ struct serdev_controller *ctrl = serdev->ctrl;
+
+ if (!ctrl || !ctrl->ops->write_buf)
+ return -EINVAL;
+
+ return ctrl->ops->write_buf(ctrl, buf, count);
+}
+EXPORT_SYMBOL_GPL(serdev_device_write_buf);
+
int serdev_device_write(struct serdev_device *serdev,
const unsigned char *buf, size_t count,
unsigned long timeout)
diff --git a/drivers/tty/serdev/serdev-ttyport.c b/drivers/tty/serdev/serdev-ttyport.c
index 487c88f6aa0e..302018d67efa 100644
--- a/drivers/tty/serdev/serdev-ttyport.c
+++ b/drivers/tty/serdev/serdev-ttyport.c
@@ -102,9 +102,6 @@ static int ttyport_open(struct serdev_controller *ctrl)
return PTR_ERR(tty);
serport->tty = tty;
- serport->port->client_ops = &client_ops;
- serport->port->client_data = ctrl;
-
if (tty->ops->open)
tty->ops->open(serport->tty, NULL);
else
@@ -151,7 +148,7 @@ static unsigned int ttyport_set_baudrate(struct serdev_controller *ctrl, unsigne
/* tty_set_termios() return not checked as it is always 0 */
tty_set_termios(tty, &ktermios);
- return speed;
+ return ktermios.c_ospeed;
}
static void ttyport_set_flow_control(struct serdev_controller *ctrl, bool enable)
@@ -215,6 +212,7 @@ struct device *serdev_tty_port_register(struct tty_port *port,
struct device *parent,
struct tty_driver *drv, int idx)
{
+ const struct tty_port_client_operations *old_ops;
struct serdev_controller *ctrl;
struct serport *serport;
int ret;
@@ -233,28 +231,37 @@ struct device *serdev_tty_port_register(struct tty_port *port,
ctrl->ops = &ctrl_ops;
+ old_ops = port->client_ops;
+ port->client_ops = &client_ops;
+ port->client_data = ctrl;
+
ret = serdev_controller_add(ctrl);
if (ret)
- goto err_controller_put;
+ goto err_reset_data;
dev_info(&ctrl->dev, "tty port %s%d registered\n", drv->name, idx);
return &ctrl->dev;
-err_controller_put:
+err_reset_data:
+ port->client_data = NULL;
+ port->client_ops = old_ops;
serdev_controller_put(ctrl);
+
return ERR_PTR(ret);
}
-void serdev_tty_port_unregister(struct tty_port *port)
+int serdev_tty_port_unregister(struct tty_port *port)
{
struct serdev_controller *ctrl = port->client_data;
struct serport *serport = serdev_controller_get_drvdata(ctrl);
if (!serport)
- return;
+ return -ENODEV;
serdev_controller_remove(ctrl);
port->client_ops = NULL;
port->client_data = NULL;
serdev_controller_put(ctrl);
+
+ return 0;
}
diff --git a/drivers/tty/serial/8250/8250.h b/drivers/tty/serial/8250/8250.h
index ce8d4ffcc425..b2bdc35f7495 100644
--- a/drivers/tty/serial/8250/8250.h
+++ b/drivers/tty/serial/8250/8250.h
@@ -81,6 +81,9 @@ struct serial8250_config {
#define UART_CAP_HFIFO (1 << 14) /* UART has a "hidden" FIFO */
#define UART_CAP_RPM (1 << 15) /* Runtime PM is active while idle */
#define UART_CAP_IRDA (1 << 16) /* UART supports IrDA line discipline */
+#define UART_CAP_MINI (1 << 17) /* Mini UART on BCM283X family lacks:
+ * STOP PARITY EPAR SPAR WLEN5 WLEN6
+ */
#define UART_BUG_QUOT (1 << 0) /* UART has buggy quot LSB */
#define UART_BUG_TXEN (1 << 1) /* UART has buggy TX IIR status */
diff --git a/drivers/tty/serial/8250/8250_aspeed_vuart.c b/drivers/tty/serial/8250/8250_aspeed_vuart.c
new file mode 100644
index 000000000000..822be4906763
--- /dev/null
+++ b/drivers/tty/serial/8250/8250_aspeed_vuart.c
@@ -0,0 +1,323 @@
+/*
+ * Serial Port driver for Aspeed VUART device
+ *
+ * Copyright (C) 2016 Jeremy Kerr <jk@ozlabs.org>, IBM Corp.
+ * Copyright (C) 2006 Arnd Bergmann <arnd@arndb.de>, IBM Corp.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+#include <linux/device.h>
+#include <linux/module.h>
+#include <linux/of_address.h>
+#include <linux/of_irq.h>
+#include <linux/of_platform.h>
+#include <linux/clk.h>
+
+#include "8250.h"
+
+#define ASPEED_VUART_GCRA 0x20
+#define ASPEED_VUART_GCRA_VUART_EN BIT(0)
+#define ASPEED_VUART_GCRA_DISABLE_HOST_TX_DISCARD BIT(5)
+#define ASPEED_VUART_GCRB 0x24
+#define ASPEED_VUART_GCRB_HOST_SIRQ_MASK GENMASK(7, 4)
+#define ASPEED_VUART_GCRB_HOST_SIRQ_SHIFT 4
+#define ASPEED_VUART_ADDRL 0x28
+#define ASPEED_VUART_ADDRH 0x2c
+
+struct aspeed_vuart {
+ struct device *dev;
+ void __iomem *regs;
+ struct clk *clk;
+ int line;
+};
+
+/*
+ * The VUART is basically two UART 'front ends' connected by their FIFO
+ * (no actual serial line in between). One is on the BMC side (management
+ * controller) and one is on the host CPU side.
+ *
+ * It allows the BMC to provide to the host a "UART" that pipes into
+ * the BMC itself and can then be turned by the BMC into a network console
+ * of some sort for example.
+ *
+ * This driver is for the BMC side. The sysfs files allow the BMC
+ * userspace which owns the system configuration policy, to specify
+ * at what IO port and interrupt number the host side will appear
+ * to the host on the Host <-> BMC LPC bus. It could be different on a
+ * different system (though most of them use 3f8/4).
+ */
+
+static ssize_t lpc_address_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct aspeed_vuart *vuart = dev_get_drvdata(dev);
+ u16 addr;
+
+ addr = (readb(vuart->regs + ASPEED_VUART_ADDRH) << 8) |
+ (readb(vuart->regs + ASPEED_VUART_ADDRL));
+
+ return snprintf(buf, PAGE_SIZE - 1, "0x%x\n", addr);
+}
+
+static ssize_t lpc_address_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct aspeed_vuart *vuart = dev_get_drvdata(dev);
+ unsigned long val;
+ int err;
+
+ err = kstrtoul(buf, 0, &val);
+ if (err)
+ return err;
+
+ writeb(val >> 8, vuart->regs + ASPEED_VUART_ADDRH);
+ writeb(val >> 0, vuart->regs + ASPEED_VUART_ADDRL);
+
+ return count;
+}
+
+static DEVICE_ATTR_RW(lpc_address);
+
+static ssize_t sirq_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct aspeed_vuart *vuart = dev_get_drvdata(dev);
+ u8 reg;
+
+ reg = readb(vuart->regs + ASPEED_VUART_GCRB);
+ reg &= ASPEED_VUART_GCRB_HOST_SIRQ_MASK;
+ reg >>= ASPEED_VUART_GCRB_HOST_SIRQ_SHIFT;
+
+ return snprintf(buf, PAGE_SIZE - 1, "%u\n", reg);
+}
+
+static ssize_t sirq_store(struct device *dev, struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct aspeed_vuart *vuart = dev_get_drvdata(dev);
+ unsigned long val;
+ int err;
+ u8 reg;
+
+ err = kstrtoul(buf, 0, &val);
+ if (err)
+ return err;
+
+ val <<= ASPEED_VUART_GCRB_HOST_SIRQ_SHIFT;
+ val &= ASPEED_VUART_GCRB_HOST_SIRQ_MASK;
+
+ reg = readb(vuart->regs + ASPEED_VUART_GCRB);
+ reg &= ~ASPEED_VUART_GCRB_HOST_SIRQ_MASK;
+ reg |= val;
+ writeb(reg, vuart->regs + ASPEED_VUART_GCRB);
+
+ return count;
+}
+
+static DEVICE_ATTR_RW(sirq);
+
+static struct attribute *aspeed_vuart_attrs[] = {
+ &dev_attr_sirq.attr,
+ &dev_attr_lpc_address.attr,
+ NULL,
+};
+
+static const struct attribute_group aspeed_vuart_attr_group = {
+ .attrs = aspeed_vuart_attrs,
+};
+
+static void aspeed_vuart_set_enabled(struct aspeed_vuart *vuart, bool enabled)
+{
+ u8 reg = readb(vuart->regs + ASPEED_VUART_GCRA);
+
+ if (enabled)
+ reg |= ASPEED_VUART_GCRA_VUART_EN;
+ else
+ reg &= ~ASPEED_VUART_GCRA_VUART_EN;
+
+ writeb(reg, vuart->regs + ASPEED_VUART_GCRA);
+}
+
+static void aspeed_vuart_set_host_tx_discard(struct aspeed_vuart *vuart,
+ bool discard)
+{
+ u8 reg;
+
+ reg = readb(vuart->regs + ASPEED_VUART_GCRA);
+
+ /* If the DISABLE_HOST_TX_DISCARD bit is set, discard is disabled */
+ if (!discard)
+ reg |= ASPEED_VUART_GCRA_DISABLE_HOST_TX_DISCARD;
+ else
+ reg &= ~ASPEED_VUART_GCRA_DISABLE_HOST_TX_DISCARD;
+
+ writeb(reg, vuart->regs + ASPEED_VUART_GCRA);
+}
+
+static int aspeed_vuart_startup(struct uart_port *uart_port)
+{
+ struct uart_8250_port *uart_8250_port = up_to_u8250p(uart_port);
+ struct aspeed_vuart *vuart = uart_8250_port->port.private_data;
+ int rc;
+
+ rc = serial8250_do_startup(uart_port);
+ if (rc)
+ return rc;
+
+ aspeed_vuart_set_host_tx_discard(vuart, false);
+
+ return 0;
+}
+
+static void aspeed_vuart_shutdown(struct uart_port *uart_port)
+{
+ struct uart_8250_port *uart_8250_port = up_to_u8250p(uart_port);
+ struct aspeed_vuart *vuart = uart_8250_port->port.private_data;
+
+ aspeed_vuart_set_host_tx_discard(vuart, true);
+
+ serial8250_do_shutdown(uart_port);
+}
+
+static int aspeed_vuart_probe(struct platform_device *pdev)
+{
+ struct uart_8250_port port;
+ struct aspeed_vuart *vuart;
+ struct device_node *np;
+ struct resource *res;
+ u32 clk, prop;
+ int rc;
+
+ np = pdev->dev.of_node;
+
+ vuart = devm_kzalloc(&pdev->dev, sizeof(*vuart), GFP_KERNEL);
+ if (!vuart)
+ return -ENOMEM;
+
+ vuart->dev = &pdev->dev;
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ vuart->regs = devm_ioremap_resource(&pdev->dev, res);
+ if (IS_ERR(vuart->regs))
+ return PTR_ERR(vuart->regs);
+
+ memset(&port, 0, sizeof(port));
+ port.port.private_data = vuart;
+ port.port.membase = vuart->regs;
+ port.port.mapbase = res->start;
+ port.port.mapsize = resource_size(res);
+ port.port.startup = aspeed_vuart_startup;
+ port.port.shutdown = aspeed_vuart_shutdown;
+ port.port.dev = &pdev->dev;
+
+ rc = sysfs_create_group(&vuart->dev->kobj, &aspeed_vuart_attr_group);
+ if (rc < 0)
+ return rc;
+
+ if (of_property_read_u32(np, "clock-frequency", &clk)) {
+ vuart->clk = devm_clk_get(&pdev->dev, NULL);
+ if (IS_ERR(vuart->clk)) {
+ dev_warn(&pdev->dev,
+ "clk or clock-frequency not defined\n");
+ return PTR_ERR(vuart->clk);
+ }
+
+ rc = clk_prepare_enable(vuart->clk);
+ if (rc < 0)
+ return rc;
+
+ clk = clk_get_rate(vuart->clk);
+ }
+
+ /* If current-speed was set, then try not to change it. */
+ if (of_property_read_u32(np, "current-speed", &prop) == 0)
+ port.port.custom_divisor = clk / (16 * prop);
+
+ /* Check for shifted address mapping */
+ if (of_property_read_u32(np, "reg-offset", &prop) == 0)
+ port.port.mapbase += prop;
+
+ /* Check for registers offset within the devices address range */
+ if (of_property_read_u32(np, "reg-shift", &prop) == 0)
+ port.port.regshift = prop;
+
+ /* Check for fifo size */
+ if (of_property_read_u32(np, "fifo-size", &prop) == 0)
+ port.port.fifosize = prop;
+
+ /* Check for a fixed line number */
+ rc = of_alias_get_id(np, "serial");
+ if (rc >= 0)
+ port.port.line = rc;
+
+ port.port.irq = irq_of_parse_and_map(np, 0);
+ port.port.irqflags = IRQF_SHARED;
+ port.port.iotype = UPIO_MEM;
+ port.port.type = PORT_16550A;
+ port.port.uartclk = clk;
+ port.port.flags = UPF_SHARE_IRQ | UPF_BOOT_AUTOCONF
+ | UPF_FIXED_PORT | UPF_FIXED_TYPE | UPF_NO_THRE_TEST;
+
+ if (of_property_read_bool(np, "no-loopback-test"))
+ port.port.flags |= UPF_SKIP_TEST;
+
+ if (port.port.fifosize)
+ port.capabilities = UART_CAP_FIFO;
+
+ if (of_property_read_bool(np, "auto-flow-control"))
+ port.capabilities |= UART_CAP_AFE;
+
+ rc = serial8250_register_8250_port(&port);
+ if (rc < 0)
+ goto err_clk_disable;
+
+ vuart->line = rc;
+
+ aspeed_vuart_set_enabled(vuart, true);
+ aspeed_vuart_set_host_tx_discard(vuart, true);
+ platform_set_drvdata(pdev, vuart);
+
+ return 0;
+
+err_clk_disable:
+ clk_disable_unprepare(vuart->clk);
+ irq_dispose_mapping(port.port.irq);
+ return rc;
+}
+
+static int aspeed_vuart_remove(struct platform_device *pdev)
+{
+ struct aspeed_vuart *vuart = platform_get_drvdata(pdev);
+
+ aspeed_vuart_set_enabled(vuart, false);
+ serial8250_unregister_port(vuart->line);
+ sysfs_remove_group(&vuart->dev->kobj, &aspeed_vuart_attr_group);
+ clk_disable_unprepare(vuart->clk);
+
+ return 0;
+}
+
+static const struct of_device_id aspeed_vuart_table[] = {
+ { .compatible = "aspeed,ast2400-vuart" },
+ { .compatible = "aspeed,ast2500-vuart" },
+ { },
+};
+
+static struct platform_driver aspeed_vuart_driver = {
+ .driver = {
+ .name = "aspeed-vuart",
+ .of_match_table = aspeed_vuart_table,
+ },
+ .probe = aspeed_vuart_probe,
+ .remove = aspeed_vuart_remove,
+};
+
+module_platform_driver(aspeed_vuart_driver);
+
+MODULE_AUTHOR("Jeremy Kerr <jk@ozlabs.org>");
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("Driver for Aspeed VUART device");
diff --git a/drivers/tty/serial/8250/8250_bcm2835aux.c b/drivers/tty/serial/8250/8250_bcm2835aux.c
index e10f1244409b..a23c7da42ea8 100644
--- a/drivers/tty/serial/8250/8250_bcm2835aux.c
+++ b/drivers/tty/serial/8250/8250_bcm2835aux.c
@@ -39,7 +39,7 @@ static int bcm2835aux_serial_probe(struct platform_device *pdev)
/* initialize data */
spin_lock_init(&data->uart.port.lock);
- data->uart.capabilities = UART_CAP_FIFO;
+ data->uart.capabilities = UART_CAP_FIFO | UART_CAP_MINI;
data->uart.port.dev = &pdev->dev;
data->uart.port.regshift = 2;
data->uart.port.type = PORT_16550;
diff --git a/drivers/tty/serial/8250/8250_core.c b/drivers/tty/serial/8250/8250_core.c
index 1aab3010fbfa..b5def356af63 100644
--- a/drivers/tty/serial/8250/8250_core.c
+++ b/drivers/tty/serial/8250/8250_core.c
@@ -1043,24 +1043,13 @@ int serial8250_register_8250_port(struct uart_8250_port *up)
if (up->dl_write)
uart->dl_write = up->dl_write;
- if (uart->port.type != PORT_8250_CIR) {
- if (serial8250_isa_config != NULL)
- serial8250_isa_config(0, &uart->port,
- &uart->capabilities);
-
- ret = uart_add_one_port(&serial8250_reg,
- &uart->port);
- if (ret == 0)
- ret = uart->port.line;
- } else {
- dev_info(uart->port.dev,
- "skipping CIR port at 0x%lx / 0x%llx, IRQ %d\n",
- uart->port.iobase,
- (unsigned long long)uart->port.mapbase,
- uart->port.irq);
+ if (serial8250_isa_config != NULL)
+ serial8250_isa_config(0, &uart->port,
+ &uart->capabilities);
- ret = 0;
- }
+ ret = uart_add_one_port(&serial8250_reg, &uart->port);
+ if (ret == 0)
+ ret = uart->port.line;
}
mutex_unlock(&serial_mutex);
diff --git a/drivers/tty/serial/8250/8250_exar.c b/drivers/tty/serial/8250/8250_exar.c
index 1270ff163f63..a309bcffffcd 100644
--- a/drivers/tty/serial/8250/8250_exar.c
+++ b/drivers/tty/serial/8250/8250_exar.c
@@ -109,7 +109,6 @@ pci_fastcom335_setup(struct exar8250 *priv, struct pci_dev *pcidev,
u8 __iomem *p;
int err;
- port->port.flags |= UPF_EXAR_EFR;
port->port.uartclk = baud * 16;
err = default_setup(priv, pcidev, idx, offset, port);
@@ -171,19 +170,26 @@ pci_xr17c154_setup(struct exar8250 *priv, struct pci_dev *pcidev,
return default_setup(priv, pcidev, idx, offset, port);
}
-static void setup_gpio(u8 __iomem *p)
+static void setup_gpio(struct pci_dev *pcidev, u8 __iomem *p)
{
+ /*
+ * The Commtech adapters required the MPIOs to be driven low. The Exar
+ * devices will export them as GPIOs, so we pre-configure them safely
+ * as inputs.
+ */
+ u8 dir = pcidev->vendor == PCI_VENDOR_ID_EXAR ? 0xff : 0x00;
+
writeb(0x00, p + UART_EXAR_MPIOINT_7_0);
writeb(0x00, p + UART_EXAR_MPIOLVL_7_0);
writeb(0x00, p + UART_EXAR_MPIO3T_7_0);
writeb(0x00, p + UART_EXAR_MPIOINV_7_0);
- writeb(0x00, p + UART_EXAR_MPIOSEL_7_0);
+ writeb(dir, p + UART_EXAR_MPIOSEL_7_0);
writeb(0x00, p + UART_EXAR_MPIOOD_7_0);
writeb(0x00, p + UART_EXAR_MPIOINT_15_8);
writeb(0x00, p + UART_EXAR_MPIOLVL_15_8);
writeb(0x00, p + UART_EXAR_MPIO3T_15_8);
writeb(0x00, p + UART_EXAR_MPIOINV_15_8);
- writeb(0x00, p + UART_EXAR_MPIOSEL_15_8);
+ writeb(dir, p + UART_EXAR_MPIOSEL_15_8);
writeb(0x00, p + UART_EXAR_MPIOOD_15_8);
}
@@ -236,7 +242,7 @@ pci_xr17v35x_setup(struct exar8250 *priv, struct pci_dev *pcidev,
if (idx == 0) {
/* Setup Multipurpose Input/Output pins. */
- setup_gpio(p);
+ setup_gpio(pcidev, p);
port->port.private_data = xr17v35x_register_gpio(pcidev);
}
diff --git a/drivers/tty/serial/8250/8250_of.c b/drivers/tty/serial/8250/8250_of.c
index 1cbadafc6889..0cf95fddccfc 100644
--- a/drivers/tty/serial/8250/8250_of.c
+++ b/drivers/tty/serial/8250/8250_of.c
@@ -19,11 +19,13 @@
#include <linux/of_irq.h>
#include <linux/of_platform.h>
#include <linux/clk.h>
+#include <linux/reset.h>
#include "8250.h"
struct of_serial_info {
struct clk *clk;
+ struct reset_control *rst;
int type;
int line;
};
@@ -132,6 +134,13 @@ static int of_platform_serial_setup(struct platform_device *ofdev,
}
}
+ info->rst = devm_reset_control_get_optional_shared(&ofdev->dev, NULL);
+ if (IS_ERR(info->rst))
+ goto out;
+ ret = reset_control_deassert(info->rst);
+ if (ret)
+ goto out;
+
port->type = type;
port->uartclk = clk;
port->flags = UPF_SHARE_IRQ | UPF_BOOT_AUTOCONF | UPF_IOREMAP
@@ -229,6 +238,7 @@ static int of_platform_serial_remove(struct platform_device *ofdev)
serial8250_unregister_port(info->line);
+ reset_control_assert(info->rst);
if (info->clk)
clk_disable_unprepare(info->clk);
kfree(info);
diff --git a/drivers/tty/serial/8250/8250_omap.c b/drivers/tty/serial/8250/8250_omap.c
index e7e64913a748..833771bca0a5 100644
--- a/drivers/tty/serial/8250/8250_omap.c
+++ b/drivers/tty/serial/8250/8250_omap.c
@@ -613,6 +613,10 @@ static int omap_8250_startup(struct uart_port *port)
up->lsr_saved_flags = 0;
up->msr_saved_flags = 0;
+ /* Disable DMA for console UART */
+ if (uart_console(port))
+ up->dma = NULL;
+
if (up->dma) {
ret = serial8250_request_dma(up);
if (ret) {
@@ -782,8 +786,27 @@ unlock:
static void __dma_rx_complete(void *param)
{
- __dma_rx_do_complete(param);
- omap_8250_rx_dma(param);
+ struct uart_8250_port *p = param;
+ struct uart_8250_dma *dma = p->dma;
+ struct dma_tx_state state;
+ unsigned long flags;
+
+ spin_lock_irqsave(&p->port.lock, flags);
+
+ /*
+ * If the tx status is not DMA_COMPLETE, then this is a delayed
+ * completion callback. A previous RX timeout flush would have
+ * already pushed the data, so exit.
+ */
+ if (dmaengine_tx_status(dma->rxchan, dma->rx_cookie, &state) !=
+ DMA_COMPLETE) {
+ spin_unlock_irqrestore(&p->port.lock, flags);
+ return;
+ }
+ __dma_rx_do_complete(p);
+ omap_8250_rx_dma(p);
+
+ spin_unlock_irqrestore(&p->port.lock, flags);
}
static void omap_8250_rx_dma_flush(struct uart_8250_port *p)
diff --git a/drivers/tty/serial/8250/8250_port.c b/drivers/tty/serial/8250/8250_port.c
index 09a65a3ec7f7..a5fe0e66c607 100644
--- a/drivers/tty/serial/8250/8250_port.c
+++ b/drivers/tty/serial/8250/8250_port.c
@@ -47,6 +47,7 @@
/*
* These are definitions for the Exar XR17V35X and XR17(C|D)15X
*/
+#define UART_EXAR_INT0 0x80
#define UART_EXAR_SLEEP 0x8b /* Sleep mode */
#define UART_EXAR_DVID 0x8d /* Device identification */
@@ -1337,7 +1338,7 @@ out_lock:
/*
* Check if the device is a Fintek F81216A
*/
- if (port->type == PORT_16550A)
+ if (port->type == PORT_16550A && port->iotype == UPIO_PORT)
fintek_8250_probe(up);
if (up->capabilities != old_capabilities) {
@@ -1763,6 +1764,10 @@ void serial8250_tx_chars(struct uart_8250_port *up)
if ((up->capabilities & UART_CAP_HFIFO) &&
(serial_in(up, UART_LSR) & BOTH_EMPTY) != BOTH_EMPTY)
break;
+ /* The BCM2835 MINI UART THRE bit is really a not-full bit. */
+ if ((up->capabilities & UART_CAP_MINI) &&
+ !(serial_in(up, UART_LSR) & UART_LSR_THRE))
+ break;
} while (--count > 0);
if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
@@ -1869,17 +1874,13 @@ static int serial8250_default_handle_irq(struct uart_port *port)
static int exar_handle_irq(struct uart_port *port)
{
unsigned int iir = serial_port_in(port, UART_IIR);
- int ret;
+ int ret = 0;
- ret = serial8250_handle_irq(port, iir);
+ if (((port->type == PORT_XR17V35X) || (port->type == PORT_XR17D15X)) &&
+ serial_port_in(port, UART_EXAR_INT0) != 0)
+ ret = 1;
- if ((port->type == PORT_XR17V35X) ||
- (port->type == PORT_XR17D15X)) {
- serial_port_in(port, 0x80);
- serial_port_in(port, 0x81);
- serial_port_in(port, 0x82);
- serial_port_in(port, 0x83);
- }
+ ret |= serial8250_handle_irq(port, iir);
return ret;
}
@@ -2177,6 +2178,8 @@ int serial8250_do_startup(struct uart_port *port)
serial_port_in(port, UART_RX);
serial_port_in(port, UART_IIR);
serial_port_in(port, UART_MSR);
+ if ((port->type == PORT_XR17V35X) || (port->type == PORT_XR17D15X))
+ serial_port_in(port, UART_EXAR_INT0);
/*
* At this point, there's no way the LSR could still be 0xff;
@@ -2229,7 +2232,7 @@ int serial8250_do_startup(struct uart_port *port)
}
}
- if (port->irq) {
+ if (port->irq && !(up->port.flags & UPF_NO_THRE_TEST)) {
unsigned char iir1;
/*
* Test for UARTs that do not reassert THRE when the
@@ -2335,6 +2338,8 @@ dont_test_tx_en:
serial_port_in(port, UART_RX);
serial_port_in(port, UART_IIR);
serial_port_in(port, UART_MSR);
+ if ((port->type == PORT_XR17V35X) || (port->type == PORT_XR17D15X))
+ serial_port_in(port, UART_EXAR_INT0);
up->lsr_saved_flags = 0;
up->msr_saved_flags = 0;
@@ -2584,6 +2589,12 @@ serial8250_do_set_termios(struct uart_port *port, struct ktermios *termios,
unsigned long flags;
unsigned int baud, quot, frac = 0;
+ if (up->capabilities & UART_CAP_MINI) {
+ termios->c_cflag &= ~(CSTOPB | PARENB | PARODD | CMSPAR);
+ if ((termios->c_cflag & CSIZE) == CS5 ||
+ (termios->c_cflag & CSIZE) == CS6)
+ termios->c_cflag = (termios->c_cflag & ~CSIZE) | CS7;
+ }
cval = serial8250_compute_lcr(up, termios->c_cflag);
baud = serial8250_get_baud_rate(port, termios, old);
diff --git a/drivers/tty/serial/8250/Kconfig b/drivers/tty/serial/8250/Kconfig
index 0e3f529d50e9..a1161ec0256f 100644
--- a/drivers/tty/serial/8250/Kconfig
+++ b/drivers/tty/serial/8250/Kconfig
@@ -224,6 +224,16 @@ config SERIAL_8250_ACCENT
To compile this driver as a module, choose M here: the module
will be called 8250_accent.
+config SERIAL_8250_ASPEED_VUART
+ tristate "Aspeed Virtual UART"
+ depends on SERIAL_8250
+ depends on OF
+ help
+ If you want to use the virtual UART (VUART) device on Aspeed
+ BMC platforms, enable this option. This enables the 16550A-
+ compatible device on the local LPC bus, giving a UART device
+ with no physical RS232 connections.
+
config SERIAL_8250_BOCA
tristate "Support Boca cards"
depends on SERIAL_8250 != n && ISA && SERIAL_8250_MANY_PORTS
diff --git a/drivers/tty/serial/8250/Makefile b/drivers/tty/serial/8250/Makefile
index 2f30f9ecdb1b..a44a99a3e623 100644
--- a/drivers/tty/serial/8250/Makefile
+++ b/drivers/tty/serial/8250/Makefile
@@ -14,6 +14,7 @@ obj-$(CONFIG_SERIAL_8250_EXAR) += 8250_exar.o
obj-$(CONFIG_SERIAL_8250_HP300) += 8250_hp300.o
obj-$(CONFIG_SERIAL_8250_CS) += serial_cs.o
obj-$(CONFIG_SERIAL_8250_ACORN) += 8250_acorn.o
+obj-$(CONFIG_SERIAL_8250_ASPEED_VUART) += 8250_aspeed_vuart.o
obj-$(CONFIG_SERIAL_8250_BCM2835AUX) += 8250_bcm2835aux.o
obj-$(CONFIG_SERIAL_8250_CONSOLE) += 8250_early.o
obj-$(CONFIG_SERIAL_8250_FOURPORT) += 8250_fourport.o
diff --git a/drivers/tty/serial/Kconfig b/drivers/tty/serial/Kconfig
index 5c8850f7a2a0..1f096e2bb398 100644
--- a/drivers/tty/serial/Kconfig
+++ b/drivers/tty/serial/Kconfig
@@ -114,32 +114,32 @@ config SERIAL_SB1250_DUART_CONSOLE
If unsure, say Y.
config SERIAL_ATMEL
- bool "AT91 / AT32 on-chip serial port support"
+ bool "AT91 on-chip serial port support"
depends on HAS_DMA
- depends on ARCH_AT91 || AVR32 || COMPILE_TEST
+ depends on ARCH_AT91 || COMPILE_TEST
select SERIAL_CORE
select SERIAL_MCTRL_GPIO if GPIOLIB
help
This enables the driver for the on-chip UARTs of the Atmel
- AT91 and AT32 processors.
+ AT91 processors.
config SERIAL_ATMEL_CONSOLE
- bool "Support for console on AT91 / AT32 serial port"
+ bool "Support for console on AT91 serial port"
depends on SERIAL_ATMEL=y
select SERIAL_CORE_CONSOLE
help
Say Y here if you wish to use an on-chip UART on a Atmel
- AT91 or AT32 processor as the system console (the system
+ AT91 processor as the system console (the system
console is the device which receives all kernel messages and
warnings and which allows logins in single user mode).
config SERIAL_ATMEL_PDC
- bool "Support DMA transfers on AT91 / AT32 serial port"
+ bool "Support DMA transfers on AT91 serial port"
depends on SERIAL_ATMEL
default y
help
Say Y here if you wish to use the PDC to do DMA transfers to
- and from the Atmel AT91 / AT32 serial port. In order to
+ and from the Atmel AT91 serial port. In order to
actually use DMA transfers, make sure that the use_dma_tx
and use_dma_rx members in the atmel_uart_data struct is set
appropriately for each port.
@@ -152,7 +152,7 @@ config SERIAL_ATMEL_TTYAT
bool "Install as device ttyATn instead of ttySn"
depends on SERIAL_ATMEL=y
help
- Say Y here if you wish to have the internal AT91 / AT32 UARTs
+ Say Y here if you wish to have the internal AT91 UARTs
appear as /dev/ttyATn (major 204, minor starting at 154)
instead of the normal /dev/ttySn (major 4, minor starting at
64). This is necessary if you also want other UARTs, such as
@@ -1688,6 +1688,25 @@ config SERIAL_MVEBU_CONSOLE
and warnings and which allows logins in single user mode)
Otherwise, say 'N'.
+config SERIAL_OWL
+ bool "Actions Semi Owl serial port support"
+ depends on ARCH_ACTIONS || COMPILE_TEST
+ select SERIAL_CORE
+ help
+ This driver is for Actions Semiconductor S500/S900 SoC's UART.
+ Say 'Y' here if you wish to use the on-board serial port.
+ Otherwise, say 'N'.
+
+config SERIAL_OWL_CONSOLE
+ bool "Console on Actions Semi Owl serial port"
+ depends on SERIAL_OWL=y
+ select SERIAL_CORE_CONSOLE
+ select SERIAL_EARLYCON
+ default y
+ help
+ Say 'Y' here if you wish to use Actions Semiconductor S500/S900 UART
+ as the system console. Only earlycon is implemented currently.
+
endmenu
config SERIAL_MCTRL_GPIO
diff --git a/drivers/tty/serial/Makefile b/drivers/tty/serial/Makefile
index 53c03e005132..fe88a75d9a59 100644
--- a/drivers/tty/serial/Makefile
+++ b/drivers/tty/serial/Makefile
@@ -92,6 +92,7 @@ obj-$(CONFIG_SERIAL_STM32) += stm32-usart.o
obj-$(CONFIG_SERIAL_MVEBU_UART) += mvebu-uart.o
obj-$(CONFIG_SERIAL_PIC32) += pic32_uart.o
obj-$(CONFIG_SERIAL_MPS2_UART) += mps2-uart.o
+obj-$(CONFIG_SERIAL_OWL) += owl-uart.o
# GPIOLIB helpers for modem control lines
obj-$(CONFIG_SERIAL_MCTRL_GPIO) += serial_mctrl_gpio.o
diff --git a/drivers/tty/serial/altera_jtaguart.c b/drivers/tty/serial/altera_jtaguart.c
index 18e3f8342b85..0475f5d261ce 100644
--- a/drivers/tty/serial/altera_jtaguart.c
+++ b/drivers/tty/serial/altera_jtaguart.c
@@ -478,6 +478,7 @@ static int altera_jtaguart_remove(struct platform_device *pdev)
port = &altera_jtaguart_ports[i].port;
uart_remove_one_port(&altera_jtaguart_driver, port);
+ iounmap(port->membase);
return 0;
}
diff --git a/drivers/tty/serial/altera_uart.c b/drivers/tty/serial/altera_uart.c
index 46d3438a0d27..3e4b717670d7 100644
--- a/drivers/tty/serial/altera_uart.c
+++ b/drivers/tty/serial/altera_uart.c
@@ -615,6 +615,7 @@ static int altera_uart_remove(struct platform_device *pdev)
if (port) {
uart_remove_one_port(&altera_uart_driver, port);
port->mapbase = 0;
+ iounmap(port->membase);
}
return 0;
diff --git a/drivers/tty/serial/amba-pl010.c b/drivers/tty/serial/amba-pl010.c
index f2f251075109..24180adb1cbb 100644
--- a/drivers/tty/serial/amba-pl010.c
+++ b/drivers/tty/serial/amba-pl010.c
@@ -697,6 +697,7 @@ static struct console amba_console = {
#define AMBA_CONSOLE NULL
#endif
+static DEFINE_MUTEX(amba_reg_lock);
static struct uart_driver amba_reg = {
.owner = THIS_MODULE,
.driver_name = "ttyAM",
@@ -749,6 +750,19 @@ static int pl010_probe(struct amba_device *dev, const struct amba_id *id)
amba_ports[i] = uap;
amba_set_drvdata(dev, uap);
+
+ mutex_lock(&amba_reg_lock);
+ if (!amba_reg.state) {
+ ret = uart_register_driver(&amba_reg);
+ if (ret < 0) {
+ mutex_unlock(&amba_reg_lock);
+ dev_err(uap->port.dev,
+ "Failed to register AMBA-PL010 driver\n");
+ return ret;
+ }
+ }
+ mutex_unlock(&amba_reg_lock);
+
ret = uart_add_one_port(&amba_reg, &uap->port);
if (ret)
amba_ports[i] = NULL;
@@ -760,12 +774,18 @@ static int pl010_remove(struct amba_device *dev)
{
struct uart_amba_port *uap = amba_get_drvdata(dev);
int i;
+ bool busy = false;
uart_remove_one_port(&amba_reg, &uap->port);
for (i = 0; i < ARRAY_SIZE(amba_ports); i++)
if (amba_ports[i] == uap)
amba_ports[i] = NULL;
+ else if (amba_ports[i])
+ busy = true;
+
+ if (!busy)
+ uart_unregister_driver(&amba_reg);
return 0;
}
@@ -816,23 +836,14 @@ static struct amba_driver pl010_driver = {
static int __init pl010_init(void)
{
- int ret;
-
printk(KERN_INFO "Serial: AMBA driver\n");
- ret = uart_register_driver(&amba_reg);
- if (ret == 0) {
- ret = amba_driver_register(&pl010_driver);
- if (ret)
- uart_unregister_driver(&amba_reg);
- }
- return ret;
+ return amba_driver_register(&pl010_driver);
}
static void __exit pl010_exit(void)
{
amba_driver_unregister(&pl010_driver);
- uart_unregister_driver(&amba_reg);
}
module_init(pl010_init);
diff --git a/drivers/tty/serial/atmel_serial.c b/drivers/tty/serial/atmel_serial.c
index c355ac9abafc..7551cab438ff 100644
--- a/drivers/tty/serial/atmel_serial.c
+++ b/drivers/tty/serial/atmel_serial.c
@@ -1,5 +1,5 @@
/*
- * Driver for Atmel AT91 / AT32 Serial ports
+ * Driver for Atmel AT91 Serial ports
* Copyright (C) 2003 Rick Bronson
*
* Based on drivers/char/serial_sa1100.c, by Deep Blue Solutions Ltd.
@@ -46,6 +46,7 @@
#include <linux/err.h>
#include <linux/irq.h>
#include <linux/suspend.h>
+#include <linux/mm.h>
#include <asm/io.h>
#include <asm/ioctls.h>
@@ -118,7 +119,6 @@ struct atmel_uart_char {
/*
* at91: 6 USARTs and one DBGU port (SAM9260)
- * avr32: 4
* samx7: 3 USARTs and 5 UARTs
*/
#define ATMEL_MAX_UART 8
@@ -228,21 +228,6 @@ static inline void atmel_uart_writel(struct uart_port *port, u32 reg, u32 value)
__raw_writel(value, port->membase + reg);
}
-#ifdef CONFIG_AVR32
-
-/* AVR32 cannot handle 8 or 16bit I/O accesses but only 32bit I/O accesses */
-static inline u8 atmel_uart_read_char(struct uart_port *port)
-{
- return __raw_readl(port->membase + ATMEL_US_RHR);
-}
-
-static inline void atmel_uart_write_char(struct uart_port *port, u8 value)
-{
- __raw_writel(value, port->membase + ATMEL_US_THR);
-}
-
-#else
-
static inline u8 atmel_uart_read_char(struct uart_port *port)
{
return __raw_readb(port->membase + ATMEL_US_RHR);
@@ -253,8 +238,6 @@ static inline void atmel_uart_write_char(struct uart_port *port, u8 value)
__raw_writeb(value, port->membase + ATMEL_US_THR);
}
-#endif
-
#ifdef CONFIG_SERIAL_ATMEL_PDC
static bool atmel_use_pdc_rx(struct uart_port *port)
{
@@ -959,7 +942,7 @@ static int atmel_prepare_tx_dma(struct uart_port *port)
sg_set_page(&atmel_port->sg_tx,
virt_to_page(port->state->xmit.buf),
UART_XMIT_SIZE,
- (unsigned long)port->state->xmit.buf & ~PAGE_MASK);
+ offset_in_page(port->state->xmit.buf));
nent = dma_map_sg(port->dev,
&atmel_port->sg_tx,
1,
@@ -1141,7 +1124,7 @@ static int atmel_prepare_rx_dma(struct uart_port *port)
sg_set_page(&atmel_port->sg_rx,
virt_to_page(ring->buf),
sizeof(struct atmel_uart_char) * ATMEL_SERIAL_RINGSIZE,
- (unsigned long)ring->buf & ~PAGE_MASK);
+ offset_in_page(ring->buf));
nent = dma_map_sg(port->dev,
&atmel_port->sg_rx,
1,
@@ -1655,72 +1638,56 @@ static void atmel_init_property(struct atmel_uart_port *atmel_port,
struct platform_device *pdev)
{
struct device_node *np = pdev->dev.of_node;
- struct atmel_uart_data *pdata = dev_get_platdata(&pdev->dev);
-
- if (np) {
- /* DMA/PDC usage specification */
- if (of_property_read_bool(np, "atmel,use-dma-rx")) {
- if (of_property_read_bool(np, "dmas")) {
- atmel_port->use_dma_rx = true;
- atmel_port->use_pdc_rx = false;
- } else {
- atmel_port->use_dma_rx = false;
- atmel_port->use_pdc_rx = true;
- }
+
+ /* DMA/PDC usage specification */
+ if (of_property_read_bool(np, "atmel,use-dma-rx")) {
+ if (of_property_read_bool(np, "dmas")) {
+ atmel_port->use_dma_rx = true;
+ atmel_port->use_pdc_rx = false;
} else {
atmel_port->use_dma_rx = false;
- atmel_port->use_pdc_rx = false;
+ atmel_port->use_pdc_rx = true;
}
+ } else {
+ atmel_port->use_dma_rx = false;
+ atmel_port->use_pdc_rx = false;
+ }
- if (of_property_read_bool(np, "atmel,use-dma-tx")) {
- if (of_property_read_bool(np, "dmas")) {
- atmel_port->use_dma_tx = true;
- atmel_port->use_pdc_tx = false;
- } else {
- atmel_port->use_dma_tx = false;
- atmel_port->use_pdc_tx = true;
- }
+ if (of_property_read_bool(np, "atmel,use-dma-tx")) {
+ if (of_property_read_bool(np, "dmas")) {
+ atmel_port->use_dma_tx = true;
+ atmel_port->use_pdc_tx = false;
} else {
atmel_port->use_dma_tx = false;
- atmel_port->use_pdc_tx = false;
+ atmel_port->use_pdc_tx = true;
}
-
} else {
- atmel_port->use_pdc_rx = pdata->use_dma_rx;
- atmel_port->use_pdc_tx = pdata->use_dma_tx;
- atmel_port->use_dma_rx = false;
atmel_port->use_dma_tx = false;
+ atmel_port->use_pdc_tx = false;
}
-
}
static void atmel_init_rs485(struct uart_port *port,
struct platform_device *pdev)
{
struct device_node *np = pdev->dev.of_node;
- struct atmel_uart_data *pdata = dev_get_platdata(&pdev->dev);
-
- if (np) {
- struct serial_rs485 *rs485conf = &port->rs485;
- u32 rs485_delay[2];
- /* rs485 properties */
- if (of_property_read_u32_array(np, "rs485-rts-delay",
- rs485_delay, 2) == 0) {
- rs485conf->delay_rts_before_send = rs485_delay[0];
- rs485conf->delay_rts_after_send = rs485_delay[1];
- rs485conf->flags = 0;
- }
- if (of_get_property(np, "rs485-rx-during-tx", NULL))
- rs485conf->flags |= SER_RS485_RX_DURING_TX;
+ struct serial_rs485 *rs485conf = &port->rs485;
+ u32 rs485_delay[2];
- if (of_get_property(np, "linux,rs485-enabled-at-boot-time",
- NULL))
- rs485conf->flags |= SER_RS485_ENABLED;
- } else {
- port->rs485 = pdata->rs485;
+ /* rs485 properties */
+ if (of_property_read_u32_array(np, "rs485-rts-delay",
+ rs485_delay, 2) == 0) {
+ rs485conf->delay_rts_before_send = rs485_delay[0];
+ rs485conf->delay_rts_after_send = rs485_delay[1];
+ rs485conf->flags = 0;
}
+ if (of_get_property(np, "rs485-rx-during-tx", NULL))
+ rs485conf->flags |= SER_RS485_RX_DURING_TX;
+
+ if (of_get_property(np, "linux,rs485-enabled-at-boot-time", NULL))
+ rs485conf->flags |= SER_RS485_ENABLED;
}
static void atmel_set_ops(struct uart_port *port)
@@ -2402,7 +2369,6 @@ static int atmel_init_port(struct atmel_uart_port *atmel_port,
{
int ret;
struct uart_port *port = &atmel_port->uart;
- struct atmel_uart_data *pdata = dev_get_platdata(&pdev->dev);
atmel_init_property(atmel_port, pdev);
atmel_set_ops(port);
@@ -2410,24 +2376,17 @@ static int atmel_init_port(struct atmel_uart_port *atmel_port,
atmel_init_rs485(port, pdev);
port->iotype = UPIO_MEM;
- port->flags = UPF_BOOT_AUTOCONF;
+ port->flags = UPF_BOOT_AUTOCONF | UPF_IOREMAP;
port->ops = &atmel_pops;
port->fifosize = 1;
port->dev = &pdev->dev;
port->mapbase = pdev->resource[0].start;
port->irq = pdev->resource[1].start;
port->rs485_config = atmel_config_rs485;
+ port->membase = NULL;
memset(&atmel_port->rx_ring, 0, sizeof(atmel_port->rx_ring));
- if (pdata && pdata->regs) {
- /* Already mapped by setup code */
- port->membase = pdata->regs;
- } else {
- port->flags |= UPF_IOREMAP;
- port->membase = NULL;
- }
-
/* for console, the clock could already be configured */
if (!atmel_port->clk) {
atmel_port->clk = clk_get(&pdev->dev, "usart");
@@ -2460,8 +2419,6 @@ static int atmel_init_port(struct atmel_uart_port *atmel_port,
return 0;
}
-struct platform_device *atmel_default_console_device; /* the serial console device */
-
#ifdef CONFIG_SERIAL_ATMEL_CONSOLE
static void atmel_console_putchar(struct uart_port *port, int ch)
{
@@ -2594,47 +2551,6 @@ static struct console atmel_console = {
#define ATMEL_CONSOLE_DEVICE (&atmel_console)
-/*
- * Early console initialization (before VM subsystem initialized).
- */
-static int __init atmel_console_init(void)
-{
- int ret;
- if (atmel_default_console_device) {
- struct atmel_uart_data *pdata =
- dev_get_platdata(&atmel_default_console_device->dev);
- int id = pdata->num;
- struct atmel_uart_port *atmel_port = &atmel_ports[id];
-
- atmel_port->backup_imr = 0;
- atmel_port->uart.line = id;
-
- add_preferred_console(ATMEL_DEVICENAME, id, NULL);
- ret = atmel_init_port(atmel_port, atmel_default_console_device);
- if (ret)
- return ret;
- register_console(&atmel_console);
- }
-
- return 0;
-}
-
-console_initcall(atmel_console_init);
-
-/*
- * Late console initialization.
- */
-static int __init atmel_late_console_init(void)
-{
- if (atmel_default_console_device
- && !(atmel_console.flags & CON_ENABLED))
- register_console(&atmel_console);
-
- return 0;
-}
-
-core_initcall(atmel_late_console_init);
-
static inline bool atmel_is_console_port(struct uart_port *port)
{
return port->cons && port->cons->index == port->line;
@@ -2804,19 +2720,13 @@ static int atmel_serial_probe(struct platform_device *pdev)
{
struct atmel_uart_port *atmel_port;
struct device_node *np = pdev->dev.of_node;
- struct atmel_uart_data *pdata = dev_get_platdata(&pdev->dev);
void *data;
int ret = -ENODEV;
bool rs485_enabled;
BUILD_BUG_ON(ATMEL_SERIAL_RINGSIZE & (ATMEL_SERIAL_RINGSIZE - 1));
- if (np)
- ret = of_alias_get_id(np, "serial");
- else
- if (pdata)
- ret = pdata->num;
-
+ ret = of_alias_get_id(np, "serial");
if (ret < 0)
/* port id not found in platform data nor device-tree aliases:
* auto-enumerate it */
diff --git a/drivers/tty/serial/efm32-uart.c b/drivers/tty/serial/efm32-uart.c
index ebd8569f9ad5..9fff25be87f9 100644
--- a/drivers/tty/serial/efm32-uart.c
+++ b/drivers/tty/serial/efm32-uart.c
@@ -27,6 +27,7 @@
#define UARTn_FRAME 0x04
#define UARTn_FRAME_DATABITS__MASK 0x000f
#define UARTn_FRAME_DATABITS(n) ((n) - 3)
+#define UARTn_FRAME_PARITY__MASK 0x0300
#define UARTn_FRAME_PARITY_NONE 0x0000
#define UARTn_FRAME_PARITY_EVEN 0x0200
#define UARTn_FRAME_PARITY_ODD 0x0300
@@ -572,12 +573,16 @@ static void efm32_uart_console_get_options(struct efm32_uart_port *efm_port,
16 * (4 + (clkdiv >> 6)));
frame = efm32_uart_read32(efm_port, UARTn_FRAME);
- if (frame & UARTn_FRAME_PARITY_ODD)
+ switch (frame & UARTn_FRAME_PARITY__MASK) {
+ case UARTn_FRAME_PARITY_ODD:
*parity = 'o';
- else if (frame & UARTn_FRAME_PARITY_EVEN)
+ break;
+ case UARTn_FRAME_PARITY_EVEN:
*parity = 'e';
- else
+ break;
+ default:
*parity = 'n';
+ }
*bits = (frame & UARTn_FRAME_DATABITS__MASK) -
UARTn_FRAME_DATABITS(4) + 4;
diff --git a/drivers/tty/serial/fsl_lpuart.c b/drivers/tty/serial/fsl_lpuart.c
index 15df1ba78095..343de8c384b0 100644
--- a/drivers/tty/serial/fsl_lpuart.c
+++ b/drivers/tty/serial/fsl_lpuart.c
@@ -140,6 +140,8 @@
#define UARTBAUD_SBNS 0x00002000
#define UARTBAUD_SBR 0x00000000
#define UARTBAUD_SBR_MASK 0x1fff
+#define UARTBAUD_OSR_MASK 0x1f
+#define UARTBAUD_OSR_SHIFT 24
#define UARTSTAT_LBKDIF 0x80000000
#define UARTSTAT_RXEDGIF 0x40000000
@@ -231,12 +233,14 @@
#define DEV_NAME "ttyLP"
#define UART_NR 6
+/* IMX lpuart has four extra unused regs located at the beginning */
+#define IMX_REG_OFF 0x10
+
struct lpuart_port {
struct uart_port port;
struct clk *clk;
unsigned int txfifo_size;
unsigned int rxfifo_size;
- bool lpuart32;
bool lpuart_dma_tx_use;
bool lpuart_dma_rx_use;
@@ -258,13 +262,28 @@ struct lpuart_port {
wait_queue_head_t dma_wait;
};
+struct lpuart_soc_data {
+ char iotype;
+ u8 reg_off;
+};
+
+static const struct lpuart_soc_data vf_data = {
+ .iotype = UPIO_MEM,
+};
+
+static const struct lpuart_soc_data ls_data = {
+ .iotype = UPIO_MEM32BE,
+};
+
+static struct lpuart_soc_data imx_data = {
+ .iotype = UPIO_MEM32,
+ .reg_off = IMX_REG_OFF,
+};
+
static const struct of_device_id lpuart_dt_ids[] = {
- {
- .compatible = "fsl,vf610-lpuart",
- },
- {
- .compatible = "fsl,ls1021a-lpuart",
- },
+ { .compatible = "fsl,vf610-lpuart", .data = &vf_data, },
+ { .compatible = "fsl,ls1021a-lpuart", .data = &ls_data, },
+ { .compatible = "fsl,imx7ulp-lpuart", .data = &imx_data, },
{ /* sentinel */ }
};
MODULE_DEVICE_TABLE(of, lpuart_dt_ids);
@@ -272,14 +291,29 @@ MODULE_DEVICE_TABLE(of, lpuart_dt_ids);
/* Forward declare this for the dma callbacks*/
static void lpuart_dma_tx_complete(void *arg);
-static u32 lpuart32_read(void __iomem *addr)
+static inline u32 lpuart32_read(struct uart_port *port, u32 off)
{
- return ioread32be(addr);
+ switch (port->iotype) {
+ case UPIO_MEM32:
+ return readl(port->membase + off);
+ case UPIO_MEM32BE:
+ return ioread32be(port->membase + off);
+ default:
+ return 0;
+ }
}
-static void lpuart32_write(u32 val, void __iomem *addr)
+static inline void lpuart32_write(struct uart_port *port, u32 val,
+ u32 off)
{
- iowrite32be(val, addr);
+ switch (port->iotype) {
+ case UPIO_MEM32:
+ writel(val, port->membase + off);
+ break;
+ case UPIO_MEM32BE:
+ iowrite32be(val, port->membase + off);
+ break;
+ }
}
static void lpuart_stop_tx(struct uart_port *port)
@@ -295,9 +329,9 @@ static void lpuart32_stop_tx(struct uart_port *port)
{
unsigned long temp;
- temp = lpuart32_read(port->membase + UARTCTRL);
+ temp = lpuart32_read(port, UARTCTRL);
temp &= ~(UARTCTRL_TIE | UARTCTRL_TCIE);
- lpuart32_write(temp, port->membase + UARTCTRL);
+ lpuart32_write(port, temp, UARTCTRL);
}
static void lpuart_stop_rx(struct uart_port *port)
@@ -312,8 +346,8 @@ static void lpuart32_stop_rx(struct uart_port *port)
{
unsigned long temp;
- temp = lpuart32_read(port->membase + UARTCTRL);
- lpuart32_write(temp & ~UARTCTRL_RE, port->membase + UARTCTRL);
+ temp = lpuart32_read(port, UARTCTRL);
+ lpuart32_write(port, temp & ~UARTCTRL_RE, UARTCTRL);
}
static void lpuart_dma_tx(struct lpuart_port *sport)
@@ -512,14 +546,14 @@ static inline void lpuart32_transmit_buffer(struct lpuart_port *sport)
struct circ_buf *xmit = &sport->port.state->xmit;
unsigned long txcnt;
- txcnt = lpuart32_read(sport->port.membase + UARTWATER);
+ txcnt = lpuart32_read(&sport->port, UARTWATER);
txcnt = txcnt >> UARTWATER_TXCNT_OFF;
txcnt &= UARTWATER_COUNT_MASK;
while (!uart_circ_empty(xmit) && (txcnt < sport->txfifo_size)) {
- lpuart32_write(xmit->buf[xmit->tail], sport->port.membase + UARTDATA);
+ lpuart32_write(&sport->port, xmit->buf[xmit->tail], UARTDATA);
xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
sport->port.icount.tx++;
- txcnt = lpuart32_read(sport->port.membase + UARTWATER);
+ txcnt = lpuart32_read(&sport->port, UARTWATER);
txcnt = txcnt >> UARTWATER_TXCNT_OFF;
txcnt &= UARTWATER_COUNT_MASK;
}
@@ -555,10 +589,10 @@ static void lpuart32_start_tx(struct uart_port *port)
struct lpuart_port *sport = container_of(port, struct lpuart_port, port);
unsigned long temp;
- temp = lpuart32_read(port->membase + UARTCTRL);
- lpuart32_write(temp | UARTCTRL_TIE, port->membase + UARTCTRL);
+ temp = lpuart32_read(port, UARTCTRL);
+ lpuart32_write(port, temp | UARTCTRL_TIE, UARTCTRL);
- if (lpuart32_read(port->membase + UARTSTAT) & UARTSTAT_TDRE)
+ if (lpuart32_read(port, UARTSTAT) & UARTSTAT_TDRE)
lpuart32_transmit_buffer(sport);
}
@@ -581,7 +615,7 @@ static unsigned int lpuart_tx_empty(struct uart_port *port)
static unsigned int lpuart32_tx_empty(struct uart_port *port)
{
- return (lpuart32_read(port->membase + UARTSTAT) & UARTSTAT_TC) ?
+ return (lpuart32_read(port, UARTSTAT) & UARTSTAT_TC) ?
TIOCSER_TEMT : 0;
}
@@ -593,22 +627,22 @@ static irqreturn_t lpuart_txint(int irq, void *dev_id)
spin_lock_irqsave(&sport->port.lock, flags);
if (sport->port.x_char) {
- if (sport->lpuart32)
- lpuart32_write(sport->port.x_char, sport->port.membase + UARTDATA);
+ if (sport->port.iotype & (UPIO_MEM32 | UPIO_MEM32BE))
+ lpuart32_write(&sport->port, sport->port.x_char, UARTDATA);
else
writeb(sport->port.x_char, sport->port.membase + UARTDR);
goto out;
}
if (uart_circ_empty(xmit) || uart_tx_stopped(&sport->port)) {
- if (sport->lpuart32)
+ if (sport->port.iotype & (UPIO_MEM32 | UPIO_MEM32BE))
lpuart32_stop_tx(&sport->port);
else
lpuart_stop_tx(&sport->port);
goto out;
}
- if (sport->lpuart32)
+ if (sport->port.iotype & (UPIO_MEM32 | UPIO_MEM32BE))
lpuart32_transmit_buffer(sport);
else
lpuart_transmit_buffer(sport);
@@ -694,15 +728,15 @@ static irqreturn_t lpuart32_rxint(int irq, void *dev_id)
spin_lock_irqsave(&sport->port.lock, flags);
- while (!(lpuart32_read(sport->port.membase + UARTFIFO) & UARTFIFO_RXEMPT)) {
+ while (!(lpuart32_read(&sport->port, UARTFIFO) & UARTFIFO_RXEMPT)) {
flg = TTY_NORMAL;
sport->port.icount.rx++;
/*
* to clear the FE, OR, NF, FE, PE flags,
* read STAT then read DATA reg
*/
- sr = lpuart32_read(sport->port.membase + UARTSTAT);
- rx = lpuart32_read(sport->port.membase + UARTDATA);
+ sr = lpuart32_read(&sport->port, UARTSTAT);
+ rx = lpuart32_read(&sport->port, UARTDATA);
rx &= 0x3ff;
if (uart_handle_sysrq_char(&sport->port, (unsigned char)rx))
@@ -769,18 +803,18 @@ static irqreturn_t lpuart32_int(int irq, void *dev_id)
struct lpuart_port *sport = dev_id;
unsigned long sts, rxcount;
- sts = lpuart32_read(sport->port.membase + UARTSTAT);
- rxcount = lpuart32_read(sport->port.membase + UARTWATER);
+ sts = lpuart32_read(&sport->port, UARTSTAT);
+ rxcount = lpuart32_read(&sport->port, UARTWATER);
rxcount = rxcount >> UARTWATER_RXCNT_OFF;
if (sts & UARTSTAT_RDRF || rxcount > 0)
lpuart32_rxint(irq, dev_id);
if ((sts & UARTSTAT_TDRE) &&
- !(lpuart32_read(sport->port.membase + UARTBAUD) & UARTBAUD_TDMAE))
+ !(lpuart32_read(&sport->port, UARTBAUD) & UARTBAUD_TDMAE))
lpuart_txint(irq, dev_id);
- lpuart32_write(sts, sport->port.membase + UARTSTAT);
+ lpuart32_write(&sport->port, sts, UARTSTAT);
return IRQ_HANDLED;
}
@@ -1041,7 +1075,7 @@ static unsigned int lpuart32_get_mctrl(struct uart_port *port)
unsigned int temp = 0;
unsigned long reg;
- reg = lpuart32_read(port->membase + UARTMODIR);
+ reg = lpuart32_read(port, UARTMODIR);
if (reg & UARTMODIR_TXCTSE)
temp |= TIOCM_CTS;
@@ -1076,7 +1110,7 @@ static void lpuart32_set_mctrl(struct uart_port *port, unsigned int mctrl)
{
unsigned long temp;
- temp = lpuart32_read(port->membase + UARTMODIR) &
+ temp = lpuart32_read(port, UARTMODIR) &
~(UARTMODIR_RXRTSE | UARTMODIR_TXCTSE);
if (mctrl & TIOCM_RTS)
@@ -1085,7 +1119,7 @@ static void lpuart32_set_mctrl(struct uart_port *port, unsigned int mctrl)
if (mctrl & TIOCM_CTS)
temp |= UARTMODIR_TXCTSE;
- lpuart32_write(temp, port->membase + UARTMODIR);
+ lpuart32_write(port, temp, UARTMODIR);
}
static void lpuart_break_ctl(struct uart_port *port, int break_state)
@@ -1104,12 +1138,12 @@ static void lpuart32_break_ctl(struct uart_port *port, int break_state)
{
unsigned long temp;
- temp = lpuart32_read(port->membase + UARTCTRL) & ~UARTCTRL_SBK;
+ temp = lpuart32_read(port, UARTCTRL) & ~UARTCTRL_SBK;
if (break_state != 0)
temp |= UARTCTRL_SBK;
- lpuart32_write(temp, port->membase + UARTCTRL);
+ lpuart32_write(port, temp, UARTCTRL);
}
static void lpuart_setup_watermark(struct lpuart_port *sport)
@@ -1149,24 +1183,24 @@ static void lpuart32_setup_watermark(struct lpuart_port *sport)
unsigned long val, ctrl;
unsigned long ctrl_saved;
- ctrl = lpuart32_read(sport->port.membase + UARTCTRL);
+ ctrl = lpuart32_read(&sport->port, UARTCTRL);
ctrl_saved = ctrl;
ctrl &= ~(UARTCTRL_TIE | UARTCTRL_TCIE | UARTCTRL_TE |
UARTCTRL_RIE | UARTCTRL_RE);
- lpuart32_write(ctrl, sport->port.membase + UARTCTRL);
+ lpuart32_write(&sport->port, ctrl, UARTCTRL);
/* enable FIFO mode */
- val = lpuart32_read(sport->port.membase + UARTFIFO);
+ val = lpuart32_read(&sport->port, UARTFIFO);
val |= UARTFIFO_TXFE | UARTFIFO_RXFE;
val |= UARTFIFO_TXFLUSH | UARTFIFO_RXFLUSH;
- lpuart32_write(val, sport->port.membase + UARTFIFO);
+ lpuart32_write(&sport->port, val, UARTFIFO);
/* set the watermark */
val = (0x1 << UARTWATER_RXWATER_OFF) | (0x0 << UARTWATER_TXWATER_OFF);
- lpuart32_write(val, sport->port.membase + UARTWATER);
+ lpuart32_write(&sport->port, val, UARTWATER);
/* Restore cr2 */
- lpuart32_write(ctrl_saved, sport->port.membase + UARTCTRL);
+ lpuart32_write(&sport->port, ctrl_saved, UARTCTRL);
}
static void rx_dma_timer_init(struct lpuart_port *sport)
@@ -1242,7 +1276,7 @@ static int lpuart32_startup(struct uart_port *port)
unsigned long temp;
/* determine FIFO size */
- temp = lpuart32_read(sport->port.membase + UARTFIFO);
+ temp = lpuart32_read(&sport->port, UARTFIFO);
sport->txfifo_size = 0x1 << (((temp >> UARTFIFO_TXSIZE_OFF) &
UARTFIFO_FIFOSIZE_MASK) - 1);
@@ -1259,10 +1293,10 @@ static int lpuart32_startup(struct uart_port *port)
lpuart32_setup_watermark(sport);
- temp = lpuart32_read(sport->port.membase + UARTCTRL);
+ temp = lpuart32_read(&sport->port, UARTCTRL);
temp |= (UARTCTRL_RIE | UARTCTRL_TIE | UARTCTRL_RE | UARTCTRL_TE);
temp |= UARTCTRL_ILIE;
- lpuart32_write(temp, sport->port.membase + UARTCTRL);
+ lpuart32_write(&sport->port, temp, UARTCTRL);
spin_unlock_irqrestore(&sport->port.lock, flags);
return 0;
@@ -1311,10 +1345,10 @@ static void lpuart32_shutdown(struct uart_port *port)
spin_lock_irqsave(&port->lock, flags);
/* disable Rx/Tx and interrupts */
- temp = lpuart32_read(port->membase + UARTCTRL);
+ temp = lpuart32_read(port, UARTCTRL);
temp &= ~(UARTCTRL_TE | UARTCTRL_RE |
UARTCTRL_TIE | UARTCTRL_TCIE | UARTCTRL_RIE);
- lpuart32_write(temp, port->membase + UARTCTRL);
+ lpuart32_write(port, temp, UARTCTRL);
spin_unlock_irqrestore(&port->lock, flags);
@@ -1479,6 +1513,75 @@ lpuart_set_termios(struct uart_port *port, struct ktermios *termios,
}
static void
+lpuart32_serial_setbrg(struct lpuart_port *sport, unsigned int baudrate)
+{
+ u32 sbr, osr, baud_diff, tmp_osr, tmp_sbr, tmp_diff, tmp;
+ u32 clk = sport->port.uartclk;
+
+ /*
+ * The idea is to use the best OSR (over-sampling rate) possible.
+ * Note, OSR is typically hard-set to 16 in other LPUART instantiations.
+ * Loop to find the best OSR value possible, one that generates minimum
+ * baud_diff iterate through the rest of the supported values of OSR.
+ *
+ * Calculation Formula:
+ * Baud Rate = baud clock / ((OSR+1) × SBR)
+ */
+ baud_diff = baudrate;
+ osr = 0;
+ sbr = 0;
+
+ for (tmp_osr = 4; tmp_osr <= 32; tmp_osr++) {
+ /* calculate the temporary sbr value */
+ tmp_sbr = (clk / (baudrate * tmp_osr));
+ if (tmp_sbr == 0)
+ tmp_sbr = 1;
+
+ /*
+ * calculate the baud rate difference based on the temporary
+ * osr and sbr values
+ */
+ tmp_diff = clk / (tmp_osr * tmp_sbr) - baudrate;
+
+ /* select best values between sbr and sbr+1 */
+ tmp = clk / (tmp_osr * (tmp_sbr + 1));
+ if (tmp_diff > (baudrate - tmp)) {
+ tmp_diff = baudrate - tmp;
+ tmp_sbr++;
+ }
+
+ if (tmp_diff <= baud_diff) {
+ baud_diff = tmp_diff;
+ osr = tmp_osr;
+ sbr = tmp_sbr;
+
+ if (!baud_diff)
+ break;
+ }
+ }
+
+ /* handle buadrate outside acceptable rate */
+ if (baud_diff > ((baudrate / 100) * 3))
+ dev_warn(sport->port.dev,
+ "unacceptable baud rate difference of more than 3%%\n");
+
+ tmp = lpuart32_read(&sport->port, UARTBAUD);
+
+ if ((osr > 3) && (osr < 8))
+ tmp |= UARTBAUD_BOTHEDGE;
+
+ tmp &= ~(UARTBAUD_OSR_MASK << UARTBAUD_OSR_SHIFT);
+ tmp |= (((osr-1) & UARTBAUD_OSR_MASK) << UARTBAUD_OSR_SHIFT);
+
+ tmp &= ~UARTBAUD_SBR_MASK;
+ tmp |= sbr & UARTBAUD_SBR_MASK;
+
+ tmp &= ~(UARTBAUD_TDMAE | UARTBAUD_RDMAE);
+
+ lpuart32_write(&sport->port, tmp, UARTBAUD);
+}
+
+static void
lpuart32_set_termios(struct uart_port *port, struct ktermios *termios,
struct ktermios *old)
{
@@ -1487,11 +1590,10 @@ lpuart32_set_termios(struct uart_port *port, struct ktermios *termios,
unsigned long ctrl, old_ctrl, bd, modem;
unsigned int baud;
unsigned int old_csize = old ? old->c_cflag & CSIZE : CS8;
- unsigned int sbr;
- ctrl = old_ctrl = lpuart32_read(sport->port.membase + UARTCTRL);
- bd = lpuart32_read(sport->port.membase + UARTBAUD);
- modem = lpuart32_read(sport->port.membase + UARTMODIR);
+ ctrl = old_ctrl = lpuart32_read(&sport->port, UARTCTRL);
+ bd = lpuart32_read(&sport->port, UARTBAUD);
+ modem = lpuart32_read(&sport->port, UARTMODIR);
/*
* only support CS8 and CS7, and for CS7 must enable PE.
* supported mode:
@@ -1577,21 +1679,16 @@ lpuart32_set_termios(struct uart_port *port, struct ktermios *termios,
uart_update_timeout(port, termios->c_cflag, baud);
/* wait transmit engin complete */
- while (!(lpuart32_read(sport->port.membase + UARTSTAT) & UARTSTAT_TC))
+ while (!(lpuart32_read(&sport->port, UARTSTAT) & UARTSTAT_TC))
barrier();
/* disable transmit and receive */
- lpuart32_write(old_ctrl & ~(UARTCTRL_TE | UARTCTRL_RE),
- sport->port.membase + UARTCTRL);
+ lpuart32_write(&sport->port, old_ctrl & ~(UARTCTRL_TE | UARTCTRL_RE),
+ UARTCTRL);
- sbr = sport->port.uartclk / (16 * baud);
- bd &= ~UARTBAUD_SBR_MASK;
- bd |= sbr & UARTBAUD_SBR_MASK;
- bd |= UARTBAUD_BOTHEDGE;
- bd &= ~(UARTBAUD_TDMAE | UARTBAUD_RDMAE);
- lpuart32_write(bd, sport->port.membase + UARTBAUD);
- lpuart32_write(modem, sport->port.membase + UARTMODIR);
- lpuart32_write(ctrl, sport->port.membase + UARTCTRL);
+ lpuart32_serial_setbrg(sport, baud);
+ lpuart32_write(&sport->port, modem, UARTMODIR);
+ lpuart32_write(&sport->port, ctrl, UARTCTRL);
/* restore control register */
spin_unlock_irqrestore(&sport->port.lock, flags);
@@ -1694,10 +1791,10 @@ static void lpuart_console_putchar(struct uart_port *port, int ch)
static void lpuart32_console_putchar(struct uart_port *port, int ch)
{
- while (!(lpuart32_read(port->membase + UARTSTAT) & UARTSTAT_TDRE))
+ while (!(lpuart32_read(port, UARTSTAT) & UARTSTAT_TDRE))
barrier();
- lpuart32_write(ch, port->membase + UARTDATA);
+ lpuart32_write(port, ch, UARTDATA);
}
static void
@@ -1745,18 +1842,18 @@ lpuart32_console_write(struct console *co, const char *s, unsigned int count)
spin_lock_irqsave(&sport->port.lock, flags);
/* first save CR2 and then disable interrupts */
- cr = old_cr = lpuart32_read(sport->port.membase + UARTCTRL);
+ cr = old_cr = lpuart32_read(&sport->port, UARTCTRL);
cr |= (UARTCTRL_TE | UARTCTRL_RE);
cr &= ~(UARTCTRL_TIE | UARTCTRL_TCIE | UARTCTRL_RIE);
- lpuart32_write(cr, sport->port.membase + UARTCTRL);
+ lpuart32_write(&sport->port, cr, UARTCTRL);
uart_console_write(&sport->port, s, count, lpuart32_console_putchar);
/* wait for transmitter finish complete and restore CR2 */
- while (!(lpuart32_read(sport->port.membase + UARTSTAT) & UARTSTAT_TC))
+ while (!(lpuart32_read(&sport->port, UARTSTAT) & UARTSTAT_TC))
barrier();
- lpuart32_write(old_cr, sport->port.membase + UARTCTRL);
+ lpuart32_write(&sport->port, old_cr, UARTCTRL);
if (locked)
spin_unlock_irqrestore(&sport->port.lock, flags);
@@ -1822,14 +1919,14 @@ lpuart32_console_get_options(struct lpuart_port *sport, int *baud,
unsigned long cr, bd;
unsigned int sbr, uartclk, baud_raw;
- cr = lpuart32_read(sport->port.membase + UARTCTRL);
+ cr = lpuart32_read(&sport->port, UARTCTRL);
cr &= UARTCTRL_TE | UARTCTRL_RE;
if (!cr)
return;
/* ok, the port was enabled */
- cr = lpuart32_read(sport->port.membase + UARTCTRL);
+ cr = lpuart32_read(&sport->port, UARTCTRL);
*parity = 'n';
if (cr & UARTCTRL_PE) {
@@ -1844,7 +1941,7 @@ lpuart32_console_get_options(struct lpuart_port *sport, int *baud,
else
*bits = 8;
- bd = lpuart32_read(sport->port.membase + UARTBAUD);
+ bd = lpuart32_read(&sport->port, UARTBAUD);
bd &= UARTBAUD_SBR_MASK;
sbr = bd;
uartclk = clk_get_rate(sport->clk);
@@ -1881,12 +1978,12 @@ static int __init lpuart_console_setup(struct console *co, char *options)
if (options)
uart_parse_options(options, &baud, &parity, &bits, &flow);
else
- if (sport->lpuart32)
+ if (sport->port.iotype & (UPIO_MEM32 | UPIO_MEM32BE))
lpuart32_console_get_options(sport, &baud, &parity, &bits);
else
lpuart_console_get_options(sport, &baud, &parity, &bits);
- if (sport->lpuart32)
+ if (sport->port.iotype & (UPIO_MEM32 | UPIO_MEM32BE))
lpuart32_setup_watermark(sport);
else
lpuart_setup_watermark(sport);
@@ -1945,12 +2042,26 @@ static int __init lpuart32_early_console_setup(struct earlycon_device *device,
if (!device->port.membase)
return -ENODEV;
+ device->port.iotype = UPIO_MEM32BE;
device->con->write = lpuart32_early_write;
return 0;
}
+static int __init lpuart32_imx_early_console_setup(struct earlycon_device *device,
+ const char *opt)
+{
+ if (!device->port.membase)
+ return -ENODEV;
+
+ device->port.iotype = UPIO_MEM32;
+ device->port.membase += IMX_REG_OFF;
+ device->con->write = lpuart32_early_write;
+
+ return 0;
+}
OF_EARLYCON_DECLARE(lpuart, "fsl,vf610-lpuart", lpuart_early_console_setup);
OF_EARLYCON_DECLARE(lpuart32, "fsl,ls1021a-lpuart", lpuart32_early_console_setup);
+OF_EARLYCON_DECLARE(lpuart32, "fsl,imx7ulp-lpuart", lpuart32_imx_early_console_setup);
EARLYCON_DECLARE(lpuart, lpuart_early_console_setup);
EARLYCON_DECLARE(lpuart32, lpuart32_early_console_setup);
@@ -1971,6 +2082,9 @@ static struct uart_driver lpuart_reg = {
static int lpuart_probe(struct platform_device *pdev)
{
+ const struct of_device_id *of_id = of_match_device(lpuart_dt_ids,
+ &pdev->dev);
+ const struct lpuart_soc_data *sdata = of_id->data;
struct device_node *np = pdev->dev.of_node;
struct lpuart_port *sport;
struct resource *res;
@@ -1988,25 +2102,23 @@ static int lpuart_probe(struct platform_device *pdev)
return ret;
}
sport->port.line = ret;
- sport->lpuart32 = of_device_is_compatible(np, "fsl,ls1021a-lpuart");
-
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
sport->port.membase = devm_ioremap_resource(&pdev->dev, res);
if (IS_ERR(sport->port.membase))
return PTR_ERR(sport->port.membase);
+ sport->port.membase += sdata->reg_off;
sport->port.mapbase = res->start;
sport->port.dev = &pdev->dev;
sport->port.type = PORT_LPUART;
- sport->port.iotype = UPIO_MEM;
ret = platform_get_irq(pdev, 0);
if (ret < 0) {
dev_err(&pdev->dev, "cannot obtain irq\n");
return ret;
}
sport->port.irq = ret;
-
- if (sport->lpuart32)
+ sport->port.iotype = sdata->iotype;
+ if (sport->port.iotype & (UPIO_MEM32 | UPIO_MEM32BE))
sport->port.ops = &lpuart32_pops;
else
sport->port.ops = &lpuart_pops;
@@ -2033,7 +2145,7 @@ static int lpuart_probe(struct platform_device *pdev)
platform_set_drvdata(pdev, &sport->port);
- if (sport->lpuart32)
+ if (sport->port.iotype & (UPIO_MEM32 | UPIO_MEM32BE))
lpuart_reg.cons = LPUART32_CONSOLE;
else
lpuart_reg.cons = LPUART_CONSOLE;
@@ -2086,11 +2198,11 @@ static int lpuart_suspend(struct device *dev)
struct lpuart_port *sport = dev_get_drvdata(dev);
unsigned long temp;
- if (sport->lpuart32) {
+ if (sport->port.iotype & (UPIO_MEM32 | UPIO_MEM32BE)) {
/* disable Rx/Tx and interrupts */
- temp = lpuart32_read(sport->port.membase + UARTCTRL);
+ temp = lpuart32_read(&sport->port, UARTCTRL);
temp &= ~(UARTCTRL_TE | UARTCTRL_TIE | UARTCTRL_TCIE);
- lpuart32_write(temp, sport->port.membase + UARTCTRL);
+ lpuart32_write(&sport->port, temp, UARTCTRL);
} else {
/* disable Rx/Tx and interrupts */
temp = readb(sport->port.membase + UARTCR2);
@@ -2137,12 +2249,12 @@ static int lpuart_resume(struct device *dev)
if (sport->port.suspended && !sport->port.irq_wake)
clk_prepare_enable(sport->clk);
- if (sport->lpuart32) {
+ if (sport->port.iotype & (UPIO_MEM32 | UPIO_MEM32BE)) {
lpuart32_setup_watermark(sport);
- temp = lpuart32_read(sport->port.membase + UARTCTRL);
+ temp = lpuart32_read(&sport->port, UARTCTRL);
temp |= (UARTCTRL_RIE | UARTCTRL_TIE | UARTCTRL_RE |
UARTCTRL_TE | UARTCTRL_ILIE);
- lpuart32_write(temp, sport->port.membase + UARTCTRL);
+ lpuart32_write(&sport->port, temp, UARTCTRL);
} else {
lpuart_setup_watermark(sport);
temp = readb(sport->port.membase + UARTCR2);
diff --git a/drivers/tty/serial/ifx6x60.c b/drivers/tty/serial/ifx6x60.c
index 157883653256..f190a84a0246 100644
--- a/drivers/tty/serial/ifx6x60.c
+++ b/drivers/tty/serial/ifx6x60.c
@@ -1382,9 +1382,9 @@ static struct spi_driver ifx_spi_driver = {
static void __exit ifx_spi_exit(void)
{
/* unregister */
+ spi_unregister_driver(&ifx_spi_driver);
tty_unregister_driver(tty_drv);
put_tty_driver(tty_drv);
- spi_unregister_driver(&ifx_spi_driver);
unregister_reboot_notifier(&ifx_modem_reboot_notifier_block);
}
diff --git a/drivers/tty/serial/imx.c b/drivers/tty/serial/imx.c
index 33509b4beaec..9e3162bf3bd1 100644
--- a/drivers/tty/serial/imx.c
+++ b/drivers/tty/serial/imx.c
@@ -186,6 +186,11 @@
#define UART_NR 8
+/* RX DMA buffer periods */
+#define RX_DMA_PERIODS 4
+#define RX_BUF_SIZE (PAGE_SIZE)
+
+
/* i.MX21 type uart runs on all i.mx except i.MX1 and i.MX6q */
enum imx_uart_type {
IMX1_UART,
@@ -207,9 +212,6 @@ struct imx_port {
unsigned int have_rtscts:1;
unsigned int have_rtsgpio:1;
unsigned int dte_mode:1;
- unsigned int irda_inv_rx:1;
- unsigned int irda_inv_tx:1;
- unsigned short trcv_delay; /* transceiver delay */
struct clk *clk_ipg;
struct clk *clk_per;
const struct imx_uart_data *devdata;
@@ -224,6 +226,7 @@ struct imx_port {
struct dma_chan *dma_chan_rx, *dma_chan_tx;
struct scatterlist rx_sgl, tx_sgl[2];
void *rx_buf;
+ unsigned int rx_buf_size;
struct circ_buf rx_ring;
unsigned int rx_periods;
dma_cookie_t rx_cookie;
@@ -964,8 +967,6 @@ static void imx_timeout(unsigned long data)
}
}
-#define RX_BUF_SIZE (PAGE_SIZE)
-
/*
* There are two kinds of RX DMA interrupts(such as in the MX6Q):
* [1] the RX DMA buffer is full.
@@ -1048,9 +1049,6 @@ static void dma_rx_callback(void *data)
}
}
-/* RX DMA buffer periods */
-#define RX_DMA_PERIODS 4
-
static int start_rx_dma(struct imx_port *sport)
{
struct scatterlist *sgl = &sport->rx_sgl;
@@ -1061,9 +1059,8 @@ static int start_rx_dma(struct imx_port *sport)
sport->rx_ring.head = 0;
sport->rx_ring.tail = 0;
- sport->rx_periods = RX_DMA_PERIODS;
- sg_init_one(sgl, sport->rx_buf, RX_BUF_SIZE);
+ sg_init_one(sgl, sport->rx_buf, sport->rx_buf_size);
ret = dma_map_sg(dev, sgl, 1, DMA_FROM_DEVICE);
if (ret == 0) {
dev_err(dev, "DMA mapping error for RX.\n");
@@ -1174,7 +1171,7 @@ static int imx_uart_dma_init(struct imx_port *sport)
goto err;
}
- sport->rx_buf = kzalloc(PAGE_SIZE, GFP_KERNEL);
+ sport->rx_buf = kzalloc(sport->rx_buf_size, GFP_KERNEL);
if (!sport->rx_buf) {
ret = -ENOMEM;
goto err;
@@ -1302,7 +1299,9 @@ static int imx_startup(struct uart_port *port)
imx_enable_dma(sport);
temp = readl(sport->port.membase + UCR1);
- temp |= UCR1_RRDYEN | UCR1_RTSDEN | UCR1_UARTEN;
+ temp |= UCR1_RRDYEN | UCR1_UARTEN;
+ if (sport->have_rtscts)
+ temp |= UCR1_RTSDEN;
writel(temp, sport->port.membase + UCR1);
@@ -1340,29 +1339,13 @@ static int imx_startup(struct uart_port *port)
imx_enable_ms(&sport->port);
/*
- * If the serial port is opened for reading start RX DMA immediately
- * instead of waiting for RX FIFO interrupts. In our iMX53 the average
- * delay for the first reception dropped from approximately 35000
- * microseconds to 1000 microseconds.
+ * Start RX DMA immediately instead of waiting for RX FIFO interrupts.
+ * In our iMX53 the average delay for the first reception dropped from
+ * approximately 35000 microseconds to 1000 microseconds.
*/
if (sport->dma_is_enabled) {
- struct tty_struct *tty = sport->port.state->port.tty;
- struct tty_file_private *file_priv;
- int readcnt = 0;
-
- spin_lock(&tty->files_lock);
-
- if (!list_empty(&tty->tty_files))
- list_for_each_entry(file_priv, &tty->tty_files, list)
- if (!(file_priv->file->f_flags & O_WRONLY))
- readcnt++;
-
- spin_unlock(&tty->files_lock);
-
- if (readcnt > 0) {
- imx_disable_rx_int(sport);
- start_rx_dma(sport);
- }
+ imx_disable_rx_int(sport);
+ start_rx_dma(sport);
}
spin_unlock_irqrestore(&sport->port.lock, flags);
@@ -2053,6 +2036,7 @@ static int serial_imx_probe_dt(struct imx_port *sport,
{
struct device_node *np = pdev->dev.of_node;
int ret;
+ u32 dma_buf_size[2];
sport->devdata = of_device_get_match_data(&pdev->dev);
if (!sport->devdata)
@@ -2076,6 +2060,14 @@ static int serial_imx_probe_dt(struct imx_port *sport,
if (of_get_property(np, "rts-gpios", NULL))
sport->have_rtsgpio = 1;
+ if (!of_property_read_u32_array(np, "fsl,dma-size", dma_buf_size, 2)) {
+ sport->rx_buf_size = dma_buf_size[0] * dma_buf_size[1];
+ sport->rx_periods = dma_buf_size[1];
+ } else {
+ sport->rx_buf_size = RX_BUF_SIZE;
+ sport->rx_periods = RX_DMA_PERIODS;
+ }
+
return 0;
}
#else
@@ -2184,7 +2176,9 @@ static int serial_imx_probe(struct platform_device *pdev)
* and DCD (when they are outputs) or enables the respective
* irqs. So set this bit early, i.e. before requesting irqs.
*/
- writel(UFCR_DCEDTE, sport->port.membase + UFCR);
+ reg = readl(sport->port.membase + UFCR);
+ if (!(reg & UFCR_DCEDTE))
+ writel(reg | UFCR_DCEDTE, sport->port.membase + UFCR);
/*
* Disable UCR3_RI and UCR3_DCD irqs. They are also not
@@ -2195,7 +2189,15 @@ static int serial_imx_probe(struct platform_device *pdev)
sport->port.membase + UCR3);
} else {
- writel(0, sport->port.membase + UFCR);
+ unsigned long ucr3 = UCR3_DSR;
+
+ reg = readl(sport->port.membase + UFCR);
+ if (reg & UFCR_DCEDTE)
+ writel(reg & ~UFCR_DCEDTE, sport->port.membase + UFCR);
+
+ if (!is_imx1_uart(sport))
+ ucr3 |= IMX21_UCR3_RXDMUXSEL | UCR3_ADNIMP;
+ writel(ucr3, sport->port.membase + UCR3);
}
clk_disable_unprepare(sport->clk_ipg);
diff --git a/drivers/tty/serial/meson_uart.c b/drivers/tty/serial/meson_uart.c
index 60f16795d16b..42e4a4c7597f 100644
--- a/drivers/tty/serial/meson_uart.c
+++ b/drivers/tty/serial/meson_uart.c
@@ -286,7 +286,7 @@ static int meson_uart_startup(struct uart_port *port)
writel(val, port->membase + AML_UART_MISC);
ret = request_irq(port->irq, meson_uart_interrupt, 0,
- meson_uart_type(port), port);
+ port->name, port);
return ret;
}
@@ -298,8 +298,6 @@ static void meson_uart_change_speed(struct uart_port *port, unsigned long baud)
while (!meson_uart_tx_empty(port))
cpu_relax();
- val = readl(port->membase + AML_UART_REG5);
- val &= ~AML_UART_BAUD_MASK;
if (port->uartclk == 24000000) {
val = ((port->uartclk / 3) / baud) - 1;
val |= AML_UART_BAUD_XTAL;
@@ -355,7 +353,7 @@ static void meson_uart_set_termios(struct uart_port *port,
if (cflags & CSTOPB)
val |= AML_UART_STOP_BIN_2SB;
else
- val &= ~AML_UART_STOP_BIN_1SB;
+ val |= AML_UART_STOP_BIN_1SB;
if (cflags & CRTSCTS)
val &= ~AML_UART_TWO_WIRE_EN;
@@ -395,51 +393,25 @@ static int meson_uart_verify_port(struct uart_port *port,
return ret;
}
-static int meson_uart_res_size(struct uart_port *port)
-{
- struct platform_device *pdev = to_platform_device(port->dev);
- struct resource *res;
-
- res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- if (!res) {
- dev_err(port->dev, "cannot obtain I/O memory region");
- return -ENODEV;
- }
-
- return resource_size(res);
-}
-
static void meson_uart_release_port(struct uart_port *port)
{
- int size = meson_uart_res_size(port);
-
- if (port->flags & UPF_IOREMAP) {
- devm_release_mem_region(port->dev, port->mapbase, size);
- devm_iounmap(port->dev, port->membase);
- port->membase = NULL;
- }
+ devm_iounmap(port->dev, port->membase);
+ port->membase = NULL;
+ devm_release_mem_region(port->dev, port->mapbase, port->mapsize);
}
static int meson_uart_request_port(struct uart_port *port)
{
- int size = meson_uart_res_size(port);
-
- if (size < 0)
- return size;
-
- if (!devm_request_mem_region(port->dev, port->mapbase, size,
+ if (!devm_request_mem_region(port->dev, port->mapbase, port->mapsize,
dev_name(port->dev))) {
dev_err(port->dev, "Memory region busy\n");
return -EBUSY;
}
- if (port->flags & UPF_IOREMAP) {
- port->membase = devm_ioremap_nocache(port->dev,
- port->mapbase,
- size);
- if (port->membase == NULL)
- return -ENOMEM;
- }
+ port->membase = devm_ioremap_nocache(port->dev, port->mapbase,
+ port->mapsize);
+ if (!port->membase)
+ return -ENOMEM;
return 0;
}
@@ -470,6 +442,14 @@ static struct uart_ops meson_uart_ops = {
};
#ifdef CONFIG_SERIAL_MESON_CONSOLE
+static void meson_uart_enable_tx_engine(struct uart_port *port)
+{
+ u32 val;
+
+ val = readl(port->membase + AML_UART_CONTROL);
+ val |= AML_UART_TX_EN;
+ writel(val, port->membase + AML_UART_CONTROL);
+}
static void meson_console_putchar(struct uart_port *port, int ch)
{
@@ -499,7 +479,6 @@ static void meson_serial_port_write(struct uart_port *port, const char *s,
}
val = readl(port->membase + AML_UART_CONTROL);
- val |= AML_UART_TX_EN;
tmp = val & ~(AML_UART_TX_INT_EN | AML_UART_RX_INT_EN);
writel(tmp, port->membase + AML_UART_CONTROL);
@@ -538,6 +517,8 @@ static int meson_serial_console_setup(struct console *co, char *options)
if (!port || !port->membase)
return -ENODEV;
+ meson_uart_enable_tx_engine(port);
+
if (options)
uart_parse_options(options, &baud, &parity, &bits, &flow);
@@ -576,11 +557,16 @@ meson_serial_early_console_setup(struct earlycon_device *device, const char *opt
if (!device->port.membase)
return -ENODEV;
+ meson_uart_enable_tx_engine(&device->port);
device->con->write = meson_serial_early_console_write;
return 0;
}
+/* Legacy bindings, should be removed when no more used */
OF_EARLYCON_DECLARE(meson, "amlogic,meson-uart",
meson_serial_early_console_setup);
+/* Stable bindings */
+OF_EARLYCON_DECLARE(meson, "amlogic,meson-ao-uart",
+ meson_serial_early_console_setup);
#define MESON_SERIAL_CONSOLE (&meson_serial_console)
#else
@@ -595,11 +581,76 @@ static struct uart_driver meson_uart_driver = {
.cons = MESON_SERIAL_CONSOLE,
};
+static inline struct clk *meson_uart_probe_clock(struct device *dev,
+ const char *id)
+{
+ struct clk *clk = NULL;
+ int ret;
+
+ clk = devm_clk_get(dev, id);
+ if (IS_ERR(clk))
+ return clk;
+
+ ret = clk_prepare_enable(clk);
+ if (ret) {
+ dev_err(dev, "couldn't enable clk\n");
+ return ERR_PTR(ret);
+ }
+
+ devm_add_action_or_reset(dev,
+ (void(*)(void *))clk_disable_unprepare,
+ clk);
+
+ return clk;
+}
+
+/*
+ * This function gets clocks in the legacy non-stable DT bindings.
+ * This code will be remove once all the platforms switch to the
+ * new DT bindings.
+ */
+static int meson_uart_probe_clocks_legacy(struct platform_device *pdev,
+ struct uart_port *port)
+{
+ struct clk *clk = NULL;
+
+ clk = meson_uart_probe_clock(&pdev->dev, NULL);
+ if (IS_ERR(clk))
+ return PTR_ERR(clk);
+
+ port->uartclk = clk_get_rate(clk);
+
+ return 0;
+}
+
+static int meson_uart_probe_clocks(struct platform_device *pdev,
+ struct uart_port *port)
+{
+ struct clk *clk_xtal = NULL;
+ struct clk *clk_pclk = NULL;
+ struct clk *clk_baud = NULL;
+
+ clk_pclk = meson_uart_probe_clock(&pdev->dev, "pclk");
+ if (IS_ERR(clk_pclk))
+ return PTR_ERR(clk_pclk);
+
+ clk_xtal = meson_uart_probe_clock(&pdev->dev, "xtal");
+ if (IS_ERR(clk_xtal))
+ return PTR_ERR(clk_xtal);
+
+ clk_baud = meson_uart_probe_clock(&pdev->dev, "baud");
+ if (IS_ERR(clk_baud))
+ return PTR_ERR(clk_baud);
+
+ port->uartclk = clk_get_rate(clk_baud);
+
+ return 0;
+}
+
static int meson_uart_probe(struct platform_device *pdev)
{
struct resource *res_mem, *res_irq;
struct uart_port *port;
- struct clk *clk;
int ret = 0;
if (pdev->dev.of_node)
@@ -625,15 +676,20 @@ static int meson_uart_probe(struct platform_device *pdev)
if (!port)
return -ENOMEM;
- clk = clk_get(&pdev->dev, NULL);
- if (IS_ERR(clk))
- return PTR_ERR(clk);
+ /* Use legacy way until all platforms switch to new bindings */
+ if (of_device_is_compatible(pdev->dev.of_node, "amlogic,meson-uart"))
+ ret = meson_uart_probe_clocks_legacy(pdev, port);
+ else
+ ret = meson_uart_probe_clocks(pdev, port);
+
+ if (ret)
+ return ret;
- port->uartclk = clk_get_rate(clk);
port->iotype = UPIO_MEM;
port->mapbase = res_mem->start;
+ port->mapsize = resource_size(res_mem);
port->irq = res_irq->start;
- port->flags = UPF_BOOT_AUTOCONF | UPF_IOREMAP | UPF_LOW_LATENCY;
+ port->flags = UPF_BOOT_AUTOCONF | UPF_LOW_LATENCY;
port->dev = &pdev->dev;
port->line = pdev->id;
port->type = PORT_MESON;
@@ -668,9 +724,14 @@ static int meson_uart_remove(struct platform_device *pdev)
return 0;
}
-
static const struct of_device_id meson_uart_dt_match[] = {
+ /* Legacy bindings, should be removed when no more used */
{ .compatible = "amlogic,meson-uart" },
+ /* Stable bindings */
+ { .compatible = "amlogic,meson6-uart" },
+ { .compatible = "amlogic,meson8-uart" },
+ { .compatible = "amlogic,meson8b-uart" },
+ { .compatible = "amlogic,meson-gx-uart" },
{ /* sentinel */ },
};
MODULE_DEVICE_TABLE(of, meson_uart_dt_match);
diff --git a/drivers/tty/serial/mpsc.c b/drivers/tty/serial/mpsc.c
index 1a60a2063e75..67ffecc50e42 100644
--- a/drivers/tty/serial/mpsc.c
+++ b/drivers/tty/serial/mpsc.c
@@ -754,9 +754,10 @@ static int mpsc_alloc_ring_mem(struct mpsc_port_info *pi)
if (!dma_set_mask(pi->port.dev, 0xffffffff)) {
printk(KERN_ERR "MPSC: Inadequate DMA support\n");
rc = -ENXIO;
- } else if ((pi->dma_region = dma_alloc_noncoherent(pi->port.dev,
+ } else if ((pi->dma_region = dma_alloc_attrs(pi->port.dev,
MPSC_DMA_ALLOC_SIZE,
- &pi->dma_region_p, GFP_KERNEL))
+ &pi->dma_region_p, GFP_KERNEL,
+ DMA_ATTR_NON_CONSISTENT))
== NULL) {
printk(KERN_ERR "MPSC: Can't alloc Desc region\n");
rc = -ENOMEM;
@@ -771,8 +772,9 @@ static void mpsc_free_ring_mem(struct mpsc_port_info *pi)
pr_debug("mpsc_free_ring_mem[%d]: Freeing ring mem\n", pi->port.line);
if (pi->dma_region) {
- dma_free_noncoherent(pi->port.dev, MPSC_DMA_ALLOC_SIZE,
- pi->dma_region, pi->dma_region_p);
+ dma_free_attrs(pi->port.dev, MPSC_DMA_ALLOC_SIZE,
+ pi->dma_region, pi->dma_region_p,
+ DMA_ATTR_NON_CONSISTENT);
pi->dma_region = NULL;
pi->dma_region_p = (dma_addr_t)NULL;
}
diff --git a/drivers/tty/serial/owl-uart.c b/drivers/tty/serial/owl-uart.c
new file mode 100644
index 000000000000..1b8008797a1b
--- /dev/null
+++ b/drivers/tty/serial/owl-uart.c
@@ -0,0 +1,135 @@
+/*
+ * Actions Semi Owl family serial console
+ *
+ * Copyright 2013 Actions Semi Inc.
+ * Author: Actions Semi, Inc.
+ *
+ * Copyright (c) 2016-2017 Andreas Färber
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <linux/console.h>
+#include <linux/delay.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+#include <linux/serial.h>
+#include <linux/serial_core.h>
+
+#define OWL_UART_CTL 0x000
+#define OWL_UART_TXDAT 0x008
+#define OWL_UART_STAT 0x00c
+
+#define OWL_UART_CTL_TRFS_TX BIT(14)
+#define OWL_UART_CTL_EN BIT(15)
+#define OWL_UART_CTL_RXIE BIT(18)
+#define OWL_UART_CTL_TXIE BIT(19)
+
+#define OWL_UART_STAT_RIP BIT(0)
+#define OWL_UART_STAT_TIP BIT(1)
+#define OWL_UART_STAT_TFFU BIT(6)
+#define OWL_UART_STAT_TRFL_MASK (0x1f << 11)
+#define OWL_UART_STAT_UTBB BIT(17)
+
+static inline void owl_uart_write(struct uart_port *port, u32 val, unsigned int off)
+{
+ writel(val, port->membase + off);
+}
+
+static inline u32 owl_uart_read(struct uart_port *port, unsigned int off)
+{
+ return readl(port->membase + off);
+}
+
+#ifdef CONFIG_SERIAL_OWL_CONSOLE
+
+static void owl_console_putchar(struct uart_port *port, int ch)
+{
+ if (!port->membase)
+ return;
+
+ while (owl_uart_read(port, OWL_UART_STAT) & OWL_UART_STAT_TFFU)
+ cpu_relax();
+
+ owl_uart_write(port, ch, OWL_UART_TXDAT);
+}
+
+static void owl_uart_port_write(struct uart_port *port, const char *s,
+ u_int count)
+{
+ u32 old_ctl, val;
+ unsigned long flags;
+ int locked;
+
+ local_irq_save(flags);
+
+ if (port->sysrq)
+ locked = 0;
+ else if (oops_in_progress)
+ locked = spin_trylock(&port->lock);
+ else {
+ spin_lock(&port->lock);
+ locked = 1;
+ }
+
+ old_ctl = owl_uart_read(port, OWL_UART_CTL);
+ val = old_ctl | OWL_UART_CTL_TRFS_TX;
+ /* disable IRQ */
+ val &= ~(OWL_UART_CTL_RXIE | OWL_UART_CTL_TXIE);
+ owl_uart_write(port, val, OWL_UART_CTL);
+
+ uart_console_write(port, s, count, owl_console_putchar);
+
+ /* wait until all contents have been sent out */
+ while (owl_uart_read(port, OWL_UART_STAT) & OWL_UART_STAT_TRFL_MASK)
+ cpu_relax();
+
+ /* clear IRQ pending */
+ val = owl_uart_read(port, OWL_UART_STAT);
+ val |= OWL_UART_STAT_TIP | OWL_UART_STAT_RIP;
+ owl_uart_write(port, val, OWL_UART_STAT);
+
+ owl_uart_write(port, old_ctl, OWL_UART_CTL);
+
+ if (locked)
+ spin_unlock(&port->lock);
+
+ local_irq_restore(flags);
+}
+
+static void owl_uart_early_console_write(struct console *co,
+ const char *s,
+ u_int count)
+{
+ struct earlycon_device *dev = co->data;
+
+ owl_uart_port_write(&dev->port, s, count);
+}
+
+static int __init
+owl_uart_early_console_setup(struct earlycon_device *device, const char *opt)
+{
+ if (!device->port.membase)
+ return -ENODEV;
+
+ device->con->write = owl_uart_early_console_write;
+
+ return 0;
+}
+OF_EARLYCON_DECLARE(owl, "actions,owl-uart",
+ owl_uart_early_console_setup);
+
+#endif /* CONFIG_SERIAL_OWL_CONSOLE */
diff --git a/drivers/tty/serial/pch_uart.c b/drivers/tty/serial/pch_uart.c
index 42caccb5e87e..d3796dc26fa9 100644
--- a/drivers/tty/serial/pch_uart.c
+++ b/drivers/tty/serial/pch_uart.c
@@ -878,8 +878,7 @@ static int dma_handle_rx(struct eg20t_port *priv)
sg_dma_len(sg) = priv->trigger_level;
sg_set_page(&priv->sg_rx, virt_to_page(priv->rx_buf_virt),
- sg_dma_len(sg), (unsigned long)priv->rx_buf_virt &
- ~PAGE_MASK);
+ sg_dma_len(sg), offset_in_page(priv->rx_buf_virt));
sg_dma_address(sg) = priv->rx_buf_dma;
diff --git a/drivers/tty/serial/sccnxp.c b/drivers/tty/serial/sccnxp.c
index fcf803ffad19..cdd2f942317c 100644
--- a/drivers/tty/serial/sccnxp.c
+++ b/drivers/tty/serial/sccnxp.c
@@ -884,14 +884,19 @@ static int sccnxp_probe(struct platform_device *pdev)
clk = devm_clk_get(&pdev->dev, NULL);
if (IS_ERR(clk)) {
- if (PTR_ERR(clk) == -EPROBE_DEFER) {
- ret = -EPROBE_DEFER;
+ ret = PTR_ERR(clk);
+ if (ret == -EPROBE_DEFER)
goto err_out;
- }
+ uartclk = 0;
+ } else {
+ clk_prepare_enable(clk);
+ uartclk = clk_get_rate(clk);
+ }
+
+ if (!uartclk) {
dev_notice(&pdev->dev, "Using default clock frequency\n");
uartclk = s->chip->freq_std;
- } else
- uartclk = clk_get_rate(clk);
+ }
/* Check input frequency */
if ((uartclk < s->chip->freq_min) || (uartclk > s->chip->freq_max)) {
diff --git a/drivers/tty/serial/serial_core.c b/drivers/tty/serial/serial_core.c
index 0f45b7884a2c..f534a40aebde 100644
--- a/drivers/tty/serial/serial_core.c
+++ b/drivers/tty/serial/serial_core.c
@@ -954,11 +954,10 @@ static int uart_set_info(struct tty_struct *tty, struct tty_port *port,
old_custom_divisor != uport->custom_divisor) {
/*
* If they're setting up a custom divisor or speed,
- * instead of clearing it, then bitch about it. No
- * need to rate-limit; it's CAP_SYS_ADMIN only.
+ * instead of clearing it, then bitch about it.
*/
if (uport->flags & UPF_SPD_MASK) {
- dev_notice(uport->dev,
+ dev_notice_ratelimited(uport->dev,
"%s sets custom speed on %s. This is deprecated.\n",
current->comm,
tty_name(port->tty));
@@ -2083,7 +2082,7 @@ int uart_suspend_port(struct uart_driver *drv, struct uart_port *uport)
mutex_lock(&port->mutex);
tty_dev = device_find_child(uport->dev, &match, serial_match_port);
- if (device_may_wakeup(tty_dev)) {
+ if (tty_dev && device_may_wakeup(tty_dev)) {
if (!enable_irq_wake(uport->irq))
uport->irq_wake = 1;
put_device(tty_dev);
@@ -2782,7 +2781,7 @@ int uart_add_one_port(struct uart_driver *drv, struct uart_port *uport)
* Register the port whether it's detected or not. This allows
* setserial to be used to alter this port's parameters.
*/
- tty_dev = tty_port_register_device_attr(port, drv->tty_driver,
+ tty_dev = tty_port_register_device_attr_serdev(port, drv->tty_driver,
uport->line, uport->dev, port, uport->tty_groups);
if (likely(!IS_ERR(tty_dev))) {
device_set_wakeup_capable(tty_dev, 1);
@@ -2845,7 +2844,7 @@ int uart_remove_one_port(struct uart_driver *drv, struct uart_port *uport)
/*
* Remove the devices from the tty layer
*/
- tty_unregister_device(drv->tty_driver, uport->line);
+ tty_port_unregister_device(port, drv->tty_driver, uport->line);
tty = tty_port_tty_get(port);
if (tty) {
diff --git a/drivers/tty/serial/sh-sci.c b/drivers/tty/serial/sh-sci.c
index 71707e8e6e3f..da5ddfc14778 100644
--- a/drivers/tty/serial/sh-sci.c
+++ b/drivers/tty/serial/sh-sci.c
@@ -1450,8 +1450,7 @@ static struct dma_chan *sci_request_dma_chan(struct uart_port *port,
chan = dma_request_slave_channel(port->dev,
dir == DMA_MEM_TO_DEV ? "tx" : "rx");
if (!chan) {
- dev_warn(port->dev,
- "dma_request_slave_channel_compat failed\n");
+ dev_warn(port->dev, "dma_request_slave_channel failed\n");
return NULL;
}
@@ -1558,7 +1557,16 @@ static void sci_free_dma(struct uart_port *port)
if (s->chan_rx)
sci_rx_dma_release(s, false);
}
-#else
+
+static void sci_flush_buffer(struct uart_port *port)
+{
+ /*
+ * In uart_flush_buffer(), the xmit circular buffer has just been
+ * cleared, so we have to reset tx_dma_len accordingly.
+ */
+ to_sci_port(port)->tx_dma_len = 0;
+}
+#else /* !CONFIG_SERIAL_SH_SCI_DMA */
static inline void sci_request_dma(struct uart_port *port)
{
}
@@ -1566,7 +1574,9 @@ static inline void sci_request_dma(struct uart_port *port)
static inline void sci_free_dma(struct uart_port *port)
{
}
-#endif
+
+#define sci_flush_buffer NULL
+#endif /* !CONFIG_SERIAL_SH_SCI_DMA */
static irqreturn_t sci_rx_interrupt(int irq, void *ptr)
{
@@ -2581,6 +2591,7 @@ static const struct uart_ops sci_uart_ops = {
.break_ctl = sci_break_ctl,
.startup = sci_startup,
.shutdown = sci_shutdown,
+ .flush_buffer = sci_flush_buffer,
.set_termios = sci_set_termios,
.pm = sci_pm,
.type = sci_type,
@@ -2950,6 +2961,7 @@ static inline int sci_probe_earlyprintk(struct platform_device *pdev)
static const char banner[] __initconst = "SuperH (H)SCI(F) driver initialized";
+static DEFINE_MUTEX(sci_uart_registration_lock);
static struct uart_driver sci_uart_driver = {
.owner = THIS_MODULE,
.driver_name = "sci",
@@ -3078,6 +3090,16 @@ static int sci_probe_single(struct platform_device *dev,
return -EINVAL;
}
+ mutex_lock(&sci_uart_registration_lock);
+ if (!sci_uart_driver.state) {
+ ret = uart_register_driver(&sci_uart_driver);
+ if (ret) {
+ mutex_unlock(&sci_uart_registration_lock);
+ return ret;
+ }
+ }
+ mutex_unlock(&sci_uart_registration_lock);
+
ret = sci_init_single(dev, sciport, index, p, false);
if (ret)
return ret;
@@ -3201,24 +3223,17 @@ static struct platform_driver sci_driver = {
static int __init sci_init(void)
{
- int ret;
-
pr_info("%s\n", banner);
- ret = uart_register_driver(&sci_uart_driver);
- if (likely(ret == 0)) {
- ret = platform_driver_register(&sci_driver);
- if (unlikely(ret))
- uart_unregister_driver(&sci_uart_driver);
- }
-
- return ret;
+ return platform_driver_register(&sci_driver);
}
static void __exit sci_exit(void)
{
platform_driver_unregister(&sci_driver);
- uart_unregister_driver(&sci_uart_driver);
+
+ if (sci_uart_driver.state)
+ uart_unregister_driver(&sci_uart_driver);
}
#ifdef CONFIG_SERIAL_SH_SCI_CONSOLE
diff --git a/drivers/tty/serial/sirfsoc_uart.c b/drivers/tty/serial/sirfsoc_uart.c
index e03282d92b59..684cb8dd8050 100644
--- a/drivers/tty/serial/sirfsoc_uart.c
+++ b/drivers/tty/serial/sirfsoc_uart.c
@@ -1253,7 +1253,7 @@ next_hrt:
return HRTIMER_RESTART;
}
-static struct of_device_id sirfsoc_uart_ids[] = {
+static const struct of_device_id sirfsoc_uart_ids[] = {
{ .compatible = "sirf,prima2-uart", .data = &sirfsoc_uart,},
{ .compatible = "sirf,atlas7-uart", .data = &sirfsoc_uart},
{ .compatible = "sirf,prima2-usp-uart", .data = &sirfsoc_usp},
diff --git a/drivers/tty/serial/xilinx_uartps.c b/drivers/tty/serial/xilinx_uartps.c
index c0539950f8d7..fde55dcdea5a 100644
--- a/drivers/tty/serial/xilinx_uartps.c
+++ b/drivers/tty/serial/xilinx_uartps.c
@@ -186,6 +186,7 @@ MODULE_PARM_DESC(rx_timeout, "Rx timeout, 1-255");
* @pclk: APB clock
* @baud: Current baud rate
* @clk_rate_change_nb: Notifier block for clock changes
+ * @quirks: Flags for RXBS support.
*/
struct cdns_uart {
struct uart_port *port;
@@ -1587,20 +1588,21 @@ static int cdns_uart_probe(struct platform_device *pdev)
if (rc) {
dev_err(&pdev->dev,
"uart_add_one_port() failed; err=%i\n", rc);
- goto err_out_notif_unreg;
+ goto err_out_pm_disable;
}
return 0;
+err_out_pm_disable:
+ pm_runtime_disable(&pdev->dev);
+ pm_runtime_set_suspended(&pdev->dev);
+ pm_runtime_dont_use_autosuspend(&pdev->dev);
err_out_notif_unreg:
#ifdef CONFIG_COMMON_CLK
clk_notifier_unregister(cdns_uart_data->uartclk,
&cdns_uart_data->clk_rate_change_nb);
#endif
err_out_clk_disable:
- pm_runtime_disable(&pdev->dev);
- pm_runtime_set_suspended(&pdev->dev);
- pm_runtime_dont_use_autosuspend(&pdev->dev);
clk_disable_unprepare(cdns_uart_data->uartclk);
err_out_clk_dis_pclk:
clk_disable_unprepare(cdns_uart_data->pclk);
diff --git a/drivers/tty/synclink_gt.c b/drivers/tty/synclink_gt.c
index 31885f20fc15..cc047de72e2a 100644
--- a/drivers/tty/synclink_gt.c
+++ b/drivers/tty/synclink_gt.c
@@ -184,7 +184,7 @@ static void hdlcdev_exit(struct slgt_info *info);
struct cond_wait {
struct cond_wait *next;
wait_queue_head_t q;
- wait_queue_t wait;
+ wait_queue_entry_t wait;
unsigned int data;
};
static void init_cond_wait(struct cond_wait *w, unsigned int data);
diff --git a/drivers/tty/tty_io.c b/drivers/tty/tty_io.c
index 0c150b5a9dd6..974b13d24401 100644
--- a/drivers/tty/tty_io.c
+++ b/drivers/tty/tty_io.c
@@ -325,6 +325,56 @@ static struct tty_driver *get_tty_driver(dev_t device, int *index)
return NULL;
}
+/**
+ * tty_dev_name_to_number - return dev_t for device name
+ * @name: user space name of device under /dev
+ * @number: pointer to dev_t that this function will populate
+ *
+ * This function converts device names like ttyS0 or ttyUSB1 into dev_t
+ * like (4, 64) or (188, 1). If no corresponding driver is registered then
+ * the function returns -ENODEV.
+ *
+ * Locking: this acquires tty_mutex to protect the tty_drivers list from
+ * being modified while we are traversing it, and makes sure to
+ * release it before exiting.
+ */
+int tty_dev_name_to_number(const char *name, dev_t *number)
+{
+ struct tty_driver *p;
+ int ret;
+ int index, prefix_length = 0;
+ const char *str;
+
+ for (str = name; *str && !isdigit(*str); str++)
+ ;
+
+ if (!*str)
+ return -EINVAL;
+
+ ret = kstrtoint(str, 10, &index);
+ if (ret)
+ return ret;
+
+ prefix_length = str - name;
+ mutex_lock(&tty_mutex);
+
+ list_for_each_entry(p, &tty_drivers, tty_drivers)
+ if (prefix_length == strlen(p->name) && strncmp(name,
+ p->name, prefix_length) == 0) {
+ if (index < p->num) {
+ *number = MKDEV(p->major, p->minor_start + index);
+ goto out;
+ }
+ }
+
+ /* if here then driver wasn't found */
+ ret = -ENODEV;
+out:
+ mutex_unlock(&tty_mutex);
+ return ret;
+}
+EXPORT_SYMBOL_GPL(tty_dev_name_to_number);
+
#ifdef CONFIG_CONSOLE_POLL
/**
@@ -1083,7 +1133,10 @@ static struct tty_struct *tty_driver_lookup_tty(struct tty_driver *driver,
struct tty_struct *tty;
if (driver->ops->lookup)
- tty = driver->ops->lookup(driver, file, idx);
+ if (!file)
+ tty = ERR_PTR(-EIO);
+ else
+ tty = driver->ops->lookup(driver, file, idx);
else
tty = driver->ttys[idx];
@@ -1715,7 +1768,7 @@ static struct tty_driver *tty_lookup_driver(dev_t device, struct file *filp,
struct tty_driver *console_driver = console_device(index);
if (console_driver) {
driver = tty_driver_kref_get(console_driver);
- if (driver) {
+ if (driver && filp) {
/* Don't let /dev/console block */
filp->f_flags |= O_NONBLOCK;
break;
@@ -1748,7 +1801,7 @@ static struct tty_driver *tty_lookup_driver(dev_t device, struct file *filp,
* - concurrent tty driver removal w/ lookup
* - concurrent tty removal from driver table
*/
-static struct tty_struct *tty_open_by_driver(dev_t device, struct inode *inode,
+struct tty_struct *tty_open_by_driver(dev_t device, struct inode *inode,
struct file *filp)
{
struct tty_struct *tty;
@@ -1793,6 +1846,7 @@ out:
tty_driver_kref_put(driver);
return tty;
}
+EXPORT_SYMBOL_GPL(tty_open_by_driver);
/**
* tty_open - open a tty device
diff --git a/drivers/tty/tty_ldisc.c b/drivers/tty/tty_ldisc.c
index e4603b09863a..2fe216b276e2 100644
--- a/drivers/tty/tty_ldisc.c
+++ b/drivers/tty/tty_ldisc.c
@@ -492,6 +492,29 @@ static void tty_ldisc_close(struct tty_struct *tty, struct tty_ldisc *ld)
}
/**
+ * tty_ldisc_failto - helper for ldisc failback
+ * @tty: tty to open the ldisc on
+ * @ld: ldisc we are trying to fail back to
+ *
+ * Helper to try and recover a tty when switching back to the old
+ * ldisc fails and we need something attached.
+ */
+
+static int tty_ldisc_failto(struct tty_struct *tty, int ld)
+{
+ struct tty_ldisc *disc = tty_ldisc_get(tty, ld);
+ int r;
+
+ if (IS_ERR(disc))
+ return PTR_ERR(disc);
+ tty->ldisc = disc;
+ tty_set_termios_ldisc(tty, ld);
+ if ((r = tty_ldisc_open(tty, disc)) < 0)
+ tty_ldisc_put(disc);
+ return r;
+}
+
+/**
* tty_ldisc_restore - helper for tty ldisc change
* @tty: tty to recover
* @old: previous ldisc
@@ -502,9 +525,6 @@ static void tty_ldisc_close(struct tty_struct *tty, struct tty_ldisc *ld)
static void tty_ldisc_restore(struct tty_struct *tty, struct tty_ldisc *old)
{
- struct tty_ldisc *new_ldisc;
- int r;
-
/* There is an outstanding reference here so this is safe */
old = tty_ldisc_get(tty, old->ops->num);
WARN_ON(IS_ERR(old));
@@ -512,17 +532,13 @@ static void tty_ldisc_restore(struct tty_struct *tty, struct tty_ldisc *old)
tty_set_termios_ldisc(tty, old->ops->num);
if (tty_ldisc_open(tty, old) < 0) {
tty_ldisc_put(old);
- /* This driver is always present */
- new_ldisc = tty_ldisc_get(tty, N_TTY);
- if (IS_ERR(new_ldisc))
- panic("n_tty: get");
- tty->ldisc = new_ldisc;
- tty_set_termios_ldisc(tty, N_TTY);
- r = tty_ldisc_open(tty, new_ldisc);
- if (r < 0)
- panic("Couldn't open N_TTY ldisc for "
- "%s --- error %d.",
- tty_name(tty), r);
+ /* The traditional behaviour is to fall back to N_TTY, we
+ want to avoid falling back to N_NULL unless we have no
+ choice to avoid the risk of breaking anything */
+ if (tty_ldisc_failto(tty, N_TTY) < 0 &&
+ tty_ldisc_failto(tty, N_NULL) < 0)
+ panic("Couldn't open N_NULL ldisc for %s.",
+ tty_name(tty));
}
}
@@ -605,6 +621,7 @@ err:
tty_unlock(tty);
return retval;
}
+EXPORT_SYMBOL_GPL(tty_set_ldisc);
/**
* tty_ldisc_kill - teardown ldisc
@@ -797,6 +814,7 @@ void tty_ldisc_release(struct tty_struct *tty)
tty_ldisc_debug(tty, "released\n");
}
+EXPORT_SYMBOL_GPL(tty_ldisc_release);
/**
* tty_ldisc_init - ldisc setup for new tty
diff --git a/drivers/tty/tty_port.c b/drivers/tty/tty_port.c
index 1d21a9c1d33e..6b137194069f 100644
--- a/drivers/tty/tty_port.c
+++ b/drivers/tty/tty_port.c
@@ -129,19 +129,85 @@ struct device *tty_port_register_device_attr(struct tty_port *port,
struct device *device, void *drvdata,
const struct attribute_group **attr_grp)
{
+ tty_port_link_device(port, driver, index);
+ return tty_register_device_attr(driver, index, device, drvdata,
+ attr_grp);
+}
+EXPORT_SYMBOL_GPL(tty_port_register_device_attr);
+
+/**
+ * tty_port_register_device_attr_serdev - register tty or serdev device
+ * @port: tty_port of the device
+ * @driver: tty_driver for this device
+ * @index: index of the tty
+ * @device: parent if exists, otherwise NULL
+ * @drvdata: driver data for the device
+ * @attr_grp: attribute group for the device
+ *
+ * Register a serdev or tty device depending on if the parent device has any
+ * defined serdev clients or not.
+ */
+struct device *tty_port_register_device_attr_serdev(struct tty_port *port,
+ struct tty_driver *driver, unsigned index,
+ struct device *device, void *drvdata,
+ const struct attribute_group **attr_grp)
+{
struct device *dev;
tty_port_link_device(port, driver, index);
dev = serdev_tty_port_register(port, device, driver, index);
- if (PTR_ERR(dev) != -ENODEV)
+ if (PTR_ERR(dev) != -ENODEV) {
/* Skip creating cdev if we registered a serdev device */
return dev;
+ }
return tty_register_device_attr(driver, index, device, drvdata,
attr_grp);
}
-EXPORT_SYMBOL_GPL(tty_port_register_device_attr);
+EXPORT_SYMBOL_GPL(tty_port_register_device_attr_serdev);
+
+/**
+ * tty_port_register_device_serdev - register tty or serdev device
+ * @port: tty_port of the device
+ * @driver: tty_driver for this device
+ * @index: index of the tty
+ * @device: parent if exists, otherwise NULL
+ *
+ * Register a serdev or tty device depending on if the parent device has any
+ * defined serdev clients or not.
+ */
+struct device *tty_port_register_device_serdev(struct tty_port *port,
+ struct tty_driver *driver, unsigned index,
+ struct device *device)
+{
+ return tty_port_register_device_attr_serdev(port, driver, index,
+ device, NULL, NULL);
+}
+EXPORT_SYMBOL_GPL(tty_port_register_device_serdev);
+
+/**
+ * tty_port_unregister_device - deregister a tty or serdev device
+ * @port: tty_port of the device
+ * @driver: tty_driver for this device
+ * @index: index of the tty
+ *
+ * If a tty or serdev device is registered with a call to
+ * tty_port_register_device_serdev() then this function must be called when
+ * the device is gone.
+ */
+void tty_port_unregister_device(struct tty_port *port,
+ struct tty_driver *driver, unsigned index)
+{
+ int ret;
+
+ ret = serdev_tty_port_unregister(port);
+ if (ret == 0)
+ return;
+
+ tty_unregister_device(driver, index);
+}
+EXPORT_SYMBOL_GPL(tty_port_unregister_device);
int tty_port_alloc_xmit_buf(struct tty_port *port)
{
@@ -189,9 +255,6 @@ static void tty_port_destructor(struct kref *kref)
/* check if last port ref was dropped before tty release */
if (WARN_ON(port->itty))
return;
-
- serdev_tty_port_unregister(port);
-
if (port->xmit_buf)
free_page((unsigned long)port->xmit_buf);
tty_port_destroy(port);
diff --git a/drivers/tty/vt/consolemap.c b/drivers/tty/vt/consolemap.c
index 1f6e17fc3fb0..a5f88cf0f61d 100644
--- a/drivers/tty/vt/consolemap.c
+++ b/drivers/tty/vt/consolemap.c
@@ -322,15 +322,13 @@ int con_set_trans_old(unsigned char __user * arg)
{
int i;
unsigned short inbuf[E_TABSZ];
+ unsigned char ubuf[E_TABSZ];
- if (!access_ok(VERIFY_READ, arg, E_TABSZ))
+ if (copy_from_user(ubuf, arg, E_TABSZ))
return -EFAULT;
- for (i = 0; i < E_TABSZ ; i++) {
- unsigned char uc;
- __get_user(uc, arg+i);
- inbuf[i] = UNI_DIRECT_BASE | uc;
- }
+ for (i = 0; i < E_TABSZ ; i++)
+ inbuf[i] = UNI_DIRECT_BASE | ubuf[i];
console_lock();
memcpy(translations[USER_MAP], inbuf, sizeof(inbuf));
@@ -345,9 +343,6 @@ int con_get_trans_old(unsigned char __user * arg)
unsigned short *p = translations[USER_MAP];
unsigned char outbuf[E_TABSZ];
- if (!access_ok(VERIFY_WRITE, arg, E_TABSZ))
- return -EFAULT;
-
console_lock();
for (i = 0; i < E_TABSZ ; i++)
{
@@ -356,22 +351,16 @@ int con_get_trans_old(unsigned char __user * arg)
}
console_unlock();
- for (i = 0; i < E_TABSZ ; i++)
- __put_user(outbuf[i], arg+i);
- return 0;
+ return copy_to_user(arg, outbuf, sizeof(outbuf)) ? -EFAULT : 0;
}
int con_set_trans_new(ushort __user * arg)
{
- int i;
unsigned short inbuf[E_TABSZ];
- if (!access_ok(VERIFY_READ, arg, E_TABSZ*sizeof(unsigned short)))
+ if (copy_from_user(inbuf, arg, sizeof(inbuf)))
return -EFAULT;
- for (i = 0; i < E_TABSZ ; i++)
- __get_user(inbuf[i], arg+i);
-
console_lock();
memcpy(translations[USER_MAP], inbuf, sizeof(inbuf));
update_user_maps();
@@ -381,19 +370,13 @@ int con_set_trans_new(ushort __user * arg)
int con_get_trans_new(ushort __user * arg)
{
- int i;
unsigned short outbuf[E_TABSZ];
- if (!access_ok(VERIFY_WRITE, arg, E_TABSZ*sizeof(unsigned short)))
- return -EFAULT;
-
console_lock();
memcpy(outbuf, translations[USER_MAP], sizeof(outbuf));
console_unlock();
- for (i = 0; i < E_TABSZ ; i++)
- __put_user(outbuf[i], arg+i);
- return 0;
+ return copy_to_user(arg, outbuf, sizeof(outbuf)) ? -EFAULT : 0;
}
/*
@@ -557,14 +540,9 @@ int con_set_unimap(struct vc_data *vc, ushort ct, struct unipair __user *list)
if (!ct)
return 0;
- unilist = kmalloc_array(ct, sizeof(struct unipair), GFP_KERNEL);
- if (!unilist)
- return -ENOMEM;
-
- for (i = ct, plist = unilist; i; i--, plist++, list++) {
- __get_user(plist->unicode, &list->unicode);
- __get_user(plist->fontpos, &list->fontpos);
- }
+ unilist = memdup_user(list, ct * sizeof(struct unipair));
+ if (IS_ERR(unilist))
+ return PTR_ERR(unilist);
console_lock();
@@ -757,11 +735,11 @@ EXPORT_SYMBOL(con_copy_unimap);
*/
int con_get_unimap(struct vc_data *vc, ushort ct, ushort __user *uct, struct unipair __user *list)
{
- int i, j, k;
+ int i, j, k, ret = 0;
ushort ect;
u16 **p1, *p2;
struct uni_pagedir *p;
- struct unipair *unilist, *plist;
+ struct unipair *unilist;
unilist = kmalloc_array(ct, sizeof(struct unipair), GFP_KERNEL);
if (!unilist)
@@ -792,13 +770,11 @@ int con_get_unimap(struct vc_data *vc, ushort ct, ushort __user *uct, struct uni
}
}
console_unlock();
- for (i = min(ect, ct), plist = unilist; i; i--, list++, plist++) {
- __put_user(plist->unicode, &list->unicode);
- __put_user(plist->fontpos, &list->fontpos);
- }
- __put_user(ect, uct);
+ if (copy_to_user(list, unilist, min(ect, ct) * sizeof(struct unipair)))
+ ret = -EFAULT;
+ put_user(ect, uct);
kfree(unilist);
- return ((ect <= ct) ? 0 : -ENOMEM);
+ return ret ? ret : (ect <= ct) ? 0 : -ENOMEM;
}
/*
diff --git a/drivers/tty/vt/keyboard.c b/drivers/tty/vt/keyboard.c
index 8af8d9542663..f4166263bb3a 100644
--- a/drivers/tty/vt/keyboard.c
+++ b/drivers/tty/vt/keyboard.c
@@ -1203,8 +1203,7 @@ DECLARE_TASKLET_DISABLED(keyboard_tasklet, kbd_bh, 0);
#if defined(CONFIG_X86) || defined(CONFIG_IA64) || defined(CONFIG_ALPHA) ||\
defined(CONFIG_MIPS) || defined(CONFIG_PPC) || defined(CONFIG_SPARC) ||\
defined(CONFIG_PARISC) || defined(CONFIG_SUPERH) ||\
- (defined(CONFIG_ARM) && defined(CONFIG_KEYBOARD_ATKBD) && !defined(CONFIG_ARCH_RPC)) ||\
- defined(CONFIG_AVR32)
+ (defined(CONFIG_ARM) && defined(CONFIG_KEYBOARD_ATKBD) && !defined(CONFIG_ARCH_RPC))
#define HW_RAW(dev) (test_bit(EV_MSC, dev->evbit) && test_bit(MSC_RAW, dev->mscbit) &&\
((dev)->id.bustype == BUS_I8042) && ((dev)->id.vendor == 0x0001) && ((dev)->id.product == 0x0001))
diff --git a/drivers/tty/vt/vt.c b/drivers/tty/vt/vt.c
index 9c9945284bcf..2ebaba16f785 100644
--- a/drivers/tty/vt/vt.c
+++ b/drivers/tty/vt/vt.c
@@ -425,7 +425,7 @@ static u8 build_attr(struct vc_data *vc, u8 _color, u8 _intensity, u8 _blink,
else if (_underline)
a = (a & 0xf0) | vc->vc_ulcolor;
else if (_intensity == 0)
- a = (a & 0xf0) | vc->vc_ulcolor;
+ a = (a & 0xf0) | vc->vc_halfcolor;
if (_reverse)
a = ((a) & 0x88) | ((((a) >> 4) | ((a) << 4)) & 0x77);
if (_blink)
@@ -2709,13 +2709,13 @@ int tioclinux(struct tty_struct *tty, unsigned long arg)
* related to the kernel should not use this.
*/
data = vt_get_shift_state();
- ret = __put_user(data, p);
+ ret = put_user(data, p);
break;
case TIOCL_GETMOUSEREPORTING:
console_lock(); /* May be overkill */
data = mouse_reporting();
console_unlock();
- ret = __put_user(data, p);
+ ret = put_user(data, p);
break;
case TIOCL_SETVESABLANK:
console_lock();
@@ -2724,7 +2724,7 @@ int tioclinux(struct tty_struct *tty, unsigned long arg)
break;
case TIOCL_GETKMSGREDIRECT:
data = vt_get_kmsg_redirect();
- ret = __put_user(data, p);
+ ret = put_user(data, p);
break;
case TIOCL_SETKMSGREDIRECT:
if (!capable(CAP_SYS_ADMIN)) {
diff --git a/drivers/tty/vt/vt_ioctl.c b/drivers/tty/vt/vt_ioctl.c
index 0cbfe1ff6f6c..96d389cb506c 100644
--- a/drivers/tty/vt/vt_ioctl.c
+++ b/drivers/tty/vt/vt_ioctl.c
@@ -266,10 +266,6 @@ do_unimap_ioctl(int cmd, struct unimapdesc __user *user_ud, int perm, struct vc_
if (copy_from_user(&tmp, user_ud, sizeof tmp))
return -EFAULT;
- if (tmp.entries)
- if (!access_ok(VERIFY_WRITE, tmp.entries,
- tmp.entry_ct*sizeof(struct unipair)))
- return -EFAULT;
switch (cmd) {
case PIO_UNIMAP:
if (!perm)
@@ -1170,10 +1166,6 @@ compat_unimap_ioctl(unsigned int cmd, struct compat_unimapdesc __user *user_ud,
if (copy_from_user(&tmp, user_ud, sizeof tmp))
return -EFAULT;
tmp_entries = compat_ptr(tmp.entries);
- if (tmp_entries)
- if (!access_ok(VERIFY_WRITE, tmp_entries,
- tmp.entry_ct*sizeof(struct unipair)))
- return -EFAULT;
switch (cmd) {
case PIO_UNIMAP:
if (!perm)
diff --git a/drivers/usb/chipidea/core.c b/drivers/usb/chipidea/core.c
index 9e217b1361ea..b17ed3a9a304 100644
--- a/drivers/usb/chipidea/core.c
+++ b/drivers/usb/chipidea/core.c
@@ -818,7 +818,7 @@ static inline void ci_role_destroy(struct ci_hdrc *ci)
{
ci_hdrc_gadget_destroy(ci);
ci_hdrc_host_destroy(ci);
- if (ci->is_otg)
+ if (ci->is_otg && ci->roles[CI_ROLE_GADGET])
ci_hdrc_otg_destroy(ci);
}
@@ -843,7 +843,10 @@ static ssize_t ci_role_show(struct device *dev, struct device_attribute *attr,
{
struct ci_hdrc *ci = dev_get_drvdata(dev);
- return sprintf(buf, "%s\n", ci_role(ci)->name);
+ if (ci->role != CI_ROLE_END)
+ return sprintf(buf, "%s\n", ci_role(ci)->name);
+
+ return 0;
}
static ssize_t ci_role_store(struct device *dev,
@@ -977,27 +980,35 @@ static int ci_hdrc_probe(struct platform_device *pdev)
/* initialize role(s) before the interrupt is requested */
if (dr_mode == USB_DR_MODE_OTG || dr_mode == USB_DR_MODE_HOST) {
ret = ci_hdrc_host_init(ci);
- if (ret)
- dev_info(dev, "doesn't support host\n");
+ if (ret) {
+ if (ret == -ENXIO)
+ dev_info(dev, "doesn't support host\n");
+ else
+ goto deinit_phy;
+ }
}
if (dr_mode == USB_DR_MODE_OTG || dr_mode == USB_DR_MODE_PERIPHERAL) {
ret = ci_hdrc_gadget_init(ci);
- if (ret)
- dev_info(dev, "doesn't support gadget\n");
+ if (ret) {
+ if (ret == -ENXIO)
+ dev_info(dev, "doesn't support gadget\n");
+ else
+ goto deinit_host;
+ }
}
if (!ci->roles[CI_ROLE_HOST] && !ci->roles[CI_ROLE_GADGET]) {
dev_err(dev, "no supported roles\n");
ret = -ENODEV;
- goto deinit_phy;
+ goto deinit_gadget;
}
if (ci->is_otg && ci->roles[CI_ROLE_GADGET]) {
ret = ci_hdrc_otg_init(ci);
if (ret) {
dev_err(dev, "init otg fails, ret = %d\n", ret);
- goto stop;
+ goto deinit_gadget;
}
}
@@ -1067,7 +1078,12 @@ static int ci_hdrc_probe(struct platform_device *pdev)
remove_debug:
dbg_remove_files(ci);
stop:
- ci_role_destroy(ci);
+ if (ci->is_otg && ci->roles[CI_ROLE_GADGET])
+ ci_hdrc_otg_destroy(ci);
+deinit_gadget:
+ ci_hdrc_gadget_destroy(ci);
+deinit_host:
+ ci_hdrc_host_destroy(ci);
deinit_phy:
ci_usb_phy_exit(ci);
ulpi_exit:
diff --git a/drivers/usb/chipidea/debug.c b/drivers/usb/chipidea/debug.c
index 6d23eede4d8c..1c31e8a08810 100644
--- a/drivers/usb/chipidea/debug.c
+++ b/drivers/usb/chipidea/debug.c
@@ -294,7 +294,8 @@ static int ci_role_show(struct seq_file *s, void *data)
{
struct ci_hdrc *ci = s->private;
- seq_printf(s, "%s\n", ci_role(ci)->name);
+ if (ci->role != CI_ROLE_END)
+ seq_printf(s, "%s\n", ci_role(ci)->name);
return 0;
}
diff --git a/drivers/usb/chipidea/otg_fsm.c b/drivers/usb/chipidea/otg_fsm.c
index 93e24ce61a3a..949183ede16f 100644
--- a/drivers/usb/chipidea/otg_fsm.c
+++ b/drivers/usb/chipidea/otg_fsm.c
@@ -234,7 +234,7 @@ static void ci_otg_add_timer(struct ci_hdrc *ci, enum otg_fsm_timer t)
ktime_set(timer_sec, timer_nsec));
ci->enabled_otg_timer_bits |= (1 << t);
if ((ci->next_otg_timer == NUM_OTG_FSM_TIMERS) ||
- (ci->hr_timeouts[ci->next_otg_timer] >
+ ktime_after(ci->hr_timeouts[ci->next_otg_timer],
ci->hr_timeouts[t])) {
ci->next_otg_timer = t;
hrtimer_start_range_ns(&ci->otg_fsm_hrtimer,
@@ -269,7 +269,7 @@ static void ci_otg_del_timer(struct ci_hdrc *ci, enum otg_fsm_timer t)
for_each_set_bit(cur_timer, &enabled_timer_bits,
NUM_OTG_FSM_TIMERS) {
if ((next_timer == NUM_OTG_FSM_TIMERS) ||
- (ci->hr_timeouts[next_timer] <
+ ktime_before(ci->hr_timeouts[next_timer],
ci->hr_timeouts[cur_timer]))
next_timer = cur_timer;
}
@@ -397,13 +397,13 @@ static enum hrtimer_restart ci_otg_hrtimer_func(struct hrtimer *t)
now = ktime_get();
for_each_set_bit(cur_timer, &enabled_timer_bits, NUM_OTG_FSM_TIMERS) {
- if (now >= ci->hr_timeouts[cur_timer]) {
+ if (ktime_compare(now, ci->hr_timeouts[cur_timer]) >= 0) {
ci->enabled_otg_timer_bits &= ~(1 << cur_timer);
if (otg_timer_handlers[cur_timer])
ret = otg_timer_handlers[cur_timer](ci);
} else {
if ((next_timer == NUM_OTG_FSM_TIMERS) ||
- (ci->hr_timeouts[cur_timer] <
+ ktime_before(ci->hr_timeouts[cur_timer],
ci->hr_timeouts[next_timer]))
next_timer = cur_timer;
}
diff --git a/drivers/usb/chipidea/udc.c b/drivers/usb/chipidea/udc.c
index 56d2d3213076..d68b125796f9 100644
--- a/drivers/usb/chipidea/udc.c
+++ b/drivers/usb/chipidea/udc.c
@@ -1993,6 +1993,7 @@ static void udc_id_switch_for_host(struct ci_hdrc *ci)
int ci_hdrc_gadget_init(struct ci_hdrc *ci)
{
struct ci_role_driver *rdrv;
+ int ret;
if (!hw_read(ci, CAP_DCCPARAMS, DCCPARAMS_DC))
return -ENXIO;
@@ -2005,7 +2006,10 @@ int ci_hdrc_gadget_init(struct ci_hdrc *ci)
rdrv->stop = udc_id_switch_for_host;
rdrv->irq = udc_irq;
rdrv->name = "gadget";
- ci->roles[CI_ROLE_GADGET] = rdrv;
- return udc_start(ci);
+ ret = udc_start(ci);
+ if (!ret)
+ ci->roles[CI_ROLE_GADGET] = rdrv;
+
+ return ret;
}
diff --git a/drivers/usb/chipidea/usbmisc_imx.c b/drivers/usb/chipidea/usbmisc_imx.c
index e77a4ed4f021..9f4a0185dd60 100644
--- a/drivers/usb/chipidea/usbmisc_imx.c
+++ b/drivers/usb/chipidea/usbmisc_imx.c
@@ -108,6 +108,8 @@ struct imx_usbmisc {
const struct usbmisc_ops *ops;
};
+static inline bool is_imx53_usbmisc(struct imx_usbmisc_data *data);
+
static int usbmisc_imx25_init(struct imx_usbmisc_data *data)
{
struct imx_usbmisc *usbmisc = dev_get_drvdata(data->dev);
@@ -242,10 +244,15 @@ static int usbmisc_imx53_init(struct imx_usbmisc_data *data)
val = readl(reg) | MX53_USB_UHx_CTRL_WAKE_UP_EN
| MX53_USB_UHx_CTRL_ULPI_INT_EN;
writel(val, reg);
- /* Disable internal 60Mhz clock */
- reg = usbmisc->base + MX53_USB_CLKONOFF_CTRL_OFFSET;
- val = readl(reg) | MX53_USB_CLKONOFF_CTRL_H2_INT60CKOFF;
- writel(val, reg);
+ if (is_imx53_usbmisc(data)) {
+ /* Disable internal 60Mhz clock */
+ reg = usbmisc->base +
+ MX53_USB_CLKONOFF_CTRL_OFFSET;
+ val = readl(reg) |
+ MX53_USB_CLKONOFF_CTRL_H2_INT60CKOFF;
+ writel(val, reg);
+ }
+
}
if (data->disable_oc) {
reg = usbmisc->base + MX53_USB_UH2_CTRL_OFFSET;
@@ -267,10 +274,15 @@ static int usbmisc_imx53_init(struct imx_usbmisc_data *data)
val = readl(reg) | MX53_USB_UHx_CTRL_WAKE_UP_EN
| MX53_USB_UHx_CTRL_ULPI_INT_EN;
writel(val, reg);
- /* Disable internal 60Mhz clock */
- reg = usbmisc->base + MX53_USB_CLKONOFF_CTRL_OFFSET;
- val = readl(reg) | MX53_USB_CLKONOFF_CTRL_H3_INT60CKOFF;
- writel(val, reg);
+
+ if (is_imx53_usbmisc(data)) {
+ /* Disable internal 60Mhz clock */
+ reg = usbmisc->base +
+ MX53_USB_CLKONOFF_CTRL_OFFSET;
+ val = readl(reg) |
+ MX53_USB_CLKONOFF_CTRL_H3_INT60CKOFF;
+ writel(val, reg);
+ }
}
if (data->disable_oc) {
reg = usbmisc->base + MX53_USB_UH3_CTRL_OFFSET;
@@ -456,6 +468,10 @@ static const struct usbmisc_ops imx27_usbmisc_ops = {
.init = usbmisc_imx27_init,
};
+static const struct usbmisc_ops imx51_usbmisc_ops = {
+ .init = usbmisc_imx53_init,
+};
+
static const struct usbmisc_ops imx53_usbmisc_ops = {
.init = usbmisc_imx53_init,
};
@@ -479,6 +495,13 @@ static const struct usbmisc_ops imx7d_usbmisc_ops = {
.set_wakeup = usbmisc_imx7d_set_wakeup,
};
+static inline bool is_imx53_usbmisc(struct imx_usbmisc_data *data)
+{
+ struct imx_usbmisc *usbmisc = dev_get_drvdata(data->dev);
+
+ return usbmisc->ops == &imx53_usbmisc_ops;
+}
+
int imx_usbmisc_init(struct imx_usbmisc_data *data)
{
struct imx_usbmisc *usbmisc;
@@ -536,7 +559,7 @@ static const struct of_device_id usbmisc_imx_dt_ids[] = {
},
{
.compatible = "fsl,imx51-usbmisc",
- .data = &imx53_usbmisc_ops,
+ .data = &imx51_usbmisc_ops,
},
{
.compatible = "fsl,imx53-usbmisc",
diff --git a/drivers/usb/class/cdc-wdm.c b/drivers/usb/class/cdc-wdm.c
index 08669fee6d7f..8f972247b1c1 100644
--- a/drivers/usb/class/cdc-wdm.c
+++ b/drivers/usb/class/cdc-wdm.c
@@ -361,17 +361,9 @@ static ssize_t wdm_write
if (we < 0)
return usb_translate_errors(we);
- buf = kmalloc(count, GFP_KERNEL);
- if (!buf) {
- rv = -ENOMEM;
- goto outnl;
- }
-
- r = copy_from_user(buf, buffer, count);
- if (r > 0) {
- rv = -EFAULT;
- goto out_free_mem;
- }
+ buf = memdup_user(buffer, count);
+ if (IS_ERR(buf))
+ return PTR_ERR(buf);
/* concurrent writes and disconnect */
r = mutex_lock_interruptible(&desc->wlock);
@@ -441,8 +433,7 @@ static ssize_t wdm_write
usb_autopm_put_interface(desc->intf);
mutex_unlock(&desc->wlock);
-outnl:
- return rv < 0 ? rv : count;
+ return count;
out_free_mem_pm:
usb_autopm_put_interface(desc->intf);
diff --git a/drivers/usb/core/devio.c b/drivers/usb/core/devio.c
index 8e6ef671be9b..0e7d0e81a7cb 100644
--- a/drivers/usb/core/devio.c
+++ b/drivers/usb/core/devio.c
@@ -2537,6 +2537,9 @@ static long usbdev_do_ioctl(struct file *file, unsigned int cmd,
case USBDEVFS_DROP_PRIVILEGES:
ret = proc_drop_privileges(ps, p);
break;
+ case USBDEVFS_GET_SPEED:
+ ret = ps->dev->speed;
+ break;
}
done:
diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c
index 5dea98358c05..ab1bb3b538ac 100644
--- a/drivers/usb/core/hcd.c
+++ b/drivers/usb/core/hcd.c
@@ -26,6 +26,7 @@
#include <linux/module.h>
#include <linux/version.h>
#include <linux/kernel.h>
+#include <linux/sched/task_stack.h>
#include <linux/slab.h>
#include <linux/completion.h>
#include <linux/utsname.h>
@@ -1076,7 +1077,6 @@ static void usb_deregister_bus (struct usb_bus *bus)
static int register_root_hub(struct usb_hcd *hcd)
{
struct device *parent_dev = hcd->self.controller;
- struct device *sysdev = hcd->self.sysdev;
struct usb_device *usb_dev = hcd->self.root_hub;
const int devnum = 1;
int retval;
@@ -1123,7 +1123,6 @@ static int register_root_hub(struct usb_hcd *hcd)
/* Did the HC die before the root hub was registered? */
if (HCD_DEAD(hcd))
usb_hc_died (hcd); /* This time clean up */
- usb_dev->dev.of_node = sysdev->of_node;
}
mutex_unlock(&usb_bus_idr_lock);
@@ -1523,6 +1522,14 @@ int usb_hcd_map_urb_for_dma(struct usb_hcd *hcd, struct urb *urb,
if (hcd->self.uses_pio_for_control)
return ret;
if (IS_ENABLED(CONFIG_HAS_DMA) && hcd->self.uses_dma) {
+ if (is_vmalloc_addr(urb->setup_packet)) {
+ WARN_ONCE(1, "setup packet is not dma capable\n");
+ return -EAGAIN;
+ } else if (object_is_on_stack(urb->setup_packet)) {
+ WARN_ONCE(1, "setup packet is on stack\n");
+ return -EAGAIN;
+ }
+
urb->setup_dma = dma_map_single(
hcd->self.sysdev,
urb->setup_packet,
@@ -1587,6 +1594,9 @@ int usb_hcd_map_urb_for_dma(struct usb_hcd *hcd, struct urb *urb,
} else if (is_vmalloc_addr(urb->transfer_buffer)) {
WARN_ONCE(1, "transfer buffer not dma capable\n");
ret = -EAGAIN;
+ } else if (object_is_on_stack(urb->transfer_buffer)) {
+ WARN_ONCE(1, "transfer buffer is on stack\n");
+ ret = -EAGAIN;
} else {
urb->transfer_dma = dma_map_single(
hcd->self.sysdev,
diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
index b8bb20d7acdb..6e6797d145dd 100644
--- a/drivers/usb/core/hub.c
+++ b/drivers/usb/core/hub.c
@@ -1661,10 +1661,28 @@ static void hub_disconnect(struct usb_interface *intf)
kref_put(&hub->kref, hub_release);
}
+static bool hub_descriptor_is_sane(struct usb_host_interface *desc)
+{
+ /* Some hubs have a subclass of 1, which AFAICT according to the */
+ /* specs is not defined, but it works */
+ if (desc->desc.bInterfaceSubClass != 0 &&
+ desc->desc.bInterfaceSubClass != 1)
+ return false;
+
+ /* Multiple endpoints? What kind of mutant ninja-hub is this? */
+ if (desc->desc.bNumEndpoints != 1)
+ return false;
+
+ /* If the first endpoint is not interrupt IN, we'd better punt! */
+ if (!usb_endpoint_is_int_in(&desc->endpoint[0].desc))
+ return false;
+
+ return true;
+}
+
static int hub_probe(struct usb_interface *intf, const struct usb_device_id *id)
{
struct usb_host_interface *desc;
- struct usb_endpoint_descriptor *endpoint;
struct usb_device *hdev;
struct usb_hub *hub;
@@ -1739,25 +1757,11 @@ static int hub_probe(struct usb_interface *intf, const struct usb_device_id *id)
}
#endif
- /* Some hubs have a subclass of 1, which AFAICT according to the */
- /* specs is not defined, but it works */
- if ((desc->desc.bInterfaceSubClass != 0) &&
- (desc->desc.bInterfaceSubClass != 1)) {
-descriptor_error:
+ if (!hub_descriptor_is_sane(desc)) {
dev_err(&intf->dev, "bad descriptor, ignoring hub\n");
return -EIO;
}
- /* Multiple endpoints? What kind of mutant ninja-hub is this? */
- if (desc->desc.bNumEndpoints != 1)
- goto descriptor_error;
-
- endpoint = &desc->endpoint[0].desc;
-
- /* If it's not an interrupt in endpoint, we'd better punt! */
- if (!usb_endpoint_is_int_in(endpoint))
- goto descriptor_error;
-
/* We found a hub */
dev_info(&intf->dev, "USB hub found\n");
@@ -1784,7 +1788,7 @@ descriptor_error:
if (id->driver_info & HUB_QUIRK_CHECK_PORT_AUTOSUSPEND)
hub->quirk_check_port_auto_suspend = 1;
- if (hub_configure(hub, endpoint) >= 0)
+ if (hub_configure(hub, &desc->endpoint[0].desc) >= 0)
return 0;
hub_disconnect(intf);
@@ -3155,12 +3159,6 @@ int usb_port_suspend(struct usb_device *udev, pm_message_t msg)
if (PMSG_IS_AUTO(msg))
goto err_ltm;
}
- if (usb_unlocked_disable_lpm(udev)) {
- dev_err(&udev->dev, "Failed to disable LPM before suspend\n.");
- status = -ENOMEM;
- if (PMSG_IS_AUTO(msg))
- goto err_lpm3;
- }
/* see 7.1.7.6 */
if (hub_is_superspeed(hub->hdev))
@@ -3187,9 +3185,7 @@ int usb_port_suspend(struct usb_device *udev, pm_message_t msg)
if (status) {
dev_dbg(&port_dev->dev, "can't suspend, status %d\n", status);
- /* Try to enable USB3 LPM and LTM again */
- usb_unlocked_enable_lpm(udev);
- err_lpm3:
+ /* Try to enable USB3 LTM again */
usb_enable_ltm(udev);
err_ltm:
/* Try to enable USB2 hardware LPM again */
@@ -3473,9 +3469,8 @@ int usb_port_resume(struct usb_device *udev, pm_message_t msg)
if (udev->usb2_hw_lpm_capable == 1)
usb_set_usb2_hardware_lpm(udev, 1);
- /* Try to enable USB3 LTM and LPM */
+ /* Try to enable USB3 LTM */
usb_enable_ltm(udev);
- usb_unlocked_enable_lpm(udev);
}
usb_unlock_port(port_dev);
diff --git a/drivers/usb/core/ledtrig-usbport.c b/drivers/usb/core/ledtrig-usbport.c
index 1713248ab15a..16c19a31dad1 100644
--- a/drivers/usb/core/ledtrig-usbport.c
+++ b/drivers/usb/core/ledtrig-usbport.c
@@ -11,8 +11,10 @@
#include <linux/device.h>
#include <linux/leds.h>
#include <linux/module.h>
+#include <linux/of.h>
#include <linux/slab.h>
#include <linux/usb.h>
+#include <linux/usb/of.h>
struct usbport_trig_data {
struct led_classdev *led_cdev;
@@ -123,6 +125,57 @@ static const struct attribute_group ports_group = {
* Adding & removing ports
***************************************/
+/**
+ * usbport_trig_port_observed - Check if port should be observed
+ */
+static bool usbport_trig_port_observed(struct usbport_trig_data *usbport_data,
+ struct usb_device *usb_dev, int port1)
+{
+ struct device *dev = usbport_data->led_cdev->dev;
+ struct device_node *led_np = dev->of_node;
+ struct of_phandle_args args;
+ struct device_node *port_np;
+ int count, i;
+
+ if (!led_np)
+ return false;
+
+ /* Get node of port being added */
+ port_np = usb_of_get_child_node(usb_dev->dev.of_node, port1);
+ if (!port_np)
+ return false;
+
+ /* Amount of trigger sources for this LED */
+ count = of_count_phandle_with_args(led_np, "trigger-sources",
+ "#trigger-source-cells");
+ if (count < 0) {
+ dev_warn(dev, "Failed to get trigger sources for %s\n",
+ led_np->full_name);
+ return false;
+ }
+
+ /* Check list of sources for this specific port */
+ for (i = 0; i < count; i++) {
+ int err;
+
+ err = of_parse_phandle_with_args(led_np, "trigger-sources",
+ "#trigger-source-cells", i,
+ &args);
+ if (err) {
+ dev_err(dev, "Failed to get trigger source phandle at index %d: %d\n",
+ i, err);
+ continue;
+ }
+
+ of_node_put(args.np);
+
+ if (args.np == port_np)
+ return true;
+ }
+
+ return false;
+}
+
static int usbport_trig_add_port(struct usbport_trig_data *usbport_data,
struct usb_device *usb_dev,
const char *hub_name, int portnum)
@@ -141,6 +194,8 @@ static int usbport_trig_add_port(struct usbport_trig_data *usbport_data,
port->data = usbport_data;
port->hub = usb_dev;
port->portnum = portnum;
+ port->observed = usbport_trig_port_observed(usbport_data, usb_dev,
+ portnum);
len = strlen(hub_name) + 8;
port->port_name = kzalloc(len, GFP_KERNEL);
@@ -255,6 +310,7 @@ static void usbport_trig_activate(struct led_classdev *led_cdev)
if (err)
goto err_free;
usb_for_each_dev(usbport_data, usbport_trig_add_usb_dev_ports);
+ usbport_trig_update_count(usbport_data);
/* Notifications */
usbport_data->nb.notifier_call = usbport_trig_notify,
diff --git a/drivers/usb/core/of.c b/drivers/usb/core/of.c
index d563cbcf76cf..3863bb1ce8c5 100644
--- a/drivers/usb/core/of.c
+++ b/drivers/usb/core/of.c
@@ -28,7 +28,8 @@
*
* Find the node from device tree according to its port number.
*
- * Return: On success, a pointer to the device node, %NULL on failure.
+ * Return: A pointer to the node with incremented refcount if found, or
+ * %NULL otherwise.
*/
struct device_node *usb_of_get_child_node(struct device_node *parent,
int portnum)
diff --git a/drivers/usb/core/quirks.c b/drivers/usb/core/quirks.c
index 96b21b0dac1e..3116edfcdc18 100644
--- a/drivers/usb/core/quirks.c
+++ b/drivers/usb/core/quirks.c
@@ -223,6 +223,10 @@ static const struct usb_device_id usb_quirk_list[] = {
/* Blackmagic Design UltraStudio SDI */
{ USB_DEVICE(0x1edb, 0xbd4f), .driver_info = USB_QUIRK_NO_LPM },
+ /* Hauppauge HVR-950q */
+ { USB_DEVICE(0x2040, 0x7200), .driver_info =
+ USB_QUIRK_CONFIG_INTF_STRINGS },
+
/* INTEL VALUE SSD */
{ USB_DEVICE(0x8086, 0xf1a5), .driver_info = USB_QUIRK_RESET_RESUME },
diff --git a/drivers/usb/core/usb-acpi.c b/drivers/usb/core/usb-acpi.c
index 2776cfe64c09..ef9cf4a21afe 100644
--- a/drivers/usb/core/usb-acpi.c
+++ b/drivers/usb/core/usb-acpi.c
@@ -127,6 +127,22 @@ out:
*/
#define USB_ACPI_LOCATION_VALID (1 << 31)
+static struct acpi_device *usb_acpi_find_port(struct acpi_device *parent,
+ int raw)
+{
+ struct acpi_device *adev;
+
+ if (!parent)
+ return NULL;
+
+ list_for_each_entry(adev, &parent->children, node) {
+ if (acpi_device_adr(adev) == raw)
+ return adev;
+ }
+
+ return acpi_find_child_device(parent, raw, false);
+}
+
static struct acpi_device *usb_acpi_find_companion(struct device *dev)
{
struct usb_device *udev;
@@ -174,8 +190,10 @@ static struct acpi_device *usb_acpi_find_companion(struct device *dev)
int raw;
raw = usb_hcd_find_raw_port_number(hcd, port1);
- adev = acpi_find_child_device(ACPI_COMPANION(&udev->dev),
- raw, false);
+
+ adev = usb_acpi_find_port(ACPI_COMPANION(&udev->dev),
+ raw);
+
if (!adev)
return NULL;
} else {
@@ -186,7 +204,9 @@ static struct acpi_device *usb_acpi_find_companion(struct device *dev)
return NULL;
acpi_bus_get_device(parent_handle, &adev);
- adev = acpi_find_child_device(adev, port1, false);
+
+ adev = usb_acpi_find_port(adev, port1);
+
if (!adev)
return NULL;
}
diff --git a/drivers/usb/core/usb.c b/drivers/usb/core/usb.c
index 28b053cacc90..17681d5638ac 100644
--- a/drivers/usb/core/usb.c
+++ b/drivers/usb/core/usb.c
@@ -416,6 +416,7 @@ static void usb_release_dev(struct device *dev)
usb_destroy_configuration(udev);
usb_release_bos_descriptor(udev);
+ of_node_put(dev->of_node);
usb_put_hcd(hcd);
kfree(udev->product);
kfree(udev->manufacturer);
@@ -614,6 +615,7 @@ struct usb_device *usb_alloc_dev(struct usb_device *parent,
dev->route = 0;
dev->dev.parent = bus->controller;
+ device_set_of_node_from_dev(&dev->dev, bus->sysdev);
dev_set_name(&dev->dev, "usb%d", bus->busnum);
root_hub = 1;
} else {
diff --git a/drivers/usb/dwc2/params.c b/drivers/usb/dwc2/params.c
index 9cd8722f24f6..a3ffe97170ff 100644
--- a/drivers/usb/dwc2/params.c
+++ b/drivers/usb/dwc2/params.c
@@ -144,6 +144,8 @@ const struct of_device_id dwc2_of_match_table[] = {
{ .compatible = "lantiq,xrx200-usb", .data = dwc2_set_ltq_params },
{ .compatible = "snps,dwc2" },
{ .compatible = "samsung,s3c6400-hsotg" },
+ { .compatible = "amlogic,meson8-usb",
+ .data = dwc2_set_amlogic_params },
{ .compatible = "amlogic,meson8b-usb",
.data = dwc2_set_amlogic_params },
{ .compatible = "amlogic,meson-gxbb-usb",
diff --git a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c
index 455d89a1cd6d..326b302fc440 100644
--- a/drivers/usb/dwc3/core.c
+++ b/drivers/usb/dwc3/core.c
@@ -151,11 +151,24 @@ static void __dwc3_set_mode(struct work_struct *work)
switch (dwc->desired_dr_role) {
case DWC3_GCTL_PRTCAP_HOST:
ret = dwc3_host_init(dwc);
- if (ret)
+ if (ret) {
dev_err(dwc->dev, "failed to initialize host\n");
+ } else {
+ if (dwc->usb2_phy)
+ otg_set_vbus(dwc->usb2_phy->otg, true);
+ if (dwc->usb2_generic_phy)
+ phy_set_mode(dwc->usb2_generic_phy, PHY_MODE_USB_HOST);
+
+ }
break;
case DWC3_GCTL_PRTCAP_DEVICE:
dwc3_event_buffers_setup(dwc);
+
+ if (dwc->usb2_phy)
+ otg_set_vbus(dwc->usb2_phy->otg, false);
+ if (dwc->usb2_generic_phy)
+ phy_set_mode(dwc->usb2_generic_phy, PHY_MODE_USB_DEVICE);
+
ret = dwc3_gadget_init(dwc);
if (ret)
dev_err(dwc->dev, "failed to initialize peripheral\n");
@@ -721,6 +734,8 @@ static void dwc3_core_setup_global_control(struct dwc3 *dwc)
dwc3_writel(dwc->regs, DWC3_GCTL, reg);
}
+static int dwc3_core_get_phy(struct dwc3 *dwc);
+
/**
* dwc3_core_init - Low-level initialization of DWC3 Core
* @dwc: Pointer to our controller context structure
@@ -759,6 +774,10 @@ static int dwc3_core_init(struct dwc3 *dwc)
if (ret)
goto err0;
+ ret = dwc3_core_get_phy(dwc);
+ if (ret)
+ goto err0;
+
dwc3_core_setup_global_control(dwc);
dwc3_core_num_eps(dwc);
@@ -796,13 +815,19 @@ static int dwc3_core_init(struct dwc3 *dwc)
dwc3_writel(dwc->regs, DWC3_GUCTL2, reg);
}
- /*
- * Enable hardware control of sending remote wakeup in HS when
- * the device is in the L1 state.
- */
- if (dwc->revision >= DWC3_REVISION_290A) {
+ if (dwc->revision >= DWC3_REVISION_250A) {
reg = dwc3_readl(dwc->regs, DWC3_GUCTL1);
- reg |= DWC3_GUCTL1_DEV_L1_EXIT_BY_HW;
+
+ /*
+ * Enable hardware control of sending remote wakeup
+ * in HS when the device is in the L1 state.
+ */
+ if (dwc->revision >= DWC3_REVISION_290A)
+ reg |= DWC3_GUCTL1_DEV_L1_EXIT_BY_HW;
+
+ if (dwc->dis_tx_ipgap_linecheck_quirk)
+ reg |= DWC3_GUCTL1_TX_IPGAP_LINECHECK_DIS;
+
dwc3_writel(dwc->regs, DWC3_GUCTL1, reg);
}
@@ -903,6 +928,12 @@ static int dwc3_core_init_mode(struct dwc3 *dwc)
switch (dwc->dr_mode) {
case USB_DR_MODE_PERIPHERAL:
dwc3_set_prtcap(dwc, DWC3_GCTL_PRTCAP_DEVICE);
+
+ if (dwc->usb2_phy)
+ otg_set_vbus(dwc->usb2_phy->otg, false);
+ if (dwc->usb2_generic_phy)
+ phy_set_mode(dwc->usb2_generic_phy, PHY_MODE_USB_DEVICE);
+
ret = dwc3_gadget_init(dwc);
if (ret) {
if (ret != -EPROBE_DEFER)
@@ -912,6 +943,12 @@ static int dwc3_core_init_mode(struct dwc3 *dwc)
break;
case USB_DR_MODE_HOST:
dwc3_set_prtcap(dwc, DWC3_GCTL_PRTCAP_HOST);
+
+ if (dwc->usb2_phy)
+ otg_set_vbus(dwc->usb2_phy->otg, true);
+ if (dwc->usb2_generic_phy)
+ phy_set_mode(dwc->usb2_generic_phy, PHY_MODE_USB_HOST);
+
ret = dwc3_host_init(dwc);
if (ret) {
if (ret != -EPROBE_DEFER)
@@ -1023,6 +1060,8 @@ static void dwc3_get_properties(struct dwc3 *dwc)
"snps,dis-u2-freeclk-exists-quirk");
dwc->dis_del_phy_power_chg_quirk = device_property_read_bool(dev,
"snps,dis-del-phy-power-chg-quirk");
+ dwc->dis_tx_ipgap_linecheck_quirk = device_property_read_bool(dev,
+ "snps,dis-tx-ipgap-linecheck-quirk");
dwc->tx_de_emphasis_quirk = device_property_read_bool(dev,
"snps,tx_de_emphasis_quirk");
@@ -1148,10 +1187,6 @@ static int dwc3_probe(struct platform_device *pdev)
platform_set_drvdata(pdev, dwc);
dwc3_cache_hwparams(dwc);
- ret = dwc3_core_get_phy(dwc);
- if (ret)
- goto err0;
-
spin_lock_init(&dwc->lock);
pm_runtime_set_active(dev);
diff --git a/drivers/usb/dwc3/core.h b/drivers/usb/dwc3/core.h
index 981c77f5628e..ea910acb4bb0 100644
--- a/drivers/usb/dwc3/core.h
+++ b/drivers/usb/dwc3/core.h
@@ -1,4 +1,4 @@
-/**
+/*
* core.h - DesignWare USB3 DRD Core Header
*
* Copyright (C) 2010-2011 Texas Instruments Incorporated - http://www.ti.com
@@ -204,6 +204,7 @@
#define DWC3_GCTL_DSBLCLKGTNG BIT(0)
/* Global User Control 1 Register */
+#define DWC3_GUCTL1_TX_IPGAP_LINECHECK_DIS BIT(28)
#define DWC3_GUCTL1_DEV_L1_EXIT_BY_HW BIT(24)
/* Global USB2 PHY Configuration Register */
@@ -522,7 +523,6 @@ struct dwc3_event_buffer {
* @trb_pool_dma: dma address of @trb_pool
* @trb_enqueue: enqueue 'pointer' into TRB array
* @trb_dequeue: dequeue 'pointer' into TRB array
- * @desc: usb_endpoint_descriptor pointer
* @dwc: pointer to DWC controller
* @saved_state: ep state saved during hibernation
* @flags: endpoint flags (wedged, stalled, ...)
@@ -664,7 +664,7 @@ enum dwc3_link_state {
* @bpl: DW0-3
* @bph: DW4-7
* @size: DW8-B
- * @trl: DWC-F
+ * @ctrl: DWC-F
*/
struct dwc3_trb {
u32 bpl;
@@ -674,16 +674,16 @@ struct dwc3_trb {
} __packed;
/**
- * dwc3_hwparams - copy of HWPARAMS registers
- * @hwparams0 - GHWPARAMS0
- * @hwparams1 - GHWPARAMS1
- * @hwparams2 - GHWPARAMS2
- * @hwparams3 - GHWPARAMS3
- * @hwparams4 - GHWPARAMS4
- * @hwparams5 - GHWPARAMS5
- * @hwparams6 - GHWPARAMS6
- * @hwparams7 - GHWPARAMS7
- * @hwparams8 - GHWPARAMS8
+ * struct dwc3_hwparams - copy of HWPARAMS registers
+ * @hwparams0: GHWPARAMS0
+ * @hwparams1: GHWPARAMS1
+ * @hwparams2: GHWPARAMS2
+ * @hwparams3: GHWPARAMS3
+ * @hwparams4: GHWPARAMS4
+ * @hwparams5: GHWPARAMS5
+ * @hwparams6: GHWPARAMS6
+ * @hwparams7: GHWPARAMS7
+ * @hwparams8: GHWPARAMS8
*/
struct dwc3_hwparams {
u32 hwparams0;
@@ -730,7 +730,8 @@ struct dwc3_hwparams {
* @unaligned: true for OUT endpoints with length not divisible by maxp
* @direction: IN or OUT direction flag
* @mapped: true when request has been dma-mapped
- * @queued: true when request has been queued to HW
+ * @started: request is started
+ * @zero: wants a ZLP
*/
struct dwc3_request {
struct usb_request request;
@@ -761,17 +762,23 @@ struct dwc3_scratchpad_array {
/**
* struct dwc3 - representation of our controller
- * @drd_work - workqueue used for role swapping
+ * @drd_work: workqueue used for role swapping
* @ep0_trb: trb which is used for the ctrl_req
+ * @bounce: address of bounce buffer
+ * @scratchbuf: address of scratch buffer
* @setup_buf: used while precessing STD USB requests
- * @ep0_trb: dma address of ep0_trb
+ * @ep0_trb_addr: dma address of @ep0_trb
+ * @bounce_addr: dma address of @bounce
* @ep0_usb_req: dummy req used while handling STD USB requests
* @scratch_addr: dma address of scratchbuf
* @ep0_in_setup: one control transfer is completed and enter setup phase
* @lock: for synchronizing
* @dev: pointer to our struct device
+ * @sysdev: pointer to the DMA-capable device
* @xhci: pointer to our xHCI child
- * @event_buffer_list: a list of event buffers
+ * @xhci_resources: struct resources for our @xhci child
+ * @ev_buf: struct dwc3_event_buffer pointer
+ * @eps: endpoint array
* @gadget: device side representation of the peripheral controller
* @gadget_driver: pointer to the gadget driver
* @regs: base address for our registers
@@ -795,8 +802,6 @@ struct dwc3_scratchpad_array {
* @usb2_generic_phy: pointer to USB2 PHY
* @usb3_generic_phy: pointer to USB3 PHY
* @ulpi: pointer to ulpi interface
- * @dcfg: saved contents of DCFG register
- * @gctl: saved contents of GCTL register
* @isoch_delay: wValue from Set Isochronous Delay request;
* @u2sel: parameter from Set SEL request.
* @u2pel: parameter from Set SEL request.
@@ -830,7 +835,6 @@ struct dwc3_scratchpad_array {
* @pending_events: true when we have pending IRQs to be handled
* @pullups_connected: true when Run/Stop bit is set
* @setup_packet_pending: true when there's a Setup Packet in FIFO. Workaround
- * @start_config_issued: true when StartConfig command has been issued
* @three_stage_setup: set if we perform a three phase setup
* @usb3_lpm_capable: set if hadrware supports Link Power Management
* @disable_scramble_quirk: set if we enable the disable scramble quirk
@@ -845,11 +849,14 @@ struct dwc3_scratchpad_array {
* @dis_u2_susphy_quirk: set if we disable usb2 suspend phy
* @dis_enblslpm_quirk: set if we clear enblslpm in GUSB2PHYCFG,
* disabling the suspend signal to the PHY.
+ * @dis_rxdet_inp3_quirk: set if we disable Rx.Detect in P3
* @dis_u2_freeclk_exists_quirk : set if we clear u2_freeclk_exists
* in GUSB2PHYCFG, specify that USB2 PHY doesn't
* provide a free-running PHY clock.
* @dis_del_phy_power_chg_quirk: set if we disable delay phy power
* change quirk.
+ * @dis_tx_ipgap_linecheck_quirk: set if we disable u2mac linestate
+ * check during HS transmit.
* @tx_de_emphasis_quirk: set if we enable Tx de-emphasis quirk
* @tx_de_emphasis: Tx de-emphasis value
* 0 - -6dB de-emphasis
@@ -1004,6 +1011,7 @@ struct dwc3 {
unsigned dis_rxdet_inp3_quirk:1;
unsigned dis_u2_freeclk_exists_quirk:1;
unsigned dis_del_phy_power_chg_quirk:1;
+ unsigned dis_tx_ipgap_linecheck_quirk:1;
unsigned tx_de_emphasis_quirk:1;
unsigned tx_de_emphasis:2;
diff --git a/drivers/usb/dwc3/debug.h b/drivers/usb/dwc3/debug.h
index cb2d8d3f7f3d..5e9c070ec874 100644
--- a/drivers/usb/dwc3/debug.h
+++ b/drivers/usb/dwc3/debug.h
@@ -173,9 +173,8 @@ static inline const char *dwc3_ep0_state_string(enum dwc3_ep0_state state)
* @event: the event code
*/
static inline const char *
-dwc3_gadget_event_string(const struct dwc3_event_devt *event)
+dwc3_gadget_event_string(char *str, const struct dwc3_event_devt *event)
{
- static char str[256];
enum dwc3_link_state state = event->event_info & DWC3_LINK_STATE_MASK;
switch (event->type) {
@@ -223,15 +222,249 @@ dwc3_gadget_event_string(const struct dwc3_event_devt *event)
return str;
}
+static inline void dwc3_decode_get_status(__u8 t, __u16 i, __u16 l, char *str)
+{
+ switch (t & USB_RECIP_MASK) {
+ case USB_RECIP_INTERFACE:
+ sprintf(str, "Get Interface Status(Intf = %d, Length = %d)",
+ i, l);
+ break;
+ case USB_RECIP_ENDPOINT:
+ sprintf(str, "Get Endpoint Status(ep%d%s)",
+ i & ~USB_DIR_IN,
+ i & USB_DIR_IN ? "in" : "out");
+ break;
+ }
+}
+
+static inline void dwc3_decode_set_clear_feature(__u8 t, __u8 b, __u16 v,
+ __u16 i, char *str)
+{
+ switch (t & USB_RECIP_MASK) {
+ case USB_RECIP_DEVICE:
+ sprintf(str, "%s Device Feature(%s%s)",
+ b == USB_REQ_CLEAR_FEATURE ? "Clear" : "Set",
+ ({char *s;
+ switch (v) {
+ case USB_DEVICE_SELF_POWERED:
+ s = "Self Powered";
+ break;
+ case USB_DEVICE_REMOTE_WAKEUP:
+ s = "Remote Wakeup";
+ break;
+ case USB_DEVICE_TEST_MODE:
+ s = "Test Mode";
+ break;
+ default:
+ s = "UNKNOWN";
+ } s; }),
+ v == USB_DEVICE_TEST_MODE ?
+ ({ char *s;
+ switch (i) {
+ case TEST_J:
+ s = ": TEST_J";
+ break;
+ case TEST_K:
+ s = ": TEST_K";
+ break;
+ case TEST_SE0_NAK:
+ s = ": TEST_SE0_NAK";
+ break;
+ case TEST_PACKET:
+ s = ": TEST_PACKET";
+ break;
+ case TEST_FORCE_EN:
+ s = ": TEST_FORCE_EN";
+ break;
+ default:
+ s = ": UNKNOWN";
+ } s; }) : "");
+ break;
+ case USB_RECIP_INTERFACE:
+ sprintf(str, "%s Interface Feature(%s)",
+ b == USB_REQ_CLEAR_FEATURE ? "Clear" : "Set",
+ v == USB_INTRF_FUNC_SUSPEND ?
+ "Function Suspend" : "UNKNOWN");
+ break;
+ case USB_RECIP_ENDPOINT:
+ sprintf(str, "%s Endpoint Feature(%s ep%d%s)",
+ b == USB_REQ_CLEAR_FEATURE ? "Clear" : "Set",
+ v == USB_ENDPOINT_HALT ? "Halt" : "UNKNOWN",
+ i & ~USB_DIR_IN,
+ i & USB_DIR_IN ? "in" : "out");
+ break;
+ }
+}
+
+static inline void dwc3_decode_set_address(__u16 v, char *str)
+{
+ sprintf(str, "Set Address(Addr = %02x)", v);
+}
+
+static inline void dwc3_decode_get_set_descriptor(__u8 t, __u8 b, __u16 v,
+ __u16 i, __u16 l, char *str)
+{
+ sprintf(str, "%s %s Descriptor(Index = %d, Length = %d)",
+ b == USB_REQ_GET_DESCRIPTOR ? "Get" : "Set",
+ ({ char *s;
+ switch (v >> 8) {
+ case USB_DT_DEVICE:
+ s = "Device";
+ break;
+ case USB_DT_CONFIG:
+ s = "Configuration";
+ break;
+ case USB_DT_STRING:
+ s = "String";
+ break;
+ case USB_DT_INTERFACE:
+ s = "Interface";
+ break;
+ case USB_DT_ENDPOINT:
+ s = "Endpoint";
+ break;
+ case USB_DT_DEVICE_QUALIFIER:
+ s = "Device Qualifier";
+ break;
+ case USB_DT_OTHER_SPEED_CONFIG:
+ s = "Other Speed Config";
+ break;
+ case USB_DT_INTERFACE_POWER:
+ s = "Interface Power";
+ break;
+ case USB_DT_OTG:
+ s = "OTG";
+ break;
+ case USB_DT_DEBUG:
+ s = "Debug";
+ break;
+ case USB_DT_INTERFACE_ASSOCIATION:
+ s = "Interface Association";
+ break;
+ case USB_DT_BOS:
+ s = "BOS";
+ break;
+ case USB_DT_DEVICE_CAPABILITY:
+ s = "Device Capability";
+ break;
+ case USB_DT_PIPE_USAGE:
+ s = "Pipe Usage";
+ break;
+ case USB_DT_SS_ENDPOINT_COMP:
+ s = "SS Endpoint Companion";
+ break;
+ case USB_DT_SSP_ISOC_ENDPOINT_COMP:
+ s = "SSP Isochronous Endpoint Companion";
+ break;
+ default:
+ s = "UNKNOWN";
+ break;
+ } s; }), v & 0xff, l);
+}
+
+
+static inline void dwc3_decode_get_configuration(__u16 l, char *str)
+{
+ sprintf(str, "Get Configuration(Length = %d)", l);
+}
+
+static inline void dwc3_decode_set_configuration(__u8 v, char *str)
+{
+ sprintf(str, "Set Configuration(Config = %d)", v);
+}
+
+static inline void dwc3_decode_get_intf(__u16 i, __u16 l, char *str)
+{
+ sprintf(str, "Get Interface(Intf = %d, Length = %d)", i, l);
+}
+
+static inline void dwc3_decode_set_intf(__u8 v, __u16 i, char *str)
+{
+ sprintf(str, "Set Interface(Intf = %d, Alt.Setting = %d)", i, v);
+}
+
+static inline void dwc3_decode_synch_frame(__u16 i, __u16 l, char *str)
+{
+ sprintf(str, "Synch Frame(Endpoint = %d, Length = %d)", i, l);
+}
+
+static inline void dwc3_decode_set_sel(__u16 l, char *str)
+{
+ sprintf(str, "Set SEL(Length = %d)", l);
+}
+
+static inline void dwc3_decode_set_isoch_delay(__u8 v, char *str)
+{
+ sprintf(str, "Set Isochronous Delay(Delay = %d ns)", v);
+}
+
+/**
+ * dwc3_decode_ctrl - returns a string represetion of ctrl request
+ */
+static inline const char *dwc3_decode_ctrl(char *str, __u8 bRequestType,
+ __u8 bRequest, __u16 wValue, __u16 wIndex, __u16 wLength)
+{
+ switch (bRequest) {
+ case USB_REQ_GET_STATUS:
+ dwc3_decode_get_status(bRequestType, wIndex, wLength, str);
+ break;
+ case USB_REQ_CLEAR_FEATURE:
+ case USB_REQ_SET_FEATURE:
+ dwc3_decode_set_clear_feature(bRequestType, bRequest, wValue,
+ wIndex, str);
+ break;
+ case USB_REQ_SET_ADDRESS:
+ dwc3_decode_set_address(wValue, str);
+ break;
+ case USB_REQ_GET_DESCRIPTOR:
+ case USB_REQ_SET_DESCRIPTOR:
+ dwc3_decode_get_set_descriptor(bRequestType, bRequest, wValue,
+ wIndex, wLength, str);
+ break;
+ case USB_REQ_GET_CONFIGURATION:
+ dwc3_decode_get_configuration(wLength, str);
+ break;
+ case USB_REQ_SET_CONFIGURATION:
+ dwc3_decode_set_configuration(wValue, str);
+ break;
+ case USB_REQ_GET_INTERFACE:
+ dwc3_decode_get_intf(wIndex, wLength, str);
+ break;
+ case USB_REQ_SET_INTERFACE:
+ dwc3_decode_set_intf(wValue, wIndex, str);
+ break;
+ case USB_REQ_SYNCH_FRAME:
+ dwc3_decode_synch_frame(wIndex, wLength, str);
+ break;
+ case USB_REQ_SET_SEL:
+ dwc3_decode_set_sel(wLength, str);
+ break;
+ case USB_REQ_SET_ISOCH_DELAY:
+ dwc3_decode_set_isoch_delay(wValue, str);
+ break;
+ default:
+ sprintf(str, "%02x %02x %02x %02x %02x %02x %02x %02x",
+ bRequestType, bRequest,
+ cpu_to_le16(wValue) & 0xff,
+ cpu_to_le16(wValue) >> 8,
+ cpu_to_le16(wIndex) & 0xff,
+ cpu_to_le16(wIndex) >> 8,
+ cpu_to_le16(wLength) & 0xff,
+ cpu_to_le16(wLength) >> 8);
+ }
+
+ return str;
+}
+
/**
* dwc3_ep_event_string - returns event name
* @event: then event code
*/
static inline const char *
-dwc3_ep_event_string(const struct dwc3_event_depevt *event, u32 ep0state)
+dwc3_ep_event_string(char *str, const struct dwc3_event_depevt *event,
+ u32 ep0state)
{
u8 epnum = event->endpoint_number;
- static char str[256];
size_t len;
int status;
int ret;
@@ -332,14 +565,14 @@ static inline const char *dwc3_gadget_event_type_string(u8 event)
}
}
-static inline const char *dwc3_decode_event(u32 event, u32 ep0state)
+static inline const char *dwc3_decode_event(char *str, u32 event, u32 ep0state)
{
const union dwc3_event evt = (union dwc3_event) event;
if (evt.type.is_devspec)
- return dwc3_gadget_event_string(&evt.devt);
+ return dwc3_gadget_event_string(str, &evt.devt);
else
- return dwc3_ep_event_string(&evt.depevt, ep0state);
+ return dwc3_ep_event_string(str, &evt.depevt, ep0state);
}
static inline const char *dwc3_ep_cmd_status_string(int status)
diff --git a/drivers/usb/dwc3/debugfs.c b/drivers/usb/dwc3/debugfs.c
index 7be963dd8e3b..4e09be80e59f 100644
--- a/drivers/usb/dwc3/debugfs.c
+++ b/drivers/usb/dwc3/debugfs.c
@@ -653,16 +653,13 @@ static int dwc3_ep_trb_ring_show(struct seq_file *s, void *unused)
goto out;
}
- seq_printf(s, "enqueue pointer %d\n", dep->trb_enqueue);
- seq_printf(s, "dequeue pointer %d\n", dep->trb_dequeue);
- seq_printf(s, "\n--------------------------------------------------\n\n");
seq_printf(s, "buffer_addr,size,type,ioc,isp_imi,csp,chn,lst,hwo\n");
for (i = 0; i < DWC3_TRB_NUM; i++) {
struct dwc3_trb *trb = &dep->trb_pool[i];
unsigned int type = DWC3_TRBCTL_TYPE(trb->ctrl);
- seq_printf(s, "%08x%08x,%d,%s,%d,%d,%d,%d,%d,%d\n",
+ seq_printf(s, "%08x%08x,%d,%s,%d,%d,%d,%d,%d,%d %c%c\n",
trb->bph, trb->bpl, trb->size,
dwc3_trb_type_string(type),
!!(trb->ctrl & DWC3_TRB_CTRL_IOC),
@@ -670,7 +667,9 @@ static int dwc3_ep_trb_ring_show(struct seq_file *s, void *unused)
!!(trb->ctrl & DWC3_TRB_CTRL_CSP),
!!(trb->ctrl & DWC3_TRB_CTRL_CHN),
!!(trb->ctrl & DWC3_TRB_CTRL_LST),
- !!(trb->ctrl & DWC3_TRB_CTRL_HWO));
+ !!(trb->ctrl & DWC3_TRB_CTRL_HWO),
+ dep->trb_enqueue == i ? 'E' : ' ',
+ dep->trb_dequeue == i ? 'D' : ' ');
}
out:
diff --git a/drivers/usb/dwc3/dwc3-exynos.c b/drivers/usb/dwc3/dwc3-exynos.c
index 98f74ff66120..e089df72f766 100644
--- a/drivers/usb/dwc3/dwc3-exynos.c
+++ b/drivers/usb/dwc3/dwc3-exynos.c
@@ -125,12 +125,16 @@ static int dwc3_exynos_probe(struct platform_device *pdev)
dev_err(dev, "couldn't get clock\n");
return -EINVAL;
}
- clk_prepare_enable(exynos->clk);
+ ret = clk_prepare_enable(exynos->clk);
+ if (ret)
+ return ret;
exynos->susp_clk = devm_clk_get(dev, "usbdrd30_susp_clk");
if (IS_ERR(exynos->susp_clk))
exynos->susp_clk = NULL;
- clk_prepare_enable(exynos->susp_clk);
+ ret = clk_prepare_enable(exynos->susp_clk);
+ if (ret)
+ goto susp_clk_err;
if (of_device_is_compatible(node, "samsung,exynos7-dwusb3")) {
exynos->axius_clk = devm_clk_get(dev, "usbdrd30_axius_clk");
@@ -139,7 +143,9 @@ static int dwc3_exynos_probe(struct platform_device *pdev)
ret = -ENODEV;
goto axius_clk_err;
}
- clk_prepare_enable(exynos->axius_clk);
+ ret = clk_prepare_enable(exynos->axius_clk);
+ if (ret)
+ goto axius_clk_err;
} else {
exynos->axius_clk = NULL;
}
@@ -197,6 +203,7 @@ vdd33_err:
clk_disable_unprepare(exynos->axius_clk);
axius_clk_err:
clk_disable_unprepare(exynos->susp_clk);
+susp_clk_err:
clk_disable_unprepare(exynos->clk);
return ret;
}
diff --git a/drivers/usb/dwc3/dwc3-pci.c b/drivers/usb/dwc3/dwc3-pci.c
index 84a2cebfc712..fe851544d7fb 100644
--- a/drivers/usb/dwc3/dwc3-pci.c
+++ b/drivers/usb/dwc3/dwc3-pci.c
@@ -42,7 +42,7 @@
#define PCI_DEVICE_ID_INTEL_CNPLP 0x9dee
#define PCI_DEVICE_ID_INTEL_CNPH 0xa36e
-#define PCI_INTEL_BXT_DSM_UUID "732b85d5-b7a7-4a1b-9ba0-4bbd00ffd511"
+#define PCI_INTEL_BXT_DSM_GUID "732b85d5-b7a7-4a1b-9ba0-4bbd00ffd511"
#define PCI_INTEL_BXT_FUNC_PMU_PWR 4
#define PCI_INTEL_BXT_STATE_D0 0
#define PCI_INTEL_BXT_STATE_D3 3
@@ -51,14 +51,14 @@
* struct dwc3_pci - Driver private structure
* @dwc3: child dwc3 platform_device
* @pci: our link to PCI bus
- * @uuid: _DSM UUID
+ * @guid: _DSM GUID
* @has_dsm_for_pm: true for devices which need to run _DSM on runtime PM
*/
struct dwc3_pci {
struct platform_device *dwc3;
struct pci_dev *pci;
- u8 uuid[16];
+ guid_t guid;
unsigned int has_dsm_for_pm:1;
};
@@ -120,7 +120,7 @@ static int dwc3_pci_quirks(struct dwc3_pci *dwc)
if (pdev->device == PCI_DEVICE_ID_INTEL_BXT ||
pdev->device == PCI_DEVICE_ID_INTEL_BXT_M) {
- acpi_str_to_uuid(PCI_INTEL_BXT_DSM_UUID, dwc->uuid);
+ guid_parse(PCI_INTEL_BXT_DSM_GUID, &dwc->guid);
dwc->has_dsm_for_pm = true;
}
@@ -292,7 +292,7 @@ static int dwc3_pci_dsm(struct dwc3_pci *dwc, int param)
tmp.type = ACPI_TYPE_INTEGER;
tmp.integer.value = param;
- obj = acpi_evaluate_dsm(ACPI_HANDLE(&dwc->pci->dev), dwc->uuid,
+ obj = acpi_evaluate_dsm(ACPI_HANDLE(&dwc->pci->dev), &dwc->guid,
1, PCI_INTEL_BXT_FUNC_PMU_PWR, &argv4);
if (!obj) {
dev_err(&dwc->pci->dev, "failed to evaluate _DSM\n");
diff --git a/drivers/usb/dwc3/dwc3-st.c b/drivers/usb/dwc3/dwc3-st.c
index dfbf464eb88c..505676fd3ba4 100644
--- a/drivers/usb/dwc3/dwc3-st.c
+++ b/drivers/usb/dwc3/dwc3-st.c
@@ -230,7 +230,7 @@ static int st_dwc3_probe(struct platform_device *pdev)
dwc3_data->syscfg_reg_off = res->start;
- dev_vdbg(&pdev->dev, "glue-logic addr 0x%p, syscfg-reg offset 0x%x\n",
+ dev_vdbg(&pdev->dev, "glue-logic addr 0x%pK, syscfg-reg offset 0x%x\n",
dwc3_data->glue_base, dwc3_data->syscfg_reg_off);
dwc3_data->rstc_pwrdn =
diff --git a/drivers/usb/dwc3/ep0.c b/drivers/usb/dwc3/ep0.c
index a78c78e7a8c3..827e376bfa97 100644
--- a/drivers/usb/dwc3/ep0.c
+++ b/drivers/usb/dwc3/ep0.c
@@ -1,4 +1,4 @@
-/**
+/*
* ep0.c - DesignWare USB3 DRD Controller Endpoint 0 Handling
*
* Copyright (C) 2010-2011 Texas Instruments Incorporated - http://www.ti.com
@@ -319,10 +319,16 @@ static int dwc3_ep0_handle_status(struct dwc3 *dwc,
{
struct dwc3_ep *dep;
u32 recip;
+ u32 value;
u32 reg;
u16 usb_status = 0;
__le16 *response_pkt;
+ /* We don't support PTM_STATUS */
+ value = le16_to_cpu(ctrl->wValue);
+ if (value != 0)
+ return -EINVAL;
+
recip = ctrl->bRequestType & USB_RECIP_MASK;
switch (recip) {
case USB_RECIP_DEVICE:
diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c
index aea9a5b948b4..9e41605a276b 100644
--- a/drivers/usb/dwc3/gadget.c
+++ b/drivers/usb/dwc3/gadget.c
@@ -1,4 +1,4 @@
-/**
+/*
* gadget.c - DesignWare USB3 DRD Controller Gadget Framework Link
*
* Copyright (C) 2010-2011 Texas Instruments Incorporated - http://www.ti.com
@@ -36,13 +36,12 @@
#include "io.h"
/**
- * dwc3_gadget_set_test_mode - Enables USB2 Test Modes
+ * dwc3_gadget_set_test_mode - enables usb2 test modes
* @dwc: pointer to our context structure
* @mode: the mode to set (J, K SE0 NAK, Force Enable)
*
- * Caller should take care of locking. This function will
- * return 0 on success or -EINVAL if wrong Test Selector
- * is passed
+ * Caller should take care of locking. This function will return 0 on
+ * success or -EINVAL if wrong Test Selector is passed.
*/
int dwc3_gadget_set_test_mode(struct dwc3 *dwc, int mode)
{
@@ -69,7 +68,7 @@ int dwc3_gadget_set_test_mode(struct dwc3 *dwc, int mode)
}
/**
- * dwc3_gadget_get_link_state - Gets current state of USB Link
+ * dwc3_gadget_get_link_state - gets current state of usb link
* @dwc: pointer to our context structure
*
* Caller should take care of locking. This function will
@@ -85,7 +84,7 @@ int dwc3_gadget_get_link_state(struct dwc3 *dwc)
}
/**
- * dwc3_gadget_set_link_state - Sets USB Link to a particular State
+ * dwc3_gadget_set_link_state - sets usb link to a particular state
* @dwc: pointer to our context structure
* @state: the state to put link into
*
@@ -143,8 +142,8 @@ int dwc3_gadget_set_link_state(struct dwc3 *dwc, enum dwc3_link_state state)
}
/**
- * dwc3_ep_inc_trb() - Increment a TRB index.
- * @index - Pointer to the TRB index to increment.
+ * dwc3_ep_inc_trb - increment a trb index.
+ * @index: Pointer to the TRB index to increment.
*
* The index should never point to the link TRB. After incrementing,
* if it is point to the link TRB, wrap around to the beginning. The
@@ -157,16 +156,34 @@ static void dwc3_ep_inc_trb(u8 *index)
*index = 0;
}
+/**
+ * dwc3_ep_inc_enq - increment endpoint's enqueue pointer
+ * @dep: The endpoint whose enqueue pointer we're incrementing
+ */
static void dwc3_ep_inc_enq(struct dwc3_ep *dep)
{
dwc3_ep_inc_trb(&dep->trb_enqueue);
}
+/**
+ * dwc3_ep_inc_deq - increment endpoint's dequeue pointer
+ * @dep: The endpoint whose enqueue pointer we're incrementing
+ */
static void dwc3_ep_inc_deq(struct dwc3_ep *dep)
{
dwc3_ep_inc_trb(&dep->trb_dequeue);
}
+/**
+ * dwc3_gadget_giveback - call struct usb_request's ->complete callback
+ * @dep: The endpoint to whom the request belongs to
+ * @req: The request we're giving back
+ * @status: completion code for the request
+ *
+ * Must be called with controller's lock held and interrupts disabled. This
+ * function will unmap @req and call its ->complete() callback to notify upper
+ * layers that it has completed.
+ */
void dwc3_gadget_giveback(struct dwc3_ep *dep, struct dwc3_request *req,
int status)
{
@@ -193,6 +210,15 @@ void dwc3_gadget_giveback(struct dwc3_ep *dep, struct dwc3_request *req,
pm_runtime_put(dwc->dev);
}
+/**
+ * dwc3_send_gadget_generic_command - issue a generic command for the controller
+ * @dwc: pointer to the controller context
+ * @cmd: the command to be issued
+ * @param: command parameter
+ *
+ * Caller should take care of locking. Issue @cmd with a given @param to @dwc
+ * and wait for its completion.
+ */
int dwc3_send_gadget_generic_command(struct dwc3 *dwc, unsigned cmd, u32 param)
{
u32 timeout = 500;
@@ -225,6 +251,15 @@ int dwc3_send_gadget_generic_command(struct dwc3 *dwc, unsigned cmd, u32 param)
static int __dwc3_gadget_wakeup(struct dwc3 *dwc);
+/**
+ * dwc3_send_gadget_ep_cmd - issue an endpoint command
+ * @dep: the endpoint to which the command is going to be issued
+ * @cmd: the command to be issued
+ * @params: parameters to the command
+ *
+ * Caller should handle locking. This function will issue @cmd with given
+ * @params to @dep and wait for its completion.
+ */
int dwc3_send_gadget_ep_cmd(struct dwc3_ep *dep, unsigned cmd,
struct dwc3_gadget_ep_cmd_params *params)
{
@@ -422,36 +457,38 @@ static void dwc3_free_trb_pool(struct dwc3_ep *dep)
static int dwc3_gadget_set_xfer_resource(struct dwc3 *dwc, struct dwc3_ep *dep);
/**
- * dwc3_gadget_start_config - Configure EP resources
+ * dwc3_gadget_start_config - configure ep resources
* @dwc: pointer to our controller context structure
* @dep: endpoint that is being enabled
*
- * The assignment of transfer resources cannot perfectly follow the
- * data book due to the fact that the controller driver does not have
- * all knowledge of the configuration in advance. It is given this
- * information piecemeal by the composite gadget framework after every
- * SET_CONFIGURATION and SET_INTERFACE. Trying to follow the databook
- * programming model in this scenario can cause errors. For two
- * reasons:
+ * Issue a %DWC3_DEPCMD_DEPSTARTCFG command to @dep. After the command's
+ * completion, it will set Transfer Resource for all available endpoints.
*
- * 1) The databook says to do DEPSTARTCFG for every SET_CONFIGURATION
- * and SET_INTERFACE (8.1.5). This is incorrect in the scenario of
- * multiple interfaces.
+ * The assignment of transfer resources cannot perfectly follow the data book
+ * due to the fact that the controller driver does not have all knowledge of the
+ * configuration in advance. It is given this information piecemeal by the
+ * composite gadget framework after every SET_CONFIGURATION and
+ * SET_INTERFACE. Trying to follow the databook programming model in this
+ * scenario can cause errors. For two reasons:
*
- * 2) The databook does not mention doing more DEPXFERCFG for new
+ * 1) The databook says to do %DWC3_DEPCMD_DEPSTARTCFG for every
+ * %USB_REQ_SET_CONFIGURATION and %USB_REQ_SET_INTERFACE (8.1.5). This is
+ * incorrect in the scenario of multiple interfaces.
+ *
+ * 2) The databook does not mention doing more %DWC3_DEPCMD_DEPXFERCFG for new
* endpoint on alt setting (8.1.6).
*
* The following simplified method is used instead:
*
- * All hardware endpoints can be assigned a transfer resource and this
- * setting will stay persistent until either a core reset or
- * hibernation. So whenever we do a DEPSTARTCFG(0) we can go ahead and
- * do DEPXFERCFG for every hardware endpoint as well. We are
+ * All hardware endpoints can be assigned a transfer resource and this setting
+ * will stay persistent until either a core reset or hibernation. So whenever we
+ * do a %DWC3_DEPCMD_DEPSTARTCFG(0) we can go ahead and do
+ * %DWC3_DEPCMD_DEPXFERCFG for every hardware endpoint as well. We are
* guaranteed that there are as many transfer resources as endpoints.
*
- * This function is called for each endpoint when it is being enabled
- * but is triggered only when called for EP0-out, which always happens
- * first, and which should only happen in one of the above conditions.
+ * This function is called for each endpoint when it is being enabled but is
+ * triggered only when called for EP0-out, which always happens first, and which
+ * should only happen in one of the above conditions.
*/
static int dwc3_gadget_start_config(struct dwc3 *dwc, struct dwc3_ep *dep)
{
@@ -569,11 +606,13 @@ static int dwc3_gadget_set_xfer_resource(struct dwc3 *dwc, struct dwc3_ep *dep)
}
/**
- * __dwc3_gadget_ep_enable - Initializes a HW endpoint
+ * __dwc3_gadget_ep_enable - initializes a hw endpoint
* @dep: endpoint to be initialized
- * @desc: USB Endpoint Descriptor
+ * @modify: if true, modify existing endpoint configuration
+ * @restore: if true, restore endpoint configuration from scratch buffer
*
- * Caller should take care of locking
+ * Caller should take care of locking. Execute all necessary commands to
+ * initialize a HW endpoint so it can be used by a gadget driver.
*/
static int __dwc3_gadget_ep_enable(struct dwc3_ep *dep,
bool modify, bool restore)
@@ -685,11 +724,13 @@ static void dwc3_remove_requests(struct dwc3 *dwc, struct dwc3_ep *dep)
}
/**
- * __dwc3_gadget_ep_disable - Disables a HW endpoint
+ * __dwc3_gadget_ep_disable - disables a hw endpoint
* @dep: the endpoint to disable
*
- * This function also removes requests which are currently processed ny the
- * hardware and those which are not yet scheduled.
+ * This function undoes what __dwc3_gadget_ep_enable did and also removes
+ * requests which are currently being processed by the hardware and those which
+ * are not yet scheduled.
+ *
* Caller should take care of locking.
*/
static int __dwc3_gadget_ep_disable(struct dwc3_ep *dep)
@@ -932,7 +973,7 @@ static void dwc3_prepare_one_trb(struct dwc3_ep *dep,
}
/**
- * dwc3_ep_prev_trb() - Returns the previous TRB in the ring
+ * dwc3_ep_prev_trb - returns the previous TRB in the ring
* @dep: The endpoint with the TRB ring
* @index: The index of the current TRB in the ring
*
@@ -953,7 +994,6 @@ static struct dwc3_trb *dwc3_ep_prev_trb(struct dwc3_ep *dep, u8 index)
static u32 dwc3_calc_trbs_left(struct dwc3_ep *dep)
{
struct dwc3_trb *tmp;
- struct dwc3 *dwc = dep->dwc;
u8 trbs_left;
/*
@@ -965,8 +1005,7 @@ static u32 dwc3_calc_trbs_left(struct dwc3_ep *dep)
*/
if (dep->trb_enqueue == dep->trb_dequeue) {
tmp = dwc3_ep_prev_trb(dep, dep->trb_enqueue);
- if (dev_WARN_ONCE(dwc->dev, tmp->ctrl & DWC3_TRB_CTRL_HWO,
- "%s No TRBS left\n", dep->name))
+ if (tmp->ctrl & DWC3_TRB_CTRL_HWO)
return 0;
return DWC3_TRB_NUM - 1;
@@ -1101,6 +1140,17 @@ static void dwc3_prepare_trbs(struct dwc3_ep *dep)
}
list_for_each_entry_safe(req, n, &dep->pending_list, list) {
+ struct dwc3 *dwc = dep->dwc;
+ int ret;
+
+ ret = usb_gadget_map_request_by_dev(dwc->sysdev, &req->request,
+ dep->direction);
+ if (ret)
+ return;
+
+ req->sg = req->request.sg;
+ req->num_pending_sgs = req->request.num_mapped_sgs;
+
if (req->num_pending_sgs > 0)
dwc3_prepare_one_trb_sg(dep, req);
else
@@ -1207,7 +1257,7 @@ static void dwc3_gadget_start_isoc(struct dwc3 *dwc,
static int __dwc3_gadget_ep_queue(struct dwc3_ep *dep, struct dwc3_request *req)
{
struct dwc3 *dwc = dep->dwc;
- int ret;
+ int ret = 0;
if (!dep->endpoint.desc) {
dev_err(dwc->dev, "%s: can't queue to disabled endpoint\n",
@@ -1215,12 +1265,9 @@ static int __dwc3_gadget_ep_queue(struct dwc3_ep *dep, struct dwc3_request *req)
return -ESHUTDOWN;
}
- if (WARN(req->dep != dep, "request %p belongs to '%s'\n",
- &req->request, req->dep->name)) {
- dev_err(dwc->dev, "%s: request %p belongs to '%s'\n",
- dep->name, &req->request, req->dep->name);
+ if (WARN(req->dep != dep, "request %pK belongs to '%s'\n",
+ &req->request, req->dep->name))
return -EINVAL;
- }
pm_runtime_get(dwc->dev);
@@ -1231,14 +1278,6 @@ static int __dwc3_gadget_ep_queue(struct dwc3_ep *dep, struct dwc3_request *req)
trace_dwc3_ep_queue(req);
- ret = usb_gadget_map_request_by_dev(dwc->sysdev, &req->request,
- dep->direction);
- if (ret)
- return ret;
-
- req->sg = req->request.sg;
- req->num_pending_sgs = req->request.num_mapped_sgs;
-
list_add_tail(&req->list, &dep->pending_list);
/*
@@ -1396,7 +1435,7 @@ static int dwc3_gadget_ep_dequeue(struct usb_ep *ep,
}
goto out1;
}
- dev_err(dwc->dev, "request %p was not queued to %s\n",
+ dev_err(dwc->dev, "request %pK was not queued to %s\n",
request, ep->name);
ret = -EINVAL;
goto out0;
@@ -1741,8 +1780,8 @@ static irqreturn_t dwc3_interrupt(int irq, void *_dwc);
static irqreturn_t dwc3_thread_interrupt(int irq, void *_dwc);
/**
- * dwc3_gadget_setup_nump - Calculate and initialize NUMP field of DCFG
- * dwc: pointer to our context structure
+ * dwc3_gadget_setup_nump - calculate and initialize NUMP field of %DWC3_DCFG
+ * @dwc: pointer to our context structure
*
* The following looks like complex but it's actually very simple. In order to
* calculate the number of packets we can burst at once on OUT transfers, we're
@@ -1798,49 +1837,6 @@ static int __dwc3_gadget_start(struct dwc3 *dwc)
dwc3_writel(dwc->regs, DWC3_DEV_IMOD(0), 0);
}
- reg = dwc3_readl(dwc->regs, DWC3_DCFG);
- reg &= ~(DWC3_DCFG_SPEED_MASK);
-
- /**
- * WORKAROUND: DWC3 revision < 2.20a have an issue
- * which would cause metastability state on Run/Stop
- * bit if we try to force the IP to USB2-only mode.
- *
- * Because of that, we cannot configure the IP to any
- * speed other than the SuperSpeed
- *
- * Refers to:
- *
- * STAR#9000525659: Clock Domain Crossing on DCTL in
- * USB 2.0 Mode
- */
- if (dwc->revision < DWC3_REVISION_220A) {
- reg |= DWC3_DCFG_SUPERSPEED;
- } else {
- switch (dwc->maximum_speed) {
- case USB_SPEED_LOW:
- reg |= DWC3_DCFG_LOWSPEED;
- break;
- case USB_SPEED_FULL:
- reg |= DWC3_DCFG_FULLSPEED;
- break;
- case USB_SPEED_HIGH:
- reg |= DWC3_DCFG_HIGHSPEED;
- break;
- case USB_SPEED_SUPER_PLUS:
- reg |= DWC3_DCFG_SUPERSPEED_PLUS;
- break;
- default:
- dev_err(dwc->dev, "invalid dwc->maximum_speed (%d)\n",
- dwc->maximum_speed);
- /* fall through */
- case USB_SPEED_SUPER:
- reg |= DWC3_DCFG_SUPERSPEED;
- break;
- }
- }
- dwc3_writel(dwc->regs, DWC3_DCFG, reg);
-
/*
* We are telling dwc3 that we want to use DCFG.NUMP as ACK TP's NUMP
* field instead of letting dwc3 itself calculate that automatically.
@@ -1972,6 +1968,63 @@ out:
return 0;
}
+static void dwc3_gadget_set_speed(struct usb_gadget *g,
+ enum usb_device_speed speed)
+{
+ struct dwc3 *dwc = gadget_to_dwc(g);
+ unsigned long flags;
+ u32 reg;
+
+ spin_lock_irqsave(&dwc->lock, flags);
+ reg = dwc3_readl(dwc->regs, DWC3_DCFG);
+ reg &= ~(DWC3_DCFG_SPEED_MASK);
+
+ /*
+ * WORKAROUND: DWC3 revision < 2.20a have an issue
+ * which would cause metastability state on Run/Stop
+ * bit if we try to force the IP to USB2-only mode.
+ *
+ * Because of that, we cannot configure the IP to any
+ * speed other than the SuperSpeed
+ *
+ * Refers to:
+ *
+ * STAR#9000525659: Clock Domain Crossing on DCTL in
+ * USB 2.0 Mode
+ */
+ if (dwc->revision < DWC3_REVISION_220A) {
+ reg |= DWC3_DCFG_SUPERSPEED;
+ } else {
+ switch (speed) {
+ case USB_SPEED_LOW:
+ reg |= DWC3_DCFG_LOWSPEED;
+ break;
+ case USB_SPEED_FULL:
+ reg |= DWC3_DCFG_FULLSPEED;
+ break;
+ case USB_SPEED_HIGH:
+ reg |= DWC3_DCFG_HIGHSPEED;
+ break;
+ case USB_SPEED_SUPER:
+ reg |= DWC3_DCFG_SUPERSPEED;
+ break;
+ case USB_SPEED_SUPER_PLUS:
+ reg |= DWC3_DCFG_SUPERSPEED_PLUS;
+ break;
+ default:
+ dev_err(dwc->dev, "invalid speed (%d)\n", speed);
+
+ if (dwc->revision & DWC3_REVISION_IS_DWC31)
+ reg |= DWC3_DCFG_SUPERSPEED_PLUS;
+ else
+ reg |= DWC3_DCFG_SUPERSPEED;
+ }
+ }
+ dwc3_writel(dwc->regs, DWC3_DCFG, reg);
+
+ spin_unlock_irqrestore(&dwc->lock, flags);
+}
+
static const struct usb_gadget_ops dwc3_gadget_ops = {
.get_frame = dwc3_gadget_get_frame,
.wakeup = dwc3_gadget_wakeup,
@@ -1979,19 +2032,21 @@ static const struct usb_gadget_ops dwc3_gadget_ops = {
.pullup = dwc3_gadget_pullup,
.udc_start = dwc3_gadget_start,
.udc_stop = dwc3_gadget_stop,
+ .udc_set_speed = dwc3_gadget_set_speed,
};
/* -------------------------------------------------------------------------- */
-static int dwc3_gadget_init_endpoints(struct dwc3 *dwc, u8 num)
+static int dwc3_gadget_init_endpoints(struct dwc3 *dwc, u8 total)
{
struct dwc3_ep *dep;
u8 epnum;
INIT_LIST_HEAD(&dwc->gadget.ep_list);
- for (epnum = 0; epnum < num; epnum++) {
+ for (epnum = 0; epnum < total; epnum++) {
bool direction = epnum & 1;
+ u8 num = epnum >> 1;
dep = kzalloc(sizeof(*dep), GFP_KERNEL);
if (!dep)
@@ -2003,7 +2058,7 @@ static int dwc3_gadget_init_endpoints(struct dwc3 *dwc, u8 num)
dep->regs = dwc->regs + DWC3_DEP_BASE(epnum);
dwc->eps[epnum] = dep;
- snprintf(dep->name, sizeof(dep->name), "ep%d%s", epnum >> 1,
+ snprintf(dep->name, sizeof(dep->name), "ep%u%s", num,
direction ? "in" : "out");
dep->endpoint.name = dep->name;
@@ -2015,39 +2070,39 @@ static int dwc3_gadget_init_endpoints(struct dwc3 *dwc, u8 num)
spin_lock_init(&dep->lock);
- if (epnum == 0 || epnum == 1) {
+ if (num == 0) {
usb_ep_set_maxpacket_limit(&dep->endpoint, 512);
dep->endpoint.maxburst = 1;
dep->endpoint.ops = &dwc3_gadget_ep0_ops;
- if (!epnum)
+ if (!direction)
dwc->gadget.ep0 = &dep->endpoint;
} else if (direction) {
int mdwidth;
+ int kbytes;
int size;
int ret;
- int num;
mdwidth = DWC3_MDWIDTH(dwc->hwparams.hwparams0);
/* MDWIDTH is represented in bits, we need it in bytes */
mdwidth /= 8;
- size = dwc3_readl(dwc->regs, DWC3_GTXFIFOSIZ(epnum >> 1));
+ size = dwc3_readl(dwc->regs, DWC3_GTXFIFOSIZ(num));
size = DWC3_GTXFIFOSIZ_TXFDEF(size);
/* FIFO Depth is in MDWDITH bytes. Multiply */
size *= mdwidth;
- num = size / 1024;
- if (num == 0)
- num = 1;
+ kbytes = size / 1024;
+ if (kbytes == 0)
+ kbytes = 1;
/*
- * FIFO sizes account an extra MDWIDTH * (num + 1) bytes for
+ * FIFO sizes account an extra MDWIDTH * (kbytes + 1) bytes for
* internal overhead. We don't really know how these are used,
* but documentation say it exists.
*/
- size -= mdwidth * (num + 1);
- size /= num;
+ size -= mdwidth * (kbytes + 1);
+ size /= kbytes;
usb_ep_set_maxpacket_limit(&dep->endpoint, size);
@@ -2073,7 +2128,7 @@ static int dwc3_gadget_init_endpoints(struct dwc3 *dwc, u8 num)
return ret;
}
- if (epnum == 0 || epnum == 1) {
+ if (num == 0) {
dep->endpoint.caps.type_control = true;
} else {
dep->endpoint.caps.type_iso = true;
@@ -2871,7 +2926,7 @@ static void dwc3_gadget_hibernation_interrupt(struct dwc3 *dwc,
{
unsigned int is_ss = evtinfo & BIT(4);
- /**
+ /*
* WORKAROUND: DWC3 revison 2.20a with hibernation support
* have a known issue which can cause USB CV TD.9.23 to fail
* randomly.
@@ -2943,20 +2998,12 @@ static void dwc3_process_event_entry(struct dwc3 *dwc,
{
trace_dwc3_event(event->raw, dwc);
- /* Endpoint IRQ, handle it and return early */
- if (event->type.is_devspec == 0) {
- /* depevt */
- return dwc3_endpoint_interrupt(dwc, &event->depevt);
- }
-
- switch (event->type.type) {
- case DWC3_EVENT_TYPE_DEV:
+ if (!event->type.is_devspec)
+ dwc3_endpoint_interrupt(dwc, &event->depevt);
+ else if (event->type.type == DWC3_EVENT_TYPE_DEV)
dwc3_gadget_interrupt(dwc, &event->devt);
- break;
- /* REVISIT what to do with Carkit and I2C events ? */
- default:
+ else
dev_err(dwc->dev, "UNKNOWN IRQ type %d\n", event->raw);
- }
}
static irqreturn_t dwc3_process_event_buf(struct dwc3_event_buffer *evt)
@@ -3110,7 +3157,7 @@ out:
}
/**
- * dwc3_gadget_init - Initializes gadget related registers
+ * dwc3_gadget_init - initializes gadget related registers
* @dwc: pointer to our controller context structure
*
* Returns 0 on success otherwise negative errno.
diff --git a/drivers/usb/dwc3/gadget.h b/drivers/usb/dwc3/gadget.h
index e4602d0e515b..4a3227543255 100644
--- a/drivers/usb/dwc3/gadget.h
+++ b/drivers/usb/dwc3/gadget.h
@@ -1,4 +1,4 @@
-/**
+/*
* gadget.h - DesignWare USB3 DRD Gadget Header
*
* Copyright (C) 2010-2011 Texas Instruments Incorporated - http://www.ti.com
@@ -60,11 +60,25 @@ struct dwc3;
#define to_dwc3_request(r) (container_of(r, struct dwc3_request, request))
+/**
+ * next_request - gets the next request on the given list
+ * @list: the request list to operate on
+ *
+ * Caller should take care of locking. This function return %NULL or the first
+ * request available on @list.
+ */
static inline struct dwc3_request *next_request(struct list_head *list)
{
return list_first_entry_or_null(list, struct dwc3_request, list);
}
+/**
+ * dwc3_gadget_move_started_request - move @req to the started_list
+ * @req: the request to be moved
+ *
+ * Caller should take care of locking. This function will move @req from its
+ * current list to the endpoint's started_list.
+ */
static inline void dwc3_gadget_move_started_request(struct dwc3_request *req)
{
struct dwc3_ep *dep = req->dep;
@@ -87,10 +101,10 @@ int __dwc3_gadget_ep_set_halt(struct dwc3_ep *dep, int value, int protocol);
/**
* dwc3_gadget_ep_get_transfer_index - Gets transfer index from HW
- * @dwc: DesignWare USB3 Pointer
- * @number: DWC endpoint number
+ * @dep: dwc3 endpoint
*
- * Caller should take care of locking
+ * Caller should take care of locking. Returns the transfer resource
+ * index for a given endpoint.
*/
static inline u32 dwc3_gadget_ep_get_transfer_index(struct dwc3_ep *dep)
{
diff --git a/drivers/usb/dwc3/trace.h b/drivers/usb/dwc3/trace.h
index f1bd444d22a3..6504b116da04 100644
--- a/drivers/usb/dwc3/trace.h
+++ b/drivers/usb/dwc3/trace.h
@@ -60,13 +60,15 @@ DECLARE_EVENT_CLASS(dwc3_log_event,
TP_STRUCT__entry(
__field(u32, event)
__field(u32, ep0state)
+ __dynamic_array(char, str, DWC3_MSG_MAX)
),
TP_fast_assign(
__entry->event = event;
__entry->ep0state = dwc->ep0state;
),
TP_printk("event (%08x): %s", __entry->event,
- dwc3_decode_event(__entry->event, __entry->ep0state))
+ dwc3_decode_event(__get_str(str), __entry->event,
+ __entry->ep0state))
);
DEFINE_EVENT(dwc3_log_event, dwc3_event,
@@ -83,6 +85,7 @@ DECLARE_EVENT_CLASS(dwc3_log_ctrl,
__field(__u16, wValue)
__field(__u16, wIndex)
__field(__u16, wLength)
+ __dynamic_array(char, str, DWC3_MSG_MAX)
),
TP_fast_assign(
__entry->bRequestType = ctrl->bRequestType;
@@ -91,10 +94,9 @@ DECLARE_EVENT_CLASS(dwc3_log_ctrl,
__entry->wIndex = le16_to_cpu(ctrl->wIndex);
__entry->wLength = le16_to_cpu(ctrl->wLength);
),
- TP_printk("bRequestType %02x bRequest %02x wValue %04x wIndex %04x wLength %d",
- __entry->bRequestType, __entry->bRequest,
- __entry->wValue, __entry->wIndex,
- __entry->wLength
+ TP_printk("%s", dwc3_decode_ctrl(__get_str(str), __entry->bRequestType,
+ __entry->bRequest, __entry->wValue,
+ __entry->wIndex, __entry->wLength)
)
);
@@ -107,7 +109,7 @@ DECLARE_EVENT_CLASS(dwc3_log_request,
TP_PROTO(struct dwc3_request *req),
TP_ARGS(req),
TP_STRUCT__entry(
- __dynamic_array(char, name, DWC3_MSG_MAX)
+ __string(name, req->dep->name)
__field(struct dwc3_request *, req)
__field(unsigned, actual)
__field(unsigned, length)
@@ -117,7 +119,7 @@ DECLARE_EVENT_CLASS(dwc3_log_request,
__field(int, no_interrupt)
),
TP_fast_assign(
- snprintf(__get_str(name), DWC3_MSG_MAX, "%s", req->dep->name);
+ __assign_str(name, req->dep->name);
__entry->req = req;
__entry->actual = req->request.actual;
__entry->length = req->request.length;
@@ -190,7 +192,7 @@ DECLARE_EVENT_CLASS(dwc3_log_gadget_ep_cmd,
struct dwc3_gadget_ep_cmd_params *params, int cmd_status),
TP_ARGS(dep, cmd, params, cmd_status),
TP_STRUCT__entry(
- __dynamic_array(char, name, DWC3_MSG_MAX)
+ __string(name, dep->name)
__field(unsigned int, cmd)
__field(u32, param0)
__field(u32, param1)
@@ -198,7 +200,7 @@ DECLARE_EVENT_CLASS(dwc3_log_gadget_ep_cmd,
__field(int, cmd_status)
),
TP_fast_assign(
- snprintf(__get_str(name), DWC3_MSG_MAX, "%s", dep->name);
+ __assign_str(name, dep->name);
__entry->cmd = cmd;
__entry->param0 = params->param0;
__entry->param1 = params->param1;
@@ -223,7 +225,7 @@ DECLARE_EVENT_CLASS(dwc3_log_trb,
TP_PROTO(struct dwc3_ep *dep, struct dwc3_trb *trb),
TP_ARGS(dep, trb),
TP_STRUCT__entry(
- __dynamic_array(char, name, DWC3_MSG_MAX)
+ __string(name, dep->name)
__field(struct dwc3_trb *, trb)
__field(u32, allocated)
__field(u32, queued)
@@ -234,7 +236,7 @@ DECLARE_EVENT_CLASS(dwc3_log_trb,
__field(u32, type)
),
TP_fast_assign(
- snprintf(__get_str(name), DWC3_MSG_MAX, "%s", dep->name);
+ __assign_str(name, dep->name);
__entry->trb = trb;
__entry->allocated = dep->allocated_requests;
__entry->queued = dep->queued_requests;
@@ -291,7 +293,7 @@ DECLARE_EVENT_CLASS(dwc3_log_ep,
TP_PROTO(struct dwc3_ep *dep),
TP_ARGS(dep),
TP_STRUCT__entry(
- __dynamic_array(char, name, DWC3_MSG_MAX)
+ __string(name, dep->name)
__field(unsigned, maxpacket)
__field(unsigned, maxpacket_limit)
__field(unsigned, max_streams)
@@ -302,7 +304,7 @@ DECLARE_EVENT_CLASS(dwc3_log_ep,
__field(u8, trb_dequeue)
),
TP_fast_assign(
- snprintf(__get_str(name), DWC3_MSG_MAX, "%s", dep->name);
+ __assign_str(name, dep->name);
__entry->maxpacket = dep->endpoint.maxpacket;
__entry->maxpacket_limit = dep->endpoint.maxpacket_limit;
__entry->max_streams = dep->endpoint.max_streams;
diff --git a/drivers/usb/dwc3/ulpi.c b/drivers/usb/dwc3/ulpi.c
index bd86f84f3790..e87ce8e9edee 100644
--- a/drivers/usb/dwc3/ulpi.c
+++ b/drivers/usb/dwc3/ulpi.c
@@ -41,6 +41,12 @@ static int dwc3_ulpi_read(struct device *dev, u8 addr)
u32 reg;
int ret;
+ reg = dwc3_readl(dwc->regs, DWC3_GUSB2PHYCFG(0));
+ if (reg & DWC3_GUSB2PHYCFG_SUSPHY) {
+ reg &= ~DWC3_GUSB2PHYCFG_SUSPHY;
+ dwc3_writel(dwc->regs, DWC3_GUSB2PHYCFG(0), reg);
+ }
+
reg = DWC3_GUSB2PHYACC_NEWREGREQ | DWC3_ULPI_ADDR(addr);
dwc3_writel(dwc->regs, DWC3_GUSB2PHYACC(0), reg);
@@ -58,6 +64,12 @@ static int dwc3_ulpi_write(struct device *dev, u8 addr, u8 val)
struct dwc3 *dwc = dev_get_drvdata(dev);
u32 reg;
+ reg = dwc3_readl(dwc->regs, DWC3_GUSB2PHYCFG(0));
+ if (reg & DWC3_GUSB2PHYCFG_SUSPHY) {
+ reg &= ~DWC3_GUSB2PHYCFG_SUSPHY;
+ dwc3_writel(dwc->regs, DWC3_GUSB2PHYCFG(0), reg);
+ }
+
reg = DWC3_GUSB2PHYACC_NEWREGREQ | DWC3_ULPI_ADDR(addr);
reg |= DWC3_GUSB2PHYACC_WRITE | val;
dwc3_writel(dwc->regs, DWC3_GUSB2PHYACC(0), reg);
diff --git a/drivers/usb/early/xhci-dbc.c b/drivers/usb/early/xhci-dbc.c
index 1268818e2263..12fe70beae69 100644
--- a/drivers/usb/early/xhci-dbc.c
+++ b/drivers/usb/early/xhci-dbc.c
@@ -32,7 +32,6 @@
static struct xdbc_state xdbc;
static bool early_console_keep;
-#define XDBC_TRACE
#ifdef XDBC_TRACE
#define xdbc_trace trace_printk
#else
diff --git a/drivers/usb/gadget/Kconfig b/drivers/usb/gadget/Kconfig
index c164d6b788c3..35cc641d9f31 100644
--- a/drivers/usb/gadget/Kconfig
+++ b/drivers/usb/gadget/Kconfig
@@ -41,7 +41,7 @@ menuconfig USB_GADGET
don't have this kind of hardware (except maybe inside Linux PDAs).
For more information, see <http://www.linux-usb.org/gadget> and
- the kernel DocBook documentation for this API.
+ the kernel documentation for this API.
if USB_GADGET
@@ -158,6 +158,9 @@ config USB_U_SERIAL
config USB_U_ETHER
tristate
+config USB_U_AUDIO
+ tristate
+
config USB_F_SERIAL
tristate
@@ -191,6 +194,9 @@ config USB_F_FS
config USB_F_UAC1
tristate
+config USB_F_UAC1_LEGACY
+ tristate
+
config USB_F_UAC2
tristate
@@ -368,12 +374,30 @@ config USB_CONFIGFS_F_UAC1
depends on SND
select USB_LIBCOMPOSITE
select SND_PCM
+ select USB_U_AUDIO
select USB_F_UAC1
help
This Audio function implements 1 AudioControl interface,
1 AudioStreaming Interface each for USB-OUT and USB-IN.
- This driver requires a real Audio codec to be present
- on the device.
+ This driver doesn't expect any real Audio codec to be present
+ on the device - the audio streams are simply sinked to and
+ sourced from a virtual ALSA sound card created. The user-space
+ application may choose to do whatever it wants with the data
+ received from the USB Host and choose to provide whatever it
+ wants as audio data to the USB Host.
+
+config USB_CONFIGFS_F_UAC1_LEGACY
+ bool "Audio Class 1.0 (legacy implementation)"
+ depends on USB_CONFIGFS
+ depends on SND
+ select USB_LIBCOMPOSITE
+ select SND_PCM
+ select USB_F_UAC1_LEGACY
+ help
+ This Audio function implements 1 AudioControl interface,
+ 1 AudioStreaming Interface each for USB-OUT and USB-IN.
+ This is a legacy driver and requires a real Audio codec
+ to be present on the device.
config USB_CONFIGFS_F_UAC2
bool "Audio Class 2.0"
@@ -381,6 +405,7 @@ config USB_CONFIGFS_F_UAC2
depends on SND
select USB_LIBCOMPOSITE
select SND_PCM
+ select USB_U_AUDIO
select USB_F_UAC2
help
This Audio function is compatible with USB Audio Class
diff --git a/drivers/usb/gadget/composite.c b/drivers/usb/gadget/composite.c
index 49d685ad0da9..dd74c99d6ce1 100644
--- a/drivers/usb/gadget/composite.c
+++ b/drivers/usb/gadget/composite.c
@@ -315,6 +315,9 @@ void usb_remove_function(struct usb_configuration *c, struct usb_function *f)
list_del(&f->list);
if (f->unbind)
f->unbind(c, f);
+
+ if (f->bind_deactivated)
+ usb_function_activate(f);
}
EXPORT_SYMBOL_GPL(usb_remove_function);
@@ -607,7 +610,6 @@ static int count_configs(struct usb_composite_dev *cdev, unsigned type)
static int bos_desc(struct usb_composite_dev *cdev)
{
struct usb_ext_cap_descriptor *usb_ext;
- struct usb_ss_cap_descriptor *ss_cap;
struct usb_dcd_config_params dcd_config_params;
struct usb_bos_descriptor *bos = cdev->req->buf;
@@ -633,29 +635,35 @@ static int bos_desc(struct usb_composite_dev *cdev)
* The Superspeed USB Capability descriptor shall be implemented by all
* SuperSpeed devices.
*/
- ss_cap = cdev->req->buf + le16_to_cpu(bos->wTotalLength);
- bos->bNumDeviceCaps++;
- le16_add_cpu(&bos->wTotalLength, USB_DT_USB_SS_CAP_SIZE);
- ss_cap->bLength = USB_DT_USB_SS_CAP_SIZE;
- ss_cap->bDescriptorType = USB_DT_DEVICE_CAPABILITY;
- ss_cap->bDevCapabilityType = USB_SS_CAP_TYPE;
- ss_cap->bmAttributes = 0; /* LTM is not supported yet */
- ss_cap->wSpeedSupported = cpu_to_le16(USB_LOW_SPEED_OPERATION |
- USB_FULL_SPEED_OPERATION |
- USB_HIGH_SPEED_OPERATION |
- USB_5GBPS_OPERATION);
- ss_cap->bFunctionalitySupport = USB_LOW_SPEED_OPERATION;
-
- /* Get Controller configuration */
- if (cdev->gadget->ops->get_config_params)
- cdev->gadget->ops->get_config_params(&dcd_config_params);
- else {
- dcd_config_params.bU1devExitLat = USB_DEFAULT_U1_DEV_EXIT_LAT;
- dcd_config_params.bU2DevExitLat =
- cpu_to_le16(USB_DEFAULT_U2_DEV_EXIT_LAT);
+ if (gadget_is_superspeed(cdev->gadget)) {
+ struct usb_ss_cap_descriptor *ss_cap;
+
+ ss_cap = cdev->req->buf + le16_to_cpu(bos->wTotalLength);
+ bos->bNumDeviceCaps++;
+ le16_add_cpu(&bos->wTotalLength, USB_DT_USB_SS_CAP_SIZE);
+ ss_cap->bLength = USB_DT_USB_SS_CAP_SIZE;
+ ss_cap->bDescriptorType = USB_DT_DEVICE_CAPABILITY;
+ ss_cap->bDevCapabilityType = USB_SS_CAP_TYPE;
+ ss_cap->bmAttributes = 0; /* LTM is not supported yet */
+ ss_cap->wSpeedSupported = cpu_to_le16(USB_LOW_SPEED_OPERATION |
+ USB_FULL_SPEED_OPERATION |
+ USB_HIGH_SPEED_OPERATION |
+ USB_5GBPS_OPERATION);
+ ss_cap->bFunctionalitySupport = USB_LOW_SPEED_OPERATION;
+
+ /* Get Controller configuration */
+ if (cdev->gadget->ops->get_config_params) {
+ cdev->gadget->ops->get_config_params(
+ &dcd_config_params);
+ } else {
+ dcd_config_params.bU1devExitLat =
+ USB_DEFAULT_U1_DEV_EXIT_LAT;
+ dcd_config_params.bU2DevExitLat =
+ cpu_to_le16(USB_DEFAULT_U2_DEV_EXIT_LAT);
+ }
+ ss_cap->bU1devExitLat = dcd_config_params.bU1devExitLat;
+ ss_cap->bU2DevExitLat = dcd_config_params.bU2DevExitLat;
}
- ss_cap->bU1devExitLat = dcd_config_params.bU1devExitLat;
- ss_cap->bU2DevExitLat = dcd_config_params.bU2DevExitLat;
/* The SuperSpeedPlus USB Device Capability descriptor */
if (gadget_is_superspeed_plus(cdev->gadget)) {
@@ -956,12 +964,8 @@ static void remove_config(struct usb_composite_dev *cdev,
f = list_first_entry(&config->functions,
struct usb_function, list);
- list_del(&f->list);
- if (f->unbind) {
- DBG(cdev, "unbind function '%s'/%p\n", f->name, f);
- f->unbind(config, f);
- /* may free memory for "f" */
- }
+
+ usb_remove_function(config, f);
}
list_del(&config->list);
if (config->unbind) {
@@ -1603,7 +1607,10 @@ composite_setup(struct usb_gadget *gadget, const struct usb_ctrlrequest *ctrl)
cdev->desc.bcdUSB = cpu_to_le16(0x0210);
}
} else {
- cdev->desc.bcdUSB = cpu_to_le16(0x0200);
+ if (gadget->lpm_capable)
+ cdev->desc.bcdUSB = cpu_to_le16(0x0201);
+ else
+ cdev->desc.bcdUSB = cpu_to_le16(0x0200);
}
value = min(w_length, (u16) sizeof cdev->desc);
@@ -1634,7 +1641,8 @@ composite_setup(struct usb_gadget *gadget, const struct usb_ctrlrequest *ctrl)
value = min(w_length, (u16) value);
break;
case USB_DT_BOS:
- if (gadget_is_superspeed(gadget)) {
+ if (gadget_is_superspeed(gadget) ||
+ gadget->lpm_capable) {
value = bos_desc(cdev);
value = min(w_length, (u16) value);
}
diff --git a/drivers/usb/gadget/configfs.c b/drivers/usb/gadget/configfs.c
index cbff3b02840d..a22a892de7b7 100644
--- a/drivers/usb/gadget/configfs.c
+++ b/drivers/usb/gadget/configfs.c
@@ -738,7 +738,7 @@ static inline struct gadget_info *os_desc_item_to_gadget_info(
static ssize_t os_desc_use_show(struct config_item *item, char *page)
{
- return sprintf(page, "%d",
+ return sprintf(page, "%d\n",
os_desc_item_to_gadget_info(item)->use_os_desc);
}
@@ -762,7 +762,7 @@ static ssize_t os_desc_use_store(struct config_item *item, const char *page,
static ssize_t os_desc_b_vendor_code_show(struct config_item *item, char *page)
{
- return sprintf(page, "%d",
+ return sprintf(page, "0x%02x\n",
os_desc_item_to_gadget_info(item)->b_vendor_code);
}
@@ -787,9 +787,13 @@ static ssize_t os_desc_b_vendor_code_store(struct config_item *item,
static ssize_t os_desc_qw_sign_show(struct config_item *item, char *page)
{
struct gadget_info *gi = os_desc_item_to_gadget_info(item);
+ int res;
+
+ res = utf16s_to_utf8s((wchar_t *) gi->qw_sign, OS_STRING_QW_SIGN_LEN,
+ UTF16_LITTLE_ENDIAN, page, PAGE_SIZE - 1);
+ page[res++] = '\n';
- memcpy(page, gi->qw_sign, OS_STRING_QW_SIGN_LEN);
- return OS_STRING_QW_SIGN_LEN;
+ return res;
}
static ssize_t os_desc_qw_sign_store(struct config_item *item, const char *page,
@@ -900,7 +904,7 @@ static inline struct usb_os_desc_ext_prop
static ssize_t ext_prop_type_show(struct config_item *item, char *page)
{
- return sprintf(page, "%d", to_usb_os_desc_ext_prop(item)->type);
+ return sprintf(page, "%d\n", to_usb_os_desc_ext_prop(item)->type);
}
static ssize_t ext_prop_type_store(struct config_item *item,
diff --git a/drivers/usb/gadget/function/Makefile b/drivers/usb/gadget/function/Makefile
index cb8c225e8549..86e825269947 100644
--- a/drivers/usb/gadget/function/Makefile
+++ b/drivers/usb/gadget/function/Makefile
@@ -32,8 +32,11 @@ usb_f_mass_storage-y := f_mass_storage.o storage_common.o
obj-$(CONFIG_USB_F_MASS_STORAGE)+= usb_f_mass_storage.o
usb_f_fs-y := f_fs.o
obj-$(CONFIG_USB_F_FS) += usb_f_fs.o
-usb_f_uac1-y := f_uac1.o u_uac1.o
+obj-$(CONFIG_USB_U_AUDIO) += u_audio.o
+usb_f_uac1-y := f_uac1.o
obj-$(CONFIG_USB_F_UAC1) += usb_f_uac1.o
+usb_f_uac1_legacy-y := f_uac1_legacy.o u_uac1_legacy.o
+obj-$(CONFIG_USB_F_UAC1_LEGACY) += usb_f_uac1_legacy.o
usb_f_uac2-y := f_uac2.o
obj-$(CONFIG_USB_F_UAC2) += usb_f_uac2.o
usb_f_uvc-y := f_uvc.o uvc_queue.o uvc_v4l2.o uvc_video.o uvc_configfs.o
diff --git a/drivers/usb/gadget/function/f_fs.c b/drivers/usb/gadget/function/f_fs.c
index 47dda3450abd..d21874b35cf6 100644
--- a/drivers/usb/gadget/function/f_fs.c
+++ b/drivers/usb/gadget/function/f_fs.c
@@ -127,7 +127,6 @@ struct ffs_ep {
struct ffs_epfile {
/* Protects ep->ep and ep->req. */
struct mutex mutex;
- wait_queue_head_t wait;
struct ffs_data *ffs;
struct ffs_ep *ep; /* P: ffs->eps_lock */
@@ -889,7 +888,8 @@ static ssize_t ffs_epfile_io(struct file *file, struct ffs_io_data *io_data)
if (file->f_flags & O_NONBLOCK)
return -EAGAIN;
- ret = wait_event_interruptible(epfile->wait, (ep = epfile->ep));
+ ret = wait_event_interruptible(
+ epfile->ffs->wait, (ep = epfile->ep));
if (ret)
return -EINTR;
}
@@ -1189,6 +1189,7 @@ static long ffs_epfile_ioctl(struct file *file, unsigned code,
unsigned long value)
{
struct ffs_epfile *epfile = file->private_data;
+ struct ffs_ep *ep;
int ret;
ENTER();
@@ -1196,50 +1197,65 @@ static long ffs_epfile_ioctl(struct file *file, unsigned code,
if (WARN_ON(epfile->ffs->state != FFS_ACTIVE))
return -ENODEV;
+ /* Wait for endpoint to be enabled */
+ ep = epfile->ep;
+ if (!ep) {
+ if (file->f_flags & O_NONBLOCK)
+ return -EAGAIN;
+
+ ret = wait_event_interruptible(
+ epfile->ffs->wait, (ep = epfile->ep));
+ if (ret)
+ return -EINTR;
+ }
+
spin_lock_irq(&epfile->ffs->eps_lock);
- if (likely(epfile->ep)) {
- switch (code) {
- case FUNCTIONFS_FIFO_STATUS:
- ret = usb_ep_fifo_status(epfile->ep->ep);
- break;
- case FUNCTIONFS_FIFO_FLUSH:
- usb_ep_fifo_flush(epfile->ep->ep);
- ret = 0;
- break;
- case FUNCTIONFS_CLEAR_HALT:
- ret = usb_ep_clear_halt(epfile->ep->ep);
- break;
- case FUNCTIONFS_ENDPOINT_REVMAP:
- ret = epfile->ep->num;
- break;
- case FUNCTIONFS_ENDPOINT_DESC:
- {
- int desc_idx;
- struct usb_endpoint_descriptor *desc;
- switch (epfile->ffs->gadget->speed) {
- case USB_SPEED_SUPER:
- desc_idx = 2;
- break;
- case USB_SPEED_HIGH:
- desc_idx = 1;
- break;
- default:
- desc_idx = 0;
- }
- desc = epfile->ep->descs[desc_idx];
+ /* In the meantime, endpoint got disabled or changed. */
+ if (epfile->ep != ep) {
+ spin_unlock_irq(&epfile->ffs->eps_lock);
+ return -ESHUTDOWN;
+ }
- spin_unlock_irq(&epfile->ffs->eps_lock);
- ret = copy_to_user((void *)value, desc, desc->bLength);
- if (ret)
- ret = -EFAULT;
- return ret;
- }
+ switch (code) {
+ case FUNCTIONFS_FIFO_STATUS:
+ ret = usb_ep_fifo_status(epfile->ep->ep);
+ break;
+ case FUNCTIONFS_FIFO_FLUSH:
+ usb_ep_fifo_flush(epfile->ep->ep);
+ ret = 0;
+ break;
+ case FUNCTIONFS_CLEAR_HALT:
+ ret = usb_ep_clear_halt(epfile->ep->ep);
+ break;
+ case FUNCTIONFS_ENDPOINT_REVMAP:
+ ret = epfile->ep->num;
+ break;
+ case FUNCTIONFS_ENDPOINT_DESC:
+ {
+ int desc_idx;
+ struct usb_endpoint_descriptor *desc;
+
+ switch (epfile->ffs->gadget->speed) {
+ case USB_SPEED_SUPER:
+ desc_idx = 2;
+ break;
+ case USB_SPEED_HIGH:
+ desc_idx = 1;
+ break;
default:
- ret = -ENOTTY;
+ desc_idx = 0;
}
- } else {
- ret = -ENODEV;
+ desc = epfile->ep->descs[desc_idx];
+
+ spin_unlock_irq(&epfile->ffs->eps_lock);
+ ret = copy_to_user((void *)value, desc, desc->bLength);
+ if (ret)
+ ret = -EFAULT;
+ return ret;
+ }
+ default:
+ ret = -ENOTTY;
}
spin_unlock_irq(&epfile->ffs->eps_lock);
@@ -1593,7 +1609,8 @@ static void ffs_data_put(struct ffs_data *ffs)
pr_info("%s(): freeing\n", __func__);
ffs_data_clear(ffs);
BUG_ON(waitqueue_active(&ffs->ev.waitq) ||
- waitqueue_active(&ffs->ep0req_completion.wait));
+ waitqueue_active(&ffs->ep0req_completion.wait) ||
+ waitqueue_active(&ffs->wait));
kfree(ffs->dev_name);
kfree(ffs);
}
@@ -1640,6 +1657,7 @@ static struct ffs_data *ffs_data_new(void)
mutex_init(&ffs->mutex);
spin_lock_init(&ffs->eps_lock);
init_waitqueue_head(&ffs->ev.waitq);
+ init_waitqueue_head(&ffs->wait);
init_completion(&ffs->ep0req_completion);
/* XXX REVISIT need to update it in some places, or do we? */
@@ -1761,7 +1779,6 @@ static int ffs_epfiles_create(struct ffs_data *ffs)
for (i = 1; i <= count; ++i, ++epfile) {
epfile->ffs = ffs;
mutex_init(&epfile->mutex);
- init_waitqueue_head(&epfile->wait);
if (ffs->user_flags & FUNCTIONFS_VIRTUAL_ADDR)
sprintf(epfile->name, "ep%02x", ffs->eps_addrmap[i]);
else
@@ -1786,8 +1803,7 @@ static void ffs_epfiles_destroy(struct ffs_epfile *epfiles, unsigned count)
ENTER();
for (; count; --count, ++epfile) {
- BUG_ON(mutex_is_locked(&epfile->mutex) ||
- waitqueue_active(&epfile->wait));
+ BUG_ON(mutex_is_locked(&epfile->mutex));
if (epfile->dentry) {
d_delete(epfile->dentry);
dput(epfile->dentry);
@@ -1874,11 +1890,11 @@ static int ffs_func_eps_enable(struct ffs_function *func)
break;
}
- wake_up(&epfile->wait);
-
++ep;
++epfile;
}
+
+ wake_up_interruptible(&ffs->wait);
spin_unlock_irqrestore(&func->ffs->eps_lock, flags);
return ret;
diff --git a/drivers/usb/gadget/function/f_mass_storage.c b/drivers/usb/gadget/function/f_mass_storage.c
index 4c8aacc232c0..e80b9c123a9d 100644
--- a/drivers/usb/gadget/function/f_mass_storage.c
+++ b/drivers/usb/gadget/function/f_mass_storage.c
@@ -260,12 +260,13 @@ struct fsg_common {
struct usb_gadget *gadget;
struct usb_composite_dev *cdev;
struct fsg_dev *fsg, *new_fsg;
+ wait_queue_head_t io_wait;
wait_queue_head_t fsg_wait;
/* filesem protects: backing files in use */
struct rw_semaphore filesem;
- /* lock protects: state, all the req_busy's */
+ /* lock protects: state and thread_task */
spinlock_t lock;
struct usb_ep *ep0; /* Copy of gadget->ep0 */
@@ -303,7 +304,6 @@ struct fsg_common {
unsigned int running:1;
unsigned int sysfs:1;
- int thread_wakeup_needed;
struct completion thread_notifier;
struct task_struct *thread_task;
@@ -355,7 +355,7 @@ typedef void (*fsg_routine_t)(struct fsg_dev *);
static int exception_in_progress(struct fsg_common *common)
{
- return common->state > FSG_STATE_IDLE;
+ return common->state > FSG_STATE_NORMAL;
}
/* Make bulk-out requests be divisible by the maxpacket size */
@@ -393,16 +393,6 @@ static int fsg_set_halt(struct fsg_dev *fsg, struct usb_ep *ep)
/* These routines may be called in process context or in_irq */
-/* Caller must hold fsg->lock */
-static void wakeup_thread(struct fsg_common *common)
-{
- smp_wmb(); /* ensure the write of bh->state is complete */
- /* Tell the main thread that something has happened */
- common->thread_wakeup_needed = 1;
- if (common->thread_task)
- wake_up_process(common->thread_task);
-}
-
static void raise_exception(struct fsg_common *common, enum fsg_state new_state)
{
unsigned long flags;
@@ -456,13 +446,9 @@ static void bulk_in_complete(struct usb_ep *ep, struct usb_request *req)
if (req->status == -ECONNRESET) /* Request was cancelled */
usb_ep_fifo_flush(ep);
- /* Hold the lock while we update the request and buffer states */
- smp_wmb();
- spin_lock(&common->lock);
- bh->inreq_busy = 0;
- bh->state = BUF_STATE_EMPTY;
- wakeup_thread(common);
- spin_unlock(&common->lock);
+ /* Synchronize with the smp_load_acquire() in sleep_thread() */
+ smp_store_release(&bh->state, BUF_STATE_EMPTY);
+ wake_up(&common->io_wait);
}
static void bulk_out_complete(struct usb_ep *ep, struct usb_request *req)
@@ -477,13 +463,9 @@ static void bulk_out_complete(struct usb_ep *ep, struct usb_request *req)
if (req->status == -ECONNRESET) /* Request was cancelled */
usb_ep_fifo_flush(ep);
- /* Hold the lock while we update the request and buffer states */
- smp_wmb();
- spin_lock(&common->lock);
- bh->outreq_busy = 0;
- bh->state = BUF_STATE_FULL;
- wakeup_thread(common);
- spin_unlock(&common->lock);
+ /* Synchronize with the smp_load_acquire() in sleep_thread() */
+ smp_store_release(&bh->state, BUF_STATE_FULL);
+ wake_up(&common->io_wait);
}
static int _fsg_common_get_max_lun(struct fsg_common *common)
@@ -528,7 +510,7 @@ static int fsg_setup(struct usb_function *f,
* and reinitialize our state.
*/
DBG(fsg, "bulk reset request\n");
- raise_exception(fsg->common, FSG_STATE_RESET);
+ raise_exception(fsg->common, FSG_STATE_PROTOCOL_RESET);
return USB_GADGET_DELAYED_STATUS;
case US_BULK_GET_MAX_LUN:
@@ -559,43 +541,39 @@ static int fsg_setup(struct usb_function *f,
/* All the following routines run in process context */
/* Use this for bulk or interrupt transfers, not ep0 */
-static void start_transfer(struct fsg_dev *fsg, struct usb_ep *ep,
- struct usb_request *req, int *pbusy,
- enum fsg_buffer_state *state)
+static int start_transfer(struct fsg_dev *fsg, struct usb_ep *ep,
+ struct usb_request *req)
{
int rc;
if (ep == fsg->bulk_in)
dump_msg(fsg, "bulk-in", req->buf, req->length);
- spin_lock_irq(&fsg->common->lock);
- *pbusy = 1;
- *state = BUF_STATE_BUSY;
- spin_unlock_irq(&fsg->common->lock);
-
rc = usb_ep_queue(ep, req, GFP_KERNEL);
- if (rc == 0)
- return; /* All good, we're done */
-
- *pbusy = 0;
- *state = BUF_STATE_EMPTY;
+ if (rc) {
- /* We can't do much more than wait for a reset */
+ /* We can't do much more than wait for a reset */
+ req->status = rc;
- /*
- * Note: currently the net2280 driver fails zero-length
- * submissions if DMA is enabled.
- */
- if (rc != -ESHUTDOWN && !(rc == -EOPNOTSUPP && req->length == 0))
- WARNING(fsg, "error in submission: %s --> %d\n", ep->name, rc);
+ /*
+ * Note: currently the net2280 driver fails zero-length
+ * submissions if DMA is enabled.
+ */
+ if (rc != -ESHUTDOWN &&
+ !(rc == -EOPNOTSUPP && req->length == 0))
+ WARNING(fsg, "error in submission: %s --> %d\n",
+ ep->name, rc);
+ }
+ return rc;
}
static bool start_in_transfer(struct fsg_common *common, struct fsg_buffhd *bh)
{
if (!fsg_is_set(common))
return false;
- start_transfer(common->fsg, common->fsg->bulk_in,
- bh->inreq, &bh->inreq_busy, &bh->state);
+ bh->state = BUF_STATE_SENDING;
+ if (start_transfer(common->fsg, common->fsg->bulk_in, bh->inreq))
+ bh->state = BUF_STATE_EMPTY;
return true;
}
@@ -603,32 +581,31 @@ static bool start_out_transfer(struct fsg_common *common, struct fsg_buffhd *bh)
{
if (!fsg_is_set(common))
return false;
- start_transfer(common->fsg, common->fsg->bulk_out,
- bh->outreq, &bh->outreq_busy, &bh->state);
+ bh->state = BUF_STATE_RECEIVING;
+ if (start_transfer(common->fsg, common->fsg->bulk_out, bh->outreq))
+ bh->state = BUF_STATE_FULL;
return true;
}
-static int sleep_thread(struct fsg_common *common, bool can_freeze)
+static int sleep_thread(struct fsg_common *common, bool can_freeze,
+ struct fsg_buffhd *bh)
{
- int rc = 0;
+ int rc;
- /* Wait until a signal arrives or we are woken up */
- for (;;) {
- if (can_freeze)
- try_to_freeze();
- set_current_state(TASK_INTERRUPTIBLE);
- if (signal_pending(current)) {
- rc = -EINTR;
- break;
- }
- if (common->thread_wakeup_needed)
- break;
- schedule();
- }
- __set_current_state(TASK_RUNNING);
- common->thread_wakeup_needed = 0;
- smp_rmb(); /* ensure the latest bh->state is visible */
- return rc;
+ /* Wait until a signal arrives or bh is no longer busy */
+ if (can_freeze)
+ /*
+ * synchronize with the smp_store_release(&bh->state) in
+ * bulk_in_complete() or bulk_out_complete()
+ */
+ rc = wait_event_freezable(common->io_wait,
+ bh && smp_load_acquire(&bh->state) >=
+ BUF_STATE_EMPTY);
+ else
+ rc = wait_event_interruptible(common->io_wait,
+ bh && smp_load_acquire(&bh->state) >=
+ BUF_STATE_EMPTY);
+ return rc ? -EINTR : 0;
}
@@ -688,11 +665,9 @@ static int do_read(struct fsg_common *common)
/* Wait for the next buffer to become available */
bh = common->next_buffhd_to_fill;
- while (bh->state != BUF_STATE_EMPTY) {
- rc = sleep_thread(common, false);
- if (rc)
- return rc;
- }
+ rc = sleep_thread(common, false, bh);
+ if (rc)
+ return rc;
/*
* If we were asked to read past the end of file,
@@ -869,84 +844,80 @@ static int do_write(struct fsg_common *common)
bh = common->next_buffhd_to_drain;
if (bh->state == BUF_STATE_EMPTY && !get_some_more)
break; /* We stopped early */
- if (bh->state == BUF_STATE_FULL) {
- smp_rmb();
- common->next_buffhd_to_drain = bh->next;
- bh->state = BUF_STATE_EMPTY;
-
- /* Did something go wrong with the transfer? */
- if (bh->outreq->status != 0) {
- curlun->sense_data = SS_COMMUNICATION_FAILURE;
- curlun->sense_data_info =
+
+ /* Wait for the data to be received */
+ rc = sleep_thread(common, false, bh);
+ if (rc)
+ return rc;
+
+ common->next_buffhd_to_drain = bh->next;
+ bh->state = BUF_STATE_EMPTY;
+
+ /* Did something go wrong with the transfer? */
+ if (bh->outreq->status != 0) {
+ curlun->sense_data = SS_COMMUNICATION_FAILURE;
+ curlun->sense_data_info =
file_offset >> curlun->blkbits;
- curlun->info_valid = 1;
- break;
- }
+ curlun->info_valid = 1;
+ break;
+ }
- amount = bh->outreq->actual;
- if (curlun->file_length - file_offset < amount) {
- LERROR(curlun,
- "write %u @ %llu beyond end %llu\n",
+ amount = bh->outreq->actual;
+ if (curlun->file_length - file_offset < amount) {
+ LERROR(curlun, "write %u @ %llu beyond end %llu\n",
amount, (unsigned long long)file_offset,
(unsigned long long)curlun->file_length);
- amount = curlun->file_length - file_offset;
- }
+ amount = curlun->file_length - file_offset;
+ }
- /* Don't accept excess data. The spec doesn't say
- * what to do in this case. We'll ignore the error.
- */
- amount = min(amount, bh->bulk_out_intended_length);
-
- /* Don't write a partial block */
- amount = round_down(amount, curlun->blksize);
- if (amount == 0)
- goto empty_write;
-
- /* Perform the write */
- file_offset_tmp = file_offset;
- nwritten = vfs_write(curlun->filp,
- (char __user *)bh->buf,
- amount, &file_offset_tmp);
- VLDBG(curlun, "file write %u @ %llu -> %d\n", amount,
- (unsigned long long)file_offset, (int)nwritten);
- if (signal_pending(current))
- return -EINTR; /* Interrupted! */
-
- if (nwritten < 0) {
- LDBG(curlun, "error in file write: %d\n",
- (int)nwritten);
- nwritten = 0;
- } else if (nwritten < amount) {
- LDBG(curlun, "partial file write: %d/%u\n",
- (int)nwritten, amount);
- nwritten = round_down(nwritten, curlun->blksize);
- }
- file_offset += nwritten;
- amount_left_to_write -= nwritten;
- common->residue -= nwritten;
+ /*
+ * Don't accept excess data. The spec doesn't say
+ * what to do in this case. We'll ignore the error.
+ */
+ amount = min(amount, bh->bulk_out_intended_length);
- /* If an error occurred, report it and its position */
- if (nwritten < amount) {
- curlun->sense_data = SS_WRITE_ERROR;
- curlun->sense_data_info =
+ /* Don't write a partial block */
+ amount = round_down(amount, curlun->blksize);
+ if (amount == 0)
+ goto empty_write;
+
+ /* Perform the write */
+ file_offset_tmp = file_offset;
+ nwritten = vfs_write(curlun->filp, (char __user *)bh->buf,
+ amount, &file_offset_tmp);
+ VLDBG(curlun, "file write %u @ %llu -> %d\n", amount,
+ (unsigned long long)file_offset, (int)nwritten);
+ if (signal_pending(current))
+ return -EINTR; /* Interrupted! */
+
+ if (nwritten < 0) {
+ LDBG(curlun, "error in file write: %d\n",
+ (int) nwritten);
+ nwritten = 0;
+ } else if (nwritten < amount) {
+ LDBG(curlun, "partial file write: %d/%u\n",
+ (int) nwritten, amount);
+ nwritten = round_down(nwritten, curlun->blksize);
+ }
+ file_offset += nwritten;
+ amount_left_to_write -= nwritten;
+ common->residue -= nwritten;
+
+ /* If an error occurred, report it and its position */
+ if (nwritten < amount) {
+ curlun->sense_data = SS_WRITE_ERROR;
+ curlun->sense_data_info =
file_offset >> curlun->blkbits;
- curlun->info_valid = 1;
- break;
- }
+ curlun->info_valid = 1;
+ break;
+ }
empty_write:
- /* Did the host decide to stop early? */
- if (bh->outreq->actual < bh->bulk_out_intended_length) {
- common->short_packet_received = 1;
- break;
- }
- continue;
+ /* Did the host decide to stop early? */
+ if (bh->outreq->actual < bh->bulk_out_intended_length) {
+ common->short_packet_received = 1;
+ break;
}
-
- /* Wait for something to happen */
- rc = sleep_thread(common, false);
- if (rc)
- return rc;
}
return -EIO; /* No default reply */
@@ -1471,7 +1442,7 @@ static int wedge_bulk_in_endpoint(struct fsg_dev *fsg)
static int throw_away_data(struct fsg_common *common)
{
- struct fsg_buffhd *bh;
+ struct fsg_buffhd *bh, *bh2;
u32 amount;
int rc;
@@ -1479,26 +1450,10 @@ static int throw_away_data(struct fsg_common *common)
bh->state != BUF_STATE_EMPTY || common->usb_amount_left > 0;
bh = common->next_buffhd_to_drain) {
- /* Throw away the data in a filled buffer */
- if (bh->state == BUF_STATE_FULL) {
- smp_rmb();
- bh->state = BUF_STATE_EMPTY;
- common->next_buffhd_to_drain = bh->next;
-
- /* A short packet or an error ends everything */
- if (bh->outreq->actual < bh->bulk_out_intended_length ||
- bh->outreq->status != 0) {
- raise_exception(common,
- FSG_STATE_ABORT_BULK_OUT);
- return -EINTR;
- }
- continue;
- }
-
/* Try to submit another request if we need one */
- bh = common->next_buffhd_to_fill;
- if (bh->state == BUF_STATE_EMPTY
- && common->usb_amount_left > 0) {
+ bh2 = common->next_buffhd_to_fill;
+ if (bh2->state == BUF_STATE_EMPTY &&
+ common->usb_amount_left > 0) {
amount = min(common->usb_amount_left, FSG_BUFLEN);
/*
@@ -1506,19 +1461,30 @@ static int throw_away_data(struct fsg_common *common)
* equal to the buffer size, which is divisible by
* the bulk-out maxpacket size.
*/
- set_bulk_out_req_length(common, bh, amount);
- if (!start_out_transfer(common, bh))
+ set_bulk_out_req_length(common, bh2, amount);
+ if (!start_out_transfer(common, bh2))
/* Dunno what to do if common->fsg is NULL */
return -EIO;
- common->next_buffhd_to_fill = bh->next;
+ common->next_buffhd_to_fill = bh2->next;
common->usb_amount_left -= amount;
continue;
}
- /* Otherwise wait for something to happen */
- rc = sleep_thread(common, true);
+ /* Wait for the data to be received */
+ rc = sleep_thread(common, false, bh);
if (rc)
return rc;
+
+ /* Throw away the data in a filled buffer */
+ bh->state = BUF_STATE_EMPTY;
+ common->next_buffhd_to_drain = bh->next;
+
+ /* A short packet or an error ends everything */
+ if (bh->outreq->actual < bh->bulk_out_intended_length ||
+ bh->outreq->status != 0) {
+ raise_exception(common, FSG_STATE_ABORT_BULK_OUT);
+ return -EINTR;
+ }
}
return 0;
}
@@ -1625,7 +1591,7 @@ static int finish_reply(struct fsg_common *common)
return rc;
}
-static int send_status(struct fsg_common *common)
+static void send_status(struct fsg_common *common)
{
struct fsg_lun *curlun = common->curlun;
struct fsg_buffhd *bh;
@@ -1636,11 +1602,9 @@ static int send_status(struct fsg_common *common)
/* Wait for the next buffer to become available */
bh = common->next_buffhd_to_fill;
- while (bh->state != BUF_STATE_EMPTY) {
- rc = sleep_thread(common, true);
- if (rc)
- return rc;
- }
+ rc = sleep_thread(common, false, bh);
+ if (rc)
+ return;
if (curlun) {
sd = curlun->sense_data;
@@ -1674,10 +1638,10 @@ static int send_status(struct fsg_common *common)
bh->inreq->zero = 0;
if (!start_in_transfer(common, bh))
/* Don't know what to do if common->fsg is NULL */
- return -EIO;
+ return;
common->next_buffhd_to_fill = bh->next;
- return 0;
+ return;
}
@@ -1839,11 +1803,10 @@ static int do_scsi_command(struct fsg_common *common)
/* Wait for the next buffer to become available for data or status */
bh = common->next_buffhd_to_fill;
common->next_buffhd_to_drain = bh;
- while (bh->state != BUF_STATE_EMPTY) {
- rc = sleep_thread(common, true);
- if (rc)
- return rc;
- }
+ rc = sleep_thread(common, false, bh);
+ if (rc)
+ return rc;
+
common->phase_error = 0;
common->short_packet_received = 0;
@@ -2186,11 +2149,9 @@ static int get_next_command(struct fsg_common *common)
/* Wait for the next buffer to become available */
bh = common->next_buffhd_to_fill;
- while (bh->state != BUF_STATE_EMPTY) {
- rc = sleep_thread(common, true);
- if (rc)
- return rc;
- }
+ rc = sleep_thread(common, true, bh);
+ if (rc)
+ return rc;
/* Queue a request to read a Bulk-only CBW */
set_bulk_out_req_length(common, bh, US_BULK_CB_WRAP_LEN);
@@ -2205,12 +2166,10 @@ static int get_next_command(struct fsg_common *common)
*/
/* Wait for the CBW to arrive */
- while (bh->state != BUF_STATE_FULL) {
- rc = sleep_thread(common, true);
- if (rc)
- return rc;
- }
- smp_rmb();
+ rc = sleep_thread(common, true, bh);
+ if (rc)
+ return rc;
+
rc = fsg_is_set(common) ? received_cbw(common->fsg, bh) : -EIO;
bh->state = BUF_STATE_EMPTY;
@@ -2362,9 +2321,11 @@ static void handle_exception(struct fsg_common *common)
if (!sig)
break;
if (sig != SIGUSR1) {
+ spin_lock_irq(&common->lock);
if (common->state < FSG_STATE_EXIT)
DBG(common, "Main thread exiting on signal\n");
- raise_exception(common, FSG_STATE_EXIT);
+ common->state = FSG_STATE_EXIT;
+ spin_unlock_irq(&common->lock);
}
}
@@ -2372,23 +2333,14 @@ static void handle_exception(struct fsg_common *common)
if (likely(common->fsg)) {
for (i = 0; i < common->fsg_num_buffers; ++i) {
bh = &common->buffhds[i];
- if (bh->inreq_busy)
+ if (bh->state == BUF_STATE_SENDING)
usb_ep_dequeue(common->fsg->bulk_in, bh->inreq);
- if (bh->outreq_busy)
+ if (bh->state == BUF_STATE_RECEIVING)
usb_ep_dequeue(common->fsg->bulk_out,
bh->outreq);
- }
- /* Wait until everything is idle */
- for (;;) {
- int num_active = 0;
- for (i = 0; i < common->fsg_num_buffers; ++i) {
- bh = &common->buffhds[i];
- num_active += bh->inreq_busy + bh->outreq_busy;
- }
- if (num_active == 0)
- break;
- if (sleep_thread(common, true))
+ /* Wait for a transfer to become idle */
+ if (sleep_thread(common, false, bh))
return;
}
@@ -2413,10 +2365,9 @@ static void handle_exception(struct fsg_common *common)
common->next_buffhd_to_drain = &common->buffhds[0];
exception_req_tag = common->exception_req_tag;
old_state = common->state;
+ common->state = FSG_STATE_NORMAL;
- if (old_state == FSG_STATE_ABORT_BULK_OUT)
- common->state = FSG_STATE_STATUS_PHASE;
- else {
+ if (old_state != FSG_STATE_ABORT_BULK_OUT) {
for (i = 0; i < ARRAY_SIZE(common->luns); ++i) {
curlun = common->luns[i];
if (!curlun)
@@ -2427,21 +2378,19 @@ static void handle_exception(struct fsg_common *common)
curlun->sense_data_info = 0;
curlun->info_valid = 0;
}
- common->state = FSG_STATE_IDLE;
}
spin_unlock_irq(&common->lock);
/* Carry out any extra actions required for the exception */
switch (old_state) {
+ case FSG_STATE_NORMAL:
+ break;
+
case FSG_STATE_ABORT_BULK_OUT:
send_status(common);
- spin_lock_irq(&common->lock);
- if (common->state == FSG_STATE_STATUS_PHASE)
- common->state = FSG_STATE_IDLE;
- spin_unlock_irq(&common->lock);
break;
- case FSG_STATE_RESET:
+ case FSG_STATE_PROTOCOL_RESET:
/*
* In case we were forced against our will to halt a
* bulk endpoint, clear the halt now. (The SuperH UDC
@@ -2474,19 +2423,13 @@ static void handle_exception(struct fsg_common *common)
break;
case FSG_STATE_EXIT:
- case FSG_STATE_TERMINATED:
do_set_interface(common, NULL); /* Free resources */
spin_lock_irq(&common->lock);
common->state = FSG_STATE_TERMINATED; /* Stop the thread */
spin_unlock_irq(&common->lock);
break;
- case FSG_STATE_INTERFACE_CHANGE:
- case FSG_STATE_DISCONNECT:
- case FSG_STATE_COMMAND_PHASE:
- case FSG_STATE_DATA_PHASE:
- case FSG_STATE_STATUS_PHASE:
- case FSG_STATE_IDLE:
+ case FSG_STATE_TERMINATED:
break;
}
}
@@ -2525,33 +2468,17 @@ static int fsg_main_thread(void *common_)
}
if (!common->running) {
- sleep_thread(common, true);
+ sleep_thread(common, true, NULL);
continue;
}
- if (get_next_command(common))
+ if (get_next_command(common) || exception_in_progress(common))
continue;
-
- spin_lock_irq(&common->lock);
- if (!exception_in_progress(common))
- common->state = FSG_STATE_DATA_PHASE;
- spin_unlock_irq(&common->lock);
-
- if (do_scsi_command(common) || finish_reply(common))
+ if (do_scsi_command(common) || exception_in_progress(common))
continue;
-
- spin_lock_irq(&common->lock);
- if (!exception_in_progress(common))
- common->state = FSG_STATE_STATUS_PHASE;
- spin_unlock_irq(&common->lock);
-
- if (send_status(common))
+ if (finish_reply(common) || exception_in_progress(common))
continue;
-
- spin_lock_irq(&common->lock);
- if (!exception_in_progress(common))
- common->state = FSG_STATE_IDLE;
- spin_unlock_irq(&common->lock);
+ send_status(common);
}
spin_lock_irq(&common->lock);
@@ -2671,6 +2598,7 @@ static struct fsg_common *fsg_common_setup(struct fsg_common *common)
spin_lock_init(&common->lock);
kref_init(&common->ref);
init_completion(&common->thread_notifier);
+ init_waitqueue_head(&common->io_wait);
init_waitqueue_head(&common->fsg_wait);
common->state = FSG_STATE_TERMINATED;
memset(common->luns, 0, sizeof(common->luns));
@@ -2972,7 +2900,6 @@ static void fsg_common_release(struct kref *ref)
if (common->state != FSG_STATE_TERMINATED) {
raise_exception(common, FSG_STATE_EXIT);
wait_for_completion(&common->thread_notifier);
- common->thread_task = NULL;
}
for (i = 0; i < ARRAY_SIZE(common->luns); ++i) {
@@ -3021,11 +2948,11 @@ static int fsg_bind(struct usb_configuration *c, struct usb_function *f)
}
if (!common->thread_task) {
- common->state = FSG_STATE_IDLE;
+ common->state = FSG_STATE_NORMAL;
common->thread_task =
kthread_create(fsg_main_thread, common, "file-storage");
if (IS_ERR(common->thread_task)) {
- int ret = PTR_ERR(common->thread_task);
+ ret = PTR_ERR(common->thread_task);
common->thread_task = NULL;
common->state = FSG_STATE_TERMINATED;
return ret;
diff --git a/drivers/usb/gadget/function/f_phonet.c b/drivers/usb/gadget/function/f_phonet.c
index b4058f0000e4..6a1ce6a55158 100644
--- a/drivers/usb/gadget/function/f_phonet.c
+++ b/drivers/usb/gadget/function/f_phonet.c
@@ -281,7 +281,7 @@ static void pn_net_setup(struct net_device *dev)
dev->tx_queue_len = 1;
dev->netdev_ops = &pn_netdev_ops;
- dev->destructor = free_netdev;
+ dev->needs_free_netdev = true;
dev->header_ops = &phonet_header_ops;
}
diff --git a/drivers/usb/gadget/function/f_uac1.c b/drivers/usb/gadget/function/f_uac1.c
index f2ac0cbc29a4..8656f84e17d9 100644
--- a/drivers/usb/gadget/function/f_uac1.c
+++ b/drivers/usb/gadget/function/f_uac1.c
@@ -1,24 +1,38 @@
/*
- * f_audio.c -- USB Audio class function driver
- *
- * Copyright (C) 2008 Bryan Wu <cooloney@kernel.org>
- * Copyright (C) 2008 Analog Devices, Inc
+ * f_uac1.c -- USB Audio Class 1.0 Function (using u_audio API)
*
- * Enter bugs at http://blackfin.uclinux.org/
+ * Copyright (C) 2016 Ruslan Bilovol <ruslan.bilovol@gmail.com>
*
- * Licensed under the GPL-2 or later.
+ * This driver doesn't expect any real Audio codec to be present
+ * on the device - the audio streams are simply sinked to and
+ * sourced from a virtual ALSA sound card created.
+ *
+ * This file is based on f_uac1.c which is
+ * Copyright (C) 2008 Bryan Wu <cooloney@kernel.org>
+ * Copyright (C) 2008 Analog Devices, Inc
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
*/
-#include <linux/slab.h>
-#include <linux/kernel.h>
+#include <linux/usb/audio.h>
#include <linux/module.h>
-#include <linux/device.h>
-#include <linux/atomic.h>
+#include "u_audio.h"
#include "u_uac1.h"
-static int generic_set_cmd(struct usb_audio_control *con, u8 cmd, int value);
-static int generic_get_cmd(struct usb_audio_control *con, u8 cmd);
+struct f_uac1 {
+ struct g_audio g_audio;
+ u8 ac_intf, as_in_intf, as_out_intf;
+ u8 ac_alt, as_in_alt, as_out_alt; /* needed for get_alt() */
+};
+
+static inline struct f_uac1 *func_to_uac1(struct usb_function *f)
+{
+ return container_of(f, struct f_uac1, g_audio.func);
+}
/*
* DESCRIPTORS ... most are static, but strings and full
@@ -26,12 +40,17 @@ static int generic_get_cmd(struct usb_audio_control *con, u8 cmd);
*/
/*
- * We have two interfaces- AudioControl and AudioStreaming
- * TODO: only supcard playback currently
+ * We have three interfaces - one AudioControl and two AudioStreaming
+ *
+ * The driver implements a simple UAC_1 topology.
+ * USB-OUT -> IT_1 -> OT_2 -> ALSA_Capture
+ * ALSA_Playback -> IT_3 -> OT_4 -> USB-IN
*/
-#define F_AUDIO_AC_INTERFACE 0
-#define F_AUDIO_AS_INTERFACE 1
-#define F_AUDIO_NUM_INTERFACES 1
+#define F_AUDIO_AC_INTERFACE 0
+#define F_AUDIO_AS_OUT_INTERFACE 1
+#define F_AUDIO_AS_IN_INTERFACE 2
+/* Number of streaming interfaces */
+#define F_AUDIO_NUM_INTERFACES 2
/* B.3.1 Standard AC Interface Descriptor */
static struct usb_interface_descriptor ac_interface_desc = {
@@ -46,89 +65,91 @@ static struct usb_interface_descriptor ac_interface_desc = {
* The number of AudioStreaming and MIDIStreaming interfaces
* in the Audio Interface Collection
*/
-DECLARE_UAC_AC_HEADER_DESCRIPTOR(1);
+DECLARE_UAC_AC_HEADER_DESCRIPTOR(2);
#define UAC_DT_AC_HEADER_LENGTH UAC_DT_AC_HEADER_SIZE(F_AUDIO_NUM_INTERFACES)
-/* 1 input terminal, 1 output terminal and 1 feature unit */
-#define UAC_DT_TOTAL_LENGTH (UAC_DT_AC_HEADER_LENGTH + UAC_DT_INPUT_TERMINAL_SIZE \
- + UAC_DT_OUTPUT_TERMINAL_SIZE + UAC_DT_FEATURE_UNIT_SIZE(0))
+/* 2 input terminals and 2 output terminals */
+#define UAC_DT_TOTAL_LENGTH (UAC_DT_AC_HEADER_LENGTH \
+ + 2*UAC_DT_INPUT_TERMINAL_SIZE + 2*UAC_DT_OUTPUT_TERMINAL_SIZE)
/* B.3.2 Class-Specific AC Interface Descriptor */
-static struct uac1_ac_header_descriptor_1 ac_header_desc = {
+static struct uac1_ac_header_descriptor_2 ac_header_desc = {
.bLength = UAC_DT_AC_HEADER_LENGTH,
.bDescriptorType = USB_DT_CS_INTERFACE,
.bDescriptorSubtype = UAC_HEADER,
- .bcdADC = __constant_cpu_to_le16(0x0100),
- .wTotalLength = __constant_cpu_to_le16(UAC_DT_TOTAL_LENGTH),
+ .bcdADC = cpu_to_le16(0x0100),
+ .wTotalLength = cpu_to_le16(UAC_DT_TOTAL_LENGTH),
.bInCollection = F_AUDIO_NUM_INTERFACES,
.baInterfaceNr = {
- /* Interface number of the first AudioStream interface */
+ /* Interface number of the AudioStream interfaces */
[0] = 1,
+ [1] = 2,
}
};
-#define INPUT_TERMINAL_ID 1
-static struct uac_input_terminal_descriptor input_terminal_desc = {
+#define USB_OUT_IT_ID 1
+static struct uac_input_terminal_descriptor usb_out_it_desc = {
.bLength = UAC_DT_INPUT_TERMINAL_SIZE,
.bDescriptorType = USB_DT_CS_INTERFACE,
.bDescriptorSubtype = UAC_INPUT_TERMINAL,
- .bTerminalID = INPUT_TERMINAL_ID,
+ .bTerminalID = USB_OUT_IT_ID,
.wTerminalType = UAC_TERMINAL_STREAMING,
.bAssocTerminal = 0,
.wChannelConfig = 0x3,
};
-DECLARE_UAC_FEATURE_UNIT_DESCRIPTOR(0);
-
-#define FEATURE_UNIT_ID 2
-static struct uac_feature_unit_descriptor_0 feature_unit_desc = {
- .bLength = UAC_DT_FEATURE_UNIT_SIZE(0),
+#define IO_OUT_OT_ID 2
+static struct uac1_output_terminal_descriptor io_out_ot_desc = {
+ .bLength = UAC_DT_OUTPUT_TERMINAL_SIZE,
.bDescriptorType = USB_DT_CS_INTERFACE,
- .bDescriptorSubtype = UAC_FEATURE_UNIT,
- .bUnitID = FEATURE_UNIT_ID,
- .bSourceID = INPUT_TERMINAL_ID,
- .bControlSize = 2,
- .bmaControls[0] = (UAC_FU_MUTE | UAC_FU_VOLUME),
+ .bDescriptorSubtype = UAC_OUTPUT_TERMINAL,
+ .bTerminalID = IO_OUT_OT_ID,
+ .wTerminalType = UAC_OUTPUT_TERMINAL_SPEAKER,
+ .bAssocTerminal = 0,
+ .bSourceID = USB_OUT_IT_ID,
};
-static struct usb_audio_control mute_control = {
- .list = LIST_HEAD_INIT(mute_control.list),
- .name = "Mute Control",
- .type = UAC_FU_MUTE,
- /* Todo: add real Mute control code */
- .set = generic_set_cmd,
- .get = generic_get_cmd,
+#define IO_IN_IT_ID 3
+static struct uac_input_terminal_descriptor io_in_it_desc = {
+ .bLength = UAC_DT_INPUT_TERMINAL_SIZE,
+ .bDescriptorType = USB_DT_CS_INTERFACE,
+ .bDescriptorSubtype = UAC_INPUT_TERMINAL,
+ .bTerminalID = IO_IN_IT_ID,
+ .wTerminalType = UAC_INPUT_TERMINAL_MICROPHONE,
+ .bAssocTerminal = 0,
+ .wChannelConfig = 0x3,
};
-static struct usb_audio_control volume_control = {
- .list = LIST_HEAD_INIT(volume_control.list),
- .name = "Volume Control",
- .type = UAC_FU_VOLUME,
- /* Todo: add real Volume control code */
- .set = generic_set_cmd,
- .get = generic_get_cmd,
+#define USB_IN_OT_ID 4
+static struct uac1_output_terminal_descriptor usb_in_ot_desc = {
+ .bLength = UAC_DT_OUTPUT_TERMINAL_SIZE,
+ .bDescriptorType = USB_DT_CS_INTERFACE,
+ .bDescriptorSubtype = UAC_OUTPUT_TERMINAL,
+ .bTerminalID = USB_IN_OT_ID,
+ .wTerminalType = UAC_TERMINAL_STREAMING,
+ .bAssocTerminal = 0,
+ .bSourceID = IO_IN_IT_ID,
};
-static struct usb_audio_control_selector feature_unit = {
- .list = LIST_HEAD_INIT(feature_unit.list),
- .id = FEATURE_UNIT_ID,
- .name = "Mute & Volume Control",
- .type = UAC_FEATURE_UNIT,
- .desc = (struct usb_descriptor_header *)&feature_unit_desc,
+/* B.4.1 Standard AS Interface Descriptor */
+static struct usb_interface_descriptor as_out_interface_alt_0_desc = {
+ .bLength = USB_DT_INTERFACE_SIZE,
+ .bDescriptorType = USB_DT_INTERFACE,
+ .bAlternateSetting = 0,
+ .bNumEndpoints = 0,
+ .bInterfaceClass = USB_CLASS_AUDIO,
+ .bInterfaceSubClass = USB_SUBCLASS_AUDIOSTREAMING,
};
-#define OUTPUT_TERMINAL_ID 3
-static struct uac1_output_terminal_descriptor output_terminal_desc = {
- .bLength = UAC_DT_OUTPUT_TERMINAL_SIZE,
- .bDescriptorType = USB_DT_CS_INTERFACE,
- .bDescriptorSubtype = UAC_OUTPUT_TERMINAL,
- .bTerminalID = OUTPUT_TERMINAL_ID,
- .wTerminalType = UAC_OUTPUT_TERMINAL_SPEAKER,
- .bAssocTerminal = FEATURE_UNIT_ID,
- .bSourceID = FEATURE_UNIT_ID,
+static struct usb_interface_descriptor as_out_interface_alt_1_desc = {
+ .bLength = USB_DT_INTERFACE_SIZE,
+ .bDescriptorType = USB_DT_INTERFACE,
+ .bAlternateSetting = 1,
+ .bNumEndpoints = 1,
+ .bInterfaceClass = USB_CLASS_AUDIO,
+ .bInterfaceSubClass = USB_SUBCLASS_AUDIOSTREAMING,
};
-/* B.4.1 Standard AS Interface Descriptor */
-static struct usb_interface_descriptor as_interface_alt_0_desc = {
+static struct usb_interface_descriptor as_in_interface_alt_0_desc = {
.bLength = USB_DT_INTERFACE_SIZE,
.bDescriptorType = USB_DT_INTERFACE,
.bAlternateSetting = 0,
@@ -137,7 +158,7 @@ static struct usb_interface_descriptor as_interface_alt_0_desc = {
.bInterfaceSubClass = USB_SUBCLASS_AUDIOSTREAMING,
};
-static struct usb_interface_descriptor as_interface_alt_1_desc = {
+static struct usb_interface_descriptor as_in_interface_alt_1_desc = {
.bLength = USB_DT_INTERFACE_SIZE,
.bDescriptorType = USB_DT_INTERFACE,
.bAlternateSetting = 1,
@@ -147,18 +168,27 @@ static struct usb_interface_descriptor as_interface_alt_1_desc = {
};
/* B.4.2 Class-Specific AS Interface Descriptor */
-static struct uac1_as_header_descriptor as_header_desc = {
+static struct uac1_as_header_descriptor as_out_header_desc = {
.bLength = UAC_DT_AS_HEADER_SIZE,
.bDescriptorType = USB_DT_CS_INTERFACE,
.bDescriptorSubtype = UAC_AS_GENERAL,
- .bTerminalLink = INPUT_TERMINAL_ID,
+ .bTerminalLink = USB_OUT_IT_ID,
+ .bDelay = 1,
+ .wFormatTag = UAC_FORMAT_TYPE_I_PCM,
+};
+
+static struct uac1_as_header_descriptor as_in_header_desc = {
+ .bLength = UAC_DT_AS_HEADER_SIZE,
+ .bDescriptorType = USB_DT_CS_INTERFACE,
+ .bDescriptorSubtype = UAC_AS_GENERAL,
+ .bTerminalLink = USB_IN_OT_ID,
.bDelay = 1,
.wFormatTag = UAC_FORMAT_TYPE_I_PCM,
};
DECLARE_UAC_FORMAT_TYPE_I_DISCRETE_DESC(1);
-static struct uac_format_type_i_discrete_descriptor_1 as_type_i_desc = {
+static struct uac_format_type_i_discrete_descriptor_1 as_out_type_i_desc = {
.bLength = UAC_FORMAT_TYPE_I_DISCRETE_DESC_SIZE(1),
.bDescriptorType = USB_DT_CS_INTERFACE,
.bDescriptorSubtype = UAC_FORMAT_TYPE,
@@ -184,48 +214,97 @@ static struct uac_iso_endpoint_descriptor as_iso_out_desc = {
.bLength = UAC_ISO_ENDPOINT_DESC_SIZE,
.bDescriptorType = USB_DT_CS_ENDPOINT,
.bDescriptorSubtype = UAC_EP_GENERAL,
- .bmAttributes = 1,
+ .bmAttributes = 1,
.bLockDelayUnits = 1,
- .wLockDelay = __constant_cpu_to_le16(1),
+ .wLockDelay = cpu_to_le16(1),
+};
+
+static struct uac_format_type_i_discrete_descriptor_1 as_in_type_i_desc = {
+ .bLength = UAC_FORMAT_TYPE_I_DISCRETE_DESC_SIZE(1),
+ .bDescriptorType = USB_DT_CS_INTERFACE,
+ .bDescriptorSubtype = UAC_FORMAT_TYPE,
+ .bFormatType = UAC_FORMAT_TYPE_I,
+ .bSubframeSize = 2,
+ .bBitResolution = 16,
+ .bSamFreqType = 1,
+};
+
+/* Standard ISO OUT Endpoint Descriptor */
+static struct usb_endpoint_descriptor as_in_ep_desc = {
+ .bLength = USB_DT_ENDPOINT_AUDIO_SIZE,
+ .bDescriptorType = USB_DT_ENDPOINT,
+ .bEndpointAddress = USB_DIR_IN,
+ .bmAttributes = USB_ENDPOINT_SYNC_ASYNC
+ | USB_ENDPOINT_XFER_ISOC,
+ .wMaxPacketSize = cpu_to_le16(UAC1_OUT_EP_MAX_PACKET_SIZE),
+ .bInterval = 4,
+};
+
+/* Class-specific AS ISO OUT Endpoint Descriptor */
+static struct uac_iso_endpoint_descriptor as_iso_in_desc = {
+ .bLength = UAC_ISO_ENDPOINT_DESC_SIZE,
+ .bDescriptorType = USB_DT_CS_ENDPOINT,
+ .bDescriptorSubtype = UAC_EP_GENERAL,
+ .bmAttributes = 1,
+ .bLockDelayUnits = 0,
+ .wLockDelay = 0,
};
static struct usb_descriptor_header *f_audio_desc[] = {
(struct usb_descriptor_header *)&ac_interface_desc,
(struct usb_descriptor_header *)&ac_header_desc,
- (struct usb_descriptor_header *)&input_terminal_desc,
- (struct usb_descriptor_header *)&output_terminal_desc,
- (struct usb_descriptor_header *)&feature_unit_desc,
+ (struct usb_descriptor_header *)&usb_out_it_desc,
+ (struct usb_descriptor_header *)&io_out_ot_desc,
+ (struct usb_descriptor_header *)&io_in_it_desc,
+ (struct usb_descriptor_header *)&usb_in_ot_desc,
- (struct usb_descriptor_header *)&as_interface_alt_0_desc,
- (struct usb_descriptor_header *)&as_interface_alt_1_desc,
- (struct usb_descriptor_header *)&as_header_desc,
+ (struct usb_descriptor_header *)&as_out_interface_alt_0_desc,
+ (struct usb_descriptor_header *)&as_out_interface_alt_1_desc,
+ (struct usb_descriptor_header *)&as_out_header_desc,
- (struct usb_descriptor_header *)&as_type_i_desc,
+ (struct usb_descriptor_header *)&as_out_type_i_desc,
(struct usb_descriptor_header *)&as_out_ep_desc,
(struct usb_descriptor_header *)&as_iso_out_desc,
+
+ (struct usb_descriptor_header *)&as_in_interface_alt_0_desc,
+ (struct usb_descriptor_header *)&as_in_interface_alt_1_desc,
+ (struct usb_descriptor_header *)&as_in_header_desc,
+
+ (struct usb_descriptor_header *)&as_in_type_i_desc,
+
+ (struct usb_descriptor_header *)&as_in_ep_desc,
+ (struct usb_descriptor_header *)&as_iso_in_desc,
NULL,
};
enum {
STR_AC_IF,
- STR_INPUT_TERMINAL,
- STR_INPUT_TERMINAL_CH_NAMES,
- STR_FEAT_DESC_0,
- STR_OUTPUT_TERMINAL,
- STR_AS_IF_ALT0,
- STR_AS_IF_ALT1,
+ STR_USB_OUT_IT,
+ STR_USB_OUT_IT_CH_NAMES,
+ STR_IO_OUT_OT,
+ STR_IO_IN_IT,
+ STR_IO_IN_IT_CH_NAMES,
+ STR_USB_IN_OT,
+ STR_AS_OUT_IF_ALT0,
+ STR_AS_OUT_IF_ALT1,
+ STR_AS_IN_IF_ALT0,
+ STR_AS_IN_IF_ALT1,
};
static struct usb_string strings_uac1[] = {
[STR_AC_IF].s = "AC Interface",
- [STR_INPUT_TERMINAL].s = "Input terminal",
- [STR_INPUT_TERMINAL_CH_NAMES].s = "Channels",
- [STR_FEAT_DESC_0].s = "Volume control & mute",
- [STR_OUTPUT_TERMINAL].s = "Output terminal",
- [STR_AS_IF_ALT0].s = "AS Interface",
- [STR_AS_IF_ALT1].s = "AS Interface",
+ [STR_USB_OUT_IT].s = "Playback Input terminal",
+ [STR_USB_OUT_IT_CH_NAMES].s = "Playback Channels",
+ [STR_IO_OUT_OT].s = "Playback Output terminal",
+ [STR_IO_IN_IT].s = "Capture Input terminal",
+ [STR_IO_IN_IT_CH_NAMES].s = "Capture Channels",
+ [STR_USB_IN_OT].s = "Capture Output terminal",
+ [STR_AS_OUT_IF_ALT0].s = "Playback Inactive",
+ [STR_AS_OUT_IF_ALT1].s = "Playback Active",
+ [STR_AS_IN_IF_ALT0].s = "Capture Inactive",
+ [STR_AS_IN_IF_ALT1].s = "Capture Active",
{ },
};
@@ -243,216 +322,6 @@ static struct usb_gadget_strings *uac1_strings[] = {
* This function is an ALSA sound card following USB Audio Class Spec 1.0.
*/
-/*-------------------------------------------------------------------------*/
-struct f_audio_buf {
- u8 *buf;
- int actual;
- struct list_head list;
-};
-
-static struct f_audio_buf *f_audio_buffer_alloc(int buf_size)
-{
- struct f_audio_buf *copy_buf;
-
- copy_buf = kzalloc(sizeof *copy_buf, GFP_ATOMIC);
- if (!copy_buf)
- return ERR_PTR(-ENOMEM);
-
- copy_buf->buf = kzalloc(buf_size, GFP_ATOMIC);
- if (!copy_buf->buf) {
- kfree(copy_buf);
- return ERR_PTR(-ENOMEM);
- }
-
- return copy_buf;
-}
-
-static void f_audio_buffer_free(struct f_audio_buf *audio_buf)
-{
- kfree(audio_buf->buf);
- kfree(audio_buf);
-}
-/*-------------------------------------------------------------------------*/
-
-struct f_audio {
- struct gaudio card;
-
- /* endpoints handle full and/or high speeds */
- struct usb_ep *out_ep;
-
- spinlock_t lock;
- struct f_audio_buf *copy_buf;
- struct work_struct playback_work;
- struct list_head play_queue;
-
- /* Control Set command */
- struct list_head cs;
- u8 set_cmd;
- struct usb_audio_control *set_con;
-};
-
-static inline struct f_audio *func_to_audio(struct usb_function *f)
-{
- return container_of(f, struct f_audio, card.func);
-}
-
-/*-------------------------------------------------------------------------*/
-
-static void f_audio_playback_work(struct work_struct *data)
-{
- struct f_audio *audio = container_of(data, struct f_audio,
- playback_work);
- struct f_audio_buf *play_buf;
-
- spin_lock_irq(&audio->lock);
- if (list_empty(&audio->play_queue)) {
- spin_unlock_irq(&audio->lock);
- return;
- }
- play_buf = list_first_entry(&audio->play_queue,
- struct f_audio_buf, list);
- list_del(&play_buf->list);
- spin_unlock_irq(&audio->lock);
-
- u_audio_playback(&audio->card, play_buf->buf, play_buf->actual);
- f_audio_buffer_free(play_buf);
-}
-
-static int f_audio_out_ep_complete(struct usb_ep *ep, struct usb_request *req)
-{
- struct f_audio *audio = req->context;
- struct usb_composite_dev *cdev = audio->card.func.config->cdev;
- struct f_audio_buf *copy_buf = audio->copy_buf;
- struct f_uac1_opts *opts;
- int audio_buf_size;
- int err;
-
- opts = container_of(audio->card.func.fi, struct f_uac1_opts,
- func_inst);
- audio_buf_size = opts->audio_buf_size;
-
- if (!copy_buf)
- return -EINVAL;
-
- /* Copy buffer is full, add it to the play_queue */
- if (audio_buf_size - copy_buf->actual < req->actual) {
- list_add_tail(&copy_buf->list, &audio->play_queue);
- schedule_work(&audio->playback_work);
- copy_buf = f_audio_buffer_alloc(audio_buf_size);
- if (IS_ERR(copy_buf))
- return -ENOMEM;
- }
-
- memcpy(copy_buf->buf + copy_buf->actual, req->buf, req->actual);
- copy_buf->actual += req->actual;
- audio->copy_buf = copy_buf;
-
- err = usb_ep_queue(ep, req, GFP_ATOMIC);
- if (err)
- ERROR(cdev, "%s queue req: %d\n", ep->name, err);
-
- return 0;
-
-}
-
-static void f_audio_complete(struct usb_ep *ep, struct usb_request *req)
-{
- struct f_audio *audio = req->context;
- int status = req->status;
- u32 data = 0;
- struct usb_ep *out_ep = audio->out_ep;
-
- switch (status) {
-
- case 0: /* normal completion? */
- if (ep == out_ep)
- f_audio_out_ep_complete(ep, req);
- else if (audio->set_con) {
- memcpy(&data, req->buf, req->length);
- audio->set_con->set(audio->set_con, audio->set_cmd,
- le16_to_cpu(data));
- audio->set_con = NULL;
- }
- break;
- default:
- break;
- }
-}
-
-static int audio_set_intf_req(struct usb_function *f,
- const struct usb_ctrlrequest *ctrl)
-{
- struct f_audio *audio = func_to_audio(f);
- struct usb_composite_dev *cdev = f->config->cdev;
- struct usb_request *req = cdev->req;
- u8 id = ((le16_to_cpu(ctrl->wIndex) >> 8) & 0xFF);
- u16 len = le16_to_cpu(ctrl->wLength);
- u16 w_value = le16_to_cpu(ctrl->wValue);
- u8 con_sel = (w_value >> 8) & 0xFF;
- u8 cmd = (ctrl->bRequest & 0x0F);
- struct usb_audio_control_selector *cs;
- struct usb_audio_control *con;
-
- DBG(cdev, "bRequest 0x%x, w_value 0x%04x, len %d, entity %d\n",
- ctrl->bRequest, w_value, len, id);
-
- list_for_each_entry(cs, &audio->cs, list) {
- if (cs->id == id) {
- list_for_each_entry(con, &cs->control, list) {
- if (con->type == con_sel) {
- audio->set_con = con;
- break;
- }
- }
- break;
- }
- }
-
- audio->set_cmd = cmd;
- req->context = audio;
- req->complete = f_audio_complete;
-
- return len;
-}
-
-static int audio_get_intf_req(struct usb_function *f,
- const struct usb_ctrlrequest *ctrl)
-{
- struct f_audio *audio = func_to_audio(f);
- struct usb_composite_dev *cdev = f->config->cdev;
- struct usb_request *req = cdev->req;
- int value = -EOPNOTSUPP;
- u8 id = ((le16_to_cpu(ctrl->wIndex) >> 8) & 0xFF);
- u16 len = le16_to_cpu(ctrl->wLength);
- u16 w_value = le16_to_cpu(ctrl->wValue);
- u8 con_sel = (w_value >> 8) & 0xFF;
- u8 cmd = (ctrl->bRequest & 0x0F);
- struct usb_audio_control_selector *cs;
- struct usb_audio_control *con;
-
- DBG(cdev, "bRequest 0x%x, w_value 0x%04x, len %d, entity %d\n",
- ctrl->bRequest, w_value, len, id);
-
- list_for_each_entry(cs, &audio->cs, list) {
- if (cs->id == id) {
- list_for_each_entry(con, &cs->control, list) {
- if (con->type == con_sel && con->get) {
- value = con->get(con, cmd);
- break;
- }
- }
- break;
- }
- }
-
- req->context = audio;
- req->complete = f_audio_complete;
- len = min_t(size_t, sizeof(value), len);
- memcpy(req->buf, &value, len);
-
- return len;
-}
-
static int audio_set_endpoint_req(struct usb_function *f,
const struct usb_ctrlrequest *ctrl)
{
@@ -531,14 +400,6 @@ f_audio_setup(struct usb_function *f, const struct usb_ctrlrequest *ctrl)
* activation uses set_alt().
*/
switch (ctrl->bRequestType) {
- case USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE:
- value = audio_set_intf_req(f, ctrl);
- break;
-
- case USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_INTERFACE:
- value = audio_get_intf_req(f, ctrl);
- break;
-
case USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_ENDPOINT:
value = audio_set_endpoint_req(f, ctrl);
break;
@@ -571,143 +432,158 @@ f_audio_setup(struct usb_function *f, const struct usb_ctrlrequest *ctrl)
static int f_audio_set_alt(struct usb_function *f, unsigned intf, unsigned alt)
{
- struct f_audio *audio = func_to_audio(f);
struct usb_composite_dev *cdev = f->config->cdev;
- struct usb_ep *out_ep = audio->out_ep;
- struct usb_request *req;
- struct f_uac1_opts *opts;
- int req_buf_size, req_count, audio_buf_size;
- int i = 0, err = 0;
-
- DBG(cdev, "intf %d, alt %d\n", intf, alt);
+ struct usb_gadget *gadget = cdev->gadget;
+ struct device *dev = &gadget->dev;
+ struct f_uac1 *uac1 = func_to_uac1(f);
+ int ret = 0;
+
+ /* No i/f has more than 2 alt settings */
+ if (alt > 1) {
+ dev_err(dev, "%s:%d Error!\n", __func__, __LINE__);
+ return -EINVAL;
+ }
- opts = container_of(f->fi, struct f_uac1_opts, func_inst);
- req_buf_size = opts->req_buf_size;
- req_count = opts->req_count;
- audio_buf_size = opts->audio_buf_size;
-
- if (intf == 1) {
- if (alt == 1) {
- err = config_ep_by_speed(cdev->gadget, f, out_ep);
- if (err)
- return err;
-
- usb_ep_enable(out_ep);
- audio->copy_buf = f_audio_buffer_alloc(audio_buf_size);
- if (IS_ERR(audio->copy_buf))
- return -ENOMEM;
-
- /*
- * allocate a bunch of read buffers
- * and queue them all at once.
- */
- for (i = 0; i < req_count && err == 0; i++) {
- req = usb_ep_alloc_request(out_ep, GFP_ATOMIC);
- if (req) {
- req->buf = kzalloc(req_buf_size,
- GFP_ATOMIC);
- if (req->buf) {
- req->length = req_buf_size;
- req->context = audio;
- req->complete =
- f_audio_complete;
- err = usb_ep_queue(out_ep,
- req, GFP_ATOMIC);
- if (err)
- ERROR(cdev,
- "%s queue req: %d\n",
- out_ep->name, err);
- } else
- err = -ENOMEM;
- } else
- err = -ENOMEM;
- }
-
- } else {
- struct f_audio_buf *copy_buf = audio->copy_buf;
- if (copy_buf) {
- list_add_tail(&copy_buf->list,
- &audio->play_queue);
- schedule_work(&audio->playback_work);
- }
+ if (intf == uac1->ac_intf) {
+ /* Control I/f has only 1 AltSetting - 0 */
+ if (alt) {
+ dev_err(dev, "%s:%d Error!\n", __func__, __LINE__);
+ return -EINVAL;
}
+ return 0;
}
- return err;
+ if (intf == uac1->as_out_intf) {
+ uac1->as_out_alt = alt;
+
+ if (alt)
+ ret = u_audio_start_capture(&uac1->g_audio);
+ else
+ u_audio_stop_capture(&uac1->g_audio);
+ } else if (intf == uac1->as_in_intf) {
+ uac1->as_in_alt = alt;
+
+ if (alt)
+ ret = u_audio_start_playback(&uac1->g_audio);
+ else
+ u_audio_stop_playback(&uac1->g_audio);
+ } else {
+ dev_err(dev, "%s:%d Error!\n", __func__, __LINE__);
+ return -EINVAL;
+ }
+
+ return ret;
}
-static void f_audio_disable(struct usb_function *f)
+static int f_audio_get_alt(struct usb_function *f, unsigned intf)
{
- return;
+ struct usb_composite_dev *cdev = f->config->cdev;
+ struct usb_gadget *gadget = cdev->gadget;
+ struct device *dev = &gadget->dev;
+ struct f_uac1 *uac1 = func_to_uac1(f);
+
+ if (intf == uac1->ac_intf)
+ return uac1->ac_alt;
+ else if (intf == uac1->as_out_intf)
+ return uac1->as_out_alt;
+ else if (intf == uac1->as_in_intf)
+ return uac1->as_in_alt;
+ else
+ dev_err(dev, "%s:%d Invalid Interface %d!\n",
+ __func__, __LINE__, intf);
+
+ return -EINVAL;
}
-/*-------------------------------------------------------------------------*/
-static void f_audio_build_desc(struct f_audio *audio)
+static void f_audio_disable(struct usb_function *f)
{
- struct gaudio *card = &audio->card;
- u8 *sam_freq;
- int rate;
+ struct f_uac1 *uac1 = func_to_uac1(f);
- /* Set channel numbers */
- input_terminal_desc.bNrChannels = u_audio_get_playback_channels(card);
- as_type_i_desc.bNrChannels = u_audio_get_playback_channels(card);
+ uac1->as_out_alt = 0;
+ uac1->as_in_alt = 0;
- /* Set sample rates */
- rate = u_audio_get_playback_rate(card);
- sam_freq = as_type_i_desc.tSamFreq[0];
- memcpy(sam_freq, &rate, 3);
-
- /* Todo: Set Sample bits and other parameters */
-
- return;
+ u_audio_stop_capture(&uac1->g_audio);
}
+/*-------------------------------------------------------------------------*/
+
/* audio function driver setup/binding */
-static int
-f_audio_bind(struct usb_configuration *c, struct usb_function *f)
+static int f_audio_bind(struct usb_configuration *c, struct usb_function *f)
{
- struct usb_composite_dev *cdev = c->cdev;
- struct f_audio *audio = func_to_audio(f);
- struct usb_string *us;
- int status;
- struct usb_ep *ep = NULL;
- struct f_uac1_opts *audio_opts;
+ struct usb_composite_dev *cdev = c->cdev;
+ struct usb_gadget *gadget = cdev->gadget;
+ struct f_uac1 *uac1 = func_to_uac1(f);
+ struct g_audio *audio = func_to_g_audio(f);
+ struct f_uac1_opts *audio_opts;
+ struct usb_ep *ep = NULL;
+ struct usb_string *us;
+ u8 *sam_freq;
+ int rate;
+ int status;
audio_opts = container_of(f->fi, struct f_uac1_opts, func_inst);
- audio->card.gadget = c->cdev->gadget;
- /* set up ASLA audio devices */
- if (!audio_opts->bound) {
- status = gaudio_setup(&audio->card);
- if (status < 0)
- return status;
- audio_opts->bound = true;
- }
+
us = usb_gstrings_attach(cdev, uac1_strings, ARRAY_SIZE(strings_uac1));
if (IS_ERR(us))
return PTR_ERR(us);
ac_interface_desc.iInterface = us[STR_AC_IF].id;
- input_terminal_desc.iTerminal = us[STR_INPUT_TERMINAL].id;
- input_terminal_desc.iChannelNames = us[STR_INPUT_TERMINAL_CH_NAMES].id;
- feature_unit_desc.iFeature = us[STR_FEAT_DESC_0].id;
- output_terminal_desc.iTerminal = us[STR_OUTPUT_TERMINAL].id;
- as_interface_alt_0_desc.iInterface = us[STR_AS_IF_ALT0].id;
- as_interface_alt_1_desc.iInterface = us[STR_AS_IF_ALT1].id;
+ usb_out_it_desc.iTerminal = us[STR_USB_OUT_IT].id;
+ usb_out_it_desc.iChannelNames = us[STR_USB_OUT_IT_CH_NAMES].id;
+ io_out_ot_desc.iTerminal = us[STR_IO_OUT_OT].id;
+ as_out_interface_alt_0_desc.iInterface = us[STR_AS_OUT_IF_ALT0].id;
+ as_out_interface_alt_1_desc.iInterface = us[STR_AS_OUT_IF_ALT1].id;
+ io_in_it_desc.iTerminal = us[STR_IO_IN_IT].id;
+ io_in_it_desc.iChannelNames = us[STR_IO_IN_IT_CH_NAMES].id;
+ usb_in_ot_desc.iTerminal = us[STR_USB_IN_OT].id;
+ as_in_interface_alt_0_desc.iInterface = us[STR_AS_IN_IF_ALT0].id;
+ as_in_interface_alt_1_desc.iInterface = us[STR_AS_IN_IF_ALT1].id;
+ /* Set channel numbers */
+ usb_out_it_desc.bNrChannels = num_channels(audio_opts->c_chmask);
+ usb_out_it_desc.wChannelConfig = cpu_to_le16(audio_opts->c_chmask);
+ as_out_type_i_desc.bNrChannels = num_channels(audio_opts->c_chmask);
+ as_out_type_i_desc.bSubframeSize = audio_opts->c_ssize;
+ as_out_type_i_desc.bBitResolution = audio_opts->c_ssize * 8;
+ io_in_it_desc.bNrChannels = num_channels(audio_opts->p_chmask);
+ io_in_it_desc.wChannelConfig = cpu_to_le16(audio_opts->p_chmask);
+ as_in_type_i_desc.bNrChannels = num_channels(audio_opts->p_chmask);
+ as_in_type_i_desc.bSubframeSize = audio_opts->p_ssize;
+ as_in_type_i_desc.bBitResolution = audio_opts->p_ssize * 8;
- f_audio_build_desc(audio);
+ /* Set sample rates */
+ rate = audio_opts->c_srate;
+ sam_freq = as_out_type_i_desc.tSamFreq[0];
+ memcpy(sam_freq, &rate, 3);
+ rate = audio_opts->p_srate;
+ sam_freq = as_in_type_i_desc.tSamFreq[0];
+ memcpy(sam_freq, &rate, 3);
/* allocate instance-specific interface IDs, and patch descriptors */
status = usb_interface_id(c, f);
if (status < 0)
goto fail;
ac_interface_desc.bInterfaceNumber = status;
+ uac1->ac_intf = status;
+ uac1->ac_alt = 0;
status = usb_interface_id(c, f);
if (status < 0)
goto fail;
- as_interface_alt_0_desc.bInterfaceNumber = status;
- as_interface_alt_1_desc.bInterfaceNumber = status;
+ as_out_interface_alt_0_desc.bInterfaceNumber = status;
+ as_out_interface_alt_1_desc.bInterfaceNumber = status;
+ uac1->as_out_intf = status;
+ uac1->as_out_alt = 0;
+
+ status = usb_interface_id(c, f);
+ if (status < 0)
+ goto fail;
+ as_in_interface_alt_0_desc.bInterfaceNumber = status;
+ as_in_interface_alt_1_desc.bInterfaceNumber = status;
+ uac1->as_in_intf = status;
+ uac1->as_in_alt = 0;
+
+ audio->gadget = gadget;
status = -ENODEV;
@@ -718,52 +594,42 @@ f_audio_bind(struct usb_configuration *c, struct usb_function *f)
audio->out_ep = ep;
audio->out_ep->desc = &as_out_ep_desc;
- status = -ENOMEM;
+ ep = usb_ep_autoconfig(cdev->gadget, &as_in_ep_desc);
+ if (!ep)
+ goto fail;
+ audio->in_ep = ep;
+ audio->in_ep->desc = &as_in_ep_desc;
/* copy descriptors, and track endpoint copies */
status = usb_assign_descriptors(f, f_audio_desc, f_audio_desc, NULL,
NULL);
if (status)
goto fail;
+
+ audio->out_ep_maxpsize = as_out_ep_desc.wMaxPacketSize;
+ audio->in_ep_maxpsize = as_in_ep_desc.wMaxPacketSize;
+ audio->params.c_chmask = audio_opts->c_chmask;
+ audio->params.c_srate = audio_opts->c_srate;
+ audio->params.c_ssize = audio_opts->c_ssize;
+ audio->params.p_chmask = audio_opts->p_chmask;
+ audio->params.p_srate = audio_opts->p_srate;
+ audio->params.p_ssize = audio_opts->p_ssize;
+ audio->params.req_number = audio_opts->req_number;
+
+ status = g_audio_setup(audio, "UAC1_PCM", "UAC1_Gadget");
+ if (status)
+ goto err_card_register;
+
return 0;
+err_card_register:
+ usb_free_all_descriptors(f);
fail:
- gaudio_cleanup(&audio->card);
return status;
}
/*-------------------------------------------------------------------------*/
-static int generic_set_cmd(struct usb_audio_control *con, u8 cmd, int value)
-{
- con->data[cmd] = value;
-
- return 0;
-}
-
-static int generic_get_cmd(struct usb_audio_control *con, u8 cmd)
-{
- return con->data[cmd];
-}
-
-/* Todo: add more control selecotor dynamically */
-static int control_selector_init(struct f_audio *audio)
-{
- INIT_LIST_HEAD(&audio->cs);
- list_add(&feature_unit.list, &audio->cs);
-
- INIT_LIST_HEAD(&feature_unit.control);
- list_add(&mute_control.list, &feature_unit.control);
- list_add(&volume_control.list, &feature_unit.control);
-
- volume_control.data[UAC__CUR] = 0xffc0;
- volume_control.data[UAC__MIN] = 0xe3a0;
- volume_control.data[UAC__MAX] = 0xfff0;
- volume_control.data[UAC__RES] = 0x0030;
-
- return 0;
-}
-
static inline struct f_uac1_opts *to_f_uac1_opts(struct config_item *item)
{
return container_of(to_config_group(item), struct f_uac1_opts,
@@ -781,9 +647,10 @@ static struct configfs_item_operations f_uac1_item_ops = {
.release = f_uac1_attr_release,
};
-#define UAC1_INT_ATTRIBUTE(name) \
-static ssize_t f_uac1_opts_##name##_show(struct config_item *item, \
- char *page) \
+#define UAC1_ATTRIBUTE(name) \
+static ssize_t f_uac1_opts_##name##_show( \
+ struct config_item *item, \
+ char *page) \
{ \
struct f_uac1_opts *opts = to_f_uac1_opts(item); \
int result; \
@@ -795,7 +662,8 @@ static ssize_t f_uac1_opts_##name##_show(struct config_item *item, \
return result; \
} \
\
-static ssize_t f_uac1_opts_##name##_store(struct config_item *item, \
+static ssize_t f_uac1_opts_##name##_store( \
+ struct config_item *item, \
const char *page, size_t len) \
{ \
struct f_uac1_opts *opts = to_f_uac1_opts(item); \
@@ -822,64 +690,22 @@ end: \
\
CONFIGFS_ATTR(f_uac1_opts_, name)
-UAC1_INT_ATTRIBUTE(req_buf_size);
-UAC1_INT_ATTRIBUTE(req_count);
-UAC1_INT_ATTRIBUTE(audio_buf_size);
-
-#define UAC1_STR_ATTRIBUTE(name) \
-static ssize_t f_uac1_opts_##name##_show(struct config_item *item, \
- char *page) \
-{ \
- struct f_uac1_opts *opts = to_f_uac1_opts(item); \
- int result; \
- \
- mutex_lock(&opts->lock); \
- result = sprintf(page, "%s\n", opts->name); \
- mutex_unlock(&opts->lock); \
- \
- return result; \
-} \
- \
-static ssize_t f_uac1_opts_##name##_store(struct config_item *item, \
- const char *page, size_t len) \
-{ \
- struct f_uac1_opts *opts = to_f_uac1_opts(item); \
- int ret = -EBUSY; \
- char *tmp; \
- \
- mutex_lock(&opts->lock); \
- if (opts->refcnt) \
- goto end; \
- \
- tmp = kstrndup(page, len, GFP_KERNEL); \
- if (tmp) { \
- ret = -ENOMEM; \
- goto end; \
- } \
- if (opts->name##_alloc) \
- kfree(opts->name); \
- opts->name##_alloc = true; \
- opts->name = tmp; \
- ret = len; \
- \
-end: \
- mutex_unlock(&opts->lock); \
- return ret; \
-} \
- \
-CONFIGFS_ATTR(f_uac1_opts_, name)
-
-UAC1_STR_ATTRIBUTE(fn_play);
-UAC1_STR_ATTRIBUTE(fn_cap);
-UAC1_STR_ATTRIBUTE(fn_cntl);
+UAC1_ATTRIBUTE(c_chmask);
+UAC1_ATTRIBUTE(c_srate);
+UAC1_ATTRIBUTE(c_ssize);
+UAC1_ATTRIBUTE(p_chmask);
+UAC1_ATTRIBUTE(p_srate);
+UAC1_ATTRIBUTE(p_ssize);
+UAC1_ATTRIBUTE(req_number);
static struct configfs_attribute *f_uac1_attrs[] = {
- &f_uac1_opts_attr_req_buf_size,
- &f_uac1_opts_attr_req_count,
- &f_uac1_opts_attr_audio_buf_size,
- &f_uac1_opts_attr_fn_play,
- &f_uac1_opts_attr_fn_cap,
- &f_uac1_opts_attr_fn_cntl,
+ &f_uac1_opts_attr_c_chmask,
+ &f_uac1_opts_attr_c_srate,
+ &f_uac1_opts_attr_c_ssize,
+ &f_uac1_opts_attr_p_chmask,
+ &f_uac1_opts_attr_p_srate,
+ &f_uac1_opts_attr_p_ssize,
+ &f_uac1_opts_attr_req_number,
NULL,
};
@@ -894,12 +720,6 @@ static void f_audio_free_inst(struct usb_function_instance *f)
struct f_uac1_opts *opts;
opts = container_of(f, struct f_uac1_opts, func_inst);
- if (opts->fn_play_alloc)
- kfree(opts->fn_play);
- if (opts->fn_cap_alloc)
- kfree(opts->fn_cap);
- if (opts->fn_cntl_alloc)
- kfree(opts->fn_cntl);
kfree(opts);
}
@@ -917,21 +737,22 @@ static struct usb_function_instance *f_audio_alloc_inst(void)
config_group_init_type_name(&opts->func_inst.group, "",
&f_uac1_func_type);
- opts->req_buf_size = UAC1_OUT_EP_MAX_PACKET_SIZE;
- opts->req_count = UAC1_REQ_COUNT;
- opts->audio_buf_size = UAC1_AUDIO_BUF_SIZE;
- opts->fn_play = FILE_PCM_PLAYBACK;
- opts->fn_cap = FILE_PCM_CAPTURE;
- opts->fn_cntl = FILE_CONTROL;
+ opts->c_chmask = UAC1_DEF_CCHMASK;
+ opts->c_srate = UAC1_DEF_CSRATE;
+ opts->c_ssize = UAC1_DEF_CSSIZE;
+ opts->p_chmask = UAC1_DEF_PCHMASK;
+ opts->p_srate = UAC1_DEF_PSRATE;
+ opts->p_ssize = UAC1_DEF_PSSIZE;
+ opts->req_number = UAC1_DEF_REQ_NUM;
return &opts->func_inst;
}
static void f_audio_free(struct usb_function *f)
{
- struct f_audio *audio = func_to_audio(f);
+ struct g_audio *audio;
struct f_uac1_opts *opts;
- gaudio_cleanup(&audio->card);
+ audio = func_to_g_audio(f);
opts = container_of(f->fi, struct f_uac1_opts, func_inst);
kfree(audio);
mutex_lock(&opts->lock);
@@ -941,42 +762,41 @@ static void f_audio_free(struct usb_function *f)
static void f_audio_unbind(struct usb_configuration *c, struct usb_function *f)
{
+ struct g_audio *audio = func_to_g_audio(f);
+
+ g_audio_cleanup(audio);
usb_free_all_descriptors(f);
+
+ audio->gadget = NULL;
}
static struct usb_function *f_audio_alloc(struct usb_function_instance *fi)
{
- struct f_audio *audio;
+ struct f_uac1 *uac1;
struct f_uac1_opts *opts;
/* allocate and initialize one new instance */
- audio = kzalloc(sizeof(*audio), GFP_KERNEL);
- if (!audio)
+ uac1 = kzalloc(sizeof(*uac1), GFP_KERNEL);
+ if (!uac1)
return ERR_PTR(-ENOMEM);
- audio->card.func.name = "g_audio";
-
opts = container_of(fi, struct f_uac1_opts, func_inst);
mutex_lock(&opts->lock);
++opts->refcnt;
mutex_unlock(&opts->lock);
- INIT_LIST_HEAD(&audio->play_queue);
- spin_lock_init(&audio->lock);
-
- audio->card.func.bind = f_audio_bind;
- audio->card.func.unbind = f_audio_unbind;
- audio->card.func.set_alt = f_audio_set_alt;
- audio->card.func.setup = f_audio_setup;
- audio->card.func.disable = f_audio_disable;
- audio->card.func.free_func = f_audio_free;
-
- control_selector_init(audio);
- INIT_WORK(&audio->playback_work, f_audio_playback_work);
+ uac1->g_audio.func.name = "uac1_func";
+ uac1->g_audio.func.bind = f_audio_bind;
+ uac1->g_audio.func.unbind = f_audio_unbind;
+ uac1->g_audio.func.set_alt = f_audio_set_alt;
+ uac1->g_audio.func.get_alt = f_audio_get_alt;
+ uac1->g_audio.func.setup = f_audio_setup;
+ uac1->g_audio.func.disable = f_audio_disable;
+ uac1->g_audio.func.free_func = f_audio_free;
- return &audio->card.func;
+ return &uac1->g_audio.func;
}
DECLARE_USB_FUNCTION_INIT(uac1, f_audio_alloc_inst, f_audio_alloc);
MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Bryan Wu");
+MODULE_AUTHOR("Ruslan Bilovol");
diff --git a/drivers/usb/gadget/function/f_uac1_legacy.c b/drivers/usb/gadget/function/f_uac1_legacy.c
new file mode 100644
index 000000000000..5d229e72912e
--- /dev/null
+++ b/drivers/usb/gadget/function/f_uac1_legacy.c
@@ -0,0 +1,1021 @@
+/*
+ * f_audio.c -- USB Audio class function driver
+ *
+ * Copyright (C) 2008 Bryan Wu <cooloney@kernel.org>
+ * Copyright (C) 2008 Analog Devices, Inc
+ *
+ * Enter bugs at http://blackfin.uclinux.org/
+ *
+ * Licensed under the GPL-2 or later.
+ */
+
+#include <linux/slab.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/device.h>
+#include <linux/atomic.h>
+
+#include "u_uac1_legacy.h"
+
+static int generic_set_cmd(struct usb_audio_control *con, u8 cmd, int value);
+static int generic_get_cmd(struct usb_audio_control *con, u8 cmd);
+
+/*
+ * DESCRIPTORS ... most are static, but strings and full
+ * configuration descriptors are built on demand.
+ */
+
+/*
+ * We have two interfaces- AudioControl and AudioStreaming
+ * TODO: only supcard playback currently
+ */
+#define F_AUDIO_AC_INTERFACE 0
+#define F_AUDIO_AS_INTERFACE 1
+#define F_AUDIO_NUM_INTERFACES 1
+
+/* B.3.1 Standard AC Interface Descriptor */
+static struct usb_interface_descriptor ac_interface_desc = {
+ .bLength = USB_DT_INTERFACE_SIZE,
+ .bDescriptorType = USB_DT_INTERFACE,
+ .bNumEndpoints = 0,
+ .bInterfaceClass = USB_CLASS_AUDIO,
+ .bInterfaceSubClass = USB_SUBCLASS_AUDIOCONTROL,
+};
+
+/*
+ * The number of AudioStreaming and MIDIStreaming interfaces
+ * in the Audio Interface Collection
+ */
+DECLARE_UAC_AC_HEADER_DESCRIPTOR(1);
+
+#define UAC_DT_AC_HEADER_LENGTH UAC_DT_AC_HEADER_SIZE(F_AUDIO_NUM_INTERFACES)
+/* 1 input terminal, 1 output terminal and 1 feature unit */
+#define UAC_DT_TOTAL_LENGTH (UAC_DT_AC_HEADER_LENGTH + UAC_DT_INPUT_TERMINAL_SIZE \
+ + UAC_DT_OUTPUT_TERMINAL_SIZE + UAC_DT_FEATURE_UNIT_SIZE(0))
+/* B.3.2 Class-Specific AC Interface Descriptor */
+static struct uac1_ac_header_descriptor_1 ac_header_desc = {
+ .bLength = UAC_DT_AC_HEADER_LENGTH,
+ .bDescriptorType = USB_DT_CS_INTERFACE,
+ .bDescriptorSubtype = UAC_HEADER,
+ .bcdADC = __constant_cpu_to_le16(0x0100),
+ .wTotalLength = __constant_cpu_to_le16(UAC_DT_TOTAL_LENGTH),
+ .bInCollection = F_AUDIO_NUM_INTERFACES,
+ .baInterfaceNr = {
+ /* Interface number of the first AudioStream interface */
+ [0] = 1,
+ }
+};
+
+#define INPUT_TERMINAL_ID 1
+static struct uac_input_terminal_descriptor input_terminal_desc = {
+ .bLength = UAC_DT_INPUT_TERMINAL_SIZE,
+ .bDescriptorType = USB_DT_CS_INTERFACE,
+ .bDescriptorSubtype = UAC_INPUT_TERMINAL,
+ .bTerminalID = INPUT_TERMINAL_ID,
+ .wTerminalType = UAC_TERMINAL_STREAMING,
+ .bAssocTerminal = 0,
+ .wChannelConfig = 0x3,
+};
+
+DECLARE_UAC_FEATURE_UNIT_DESCRIPTOR(0);
+
+#define FEATURE_UNIT_ID 2
+static struct uac_feature_unit_descriptor_0 feature_unit_desc = {
+ .bLength = UAC_DT_FEATURE_UNIT_SIZE(0),
+ .bDescriptorType = USB_DT_CS_INTERFACE,
+ .bDescriptorSubtype = UAC_FEATURE_UNIT,
+ .bUnitID = FEATURE_UNIT_ID,
+ .bSourceID = INPUT_TERMINAL_ID,
+ .bControlSize = 2,
+ .bmaControls[0] = (UAC_FU_MUTE | UAC_FU_VOLUME),
+};
+
+static struct usb_audio_control mute_control = {
+ .list = LIST_HEAD_INIT(mute_control.list),
+ .name = "Mute Control",
+ .type = UAC_FU_MUTE,
+ /* Todo: add real Mute control code */
+ .set = generic_set_cmd,
+ .get = generic_get_cmd,
+};
+
+static struct usb_audio_control volume_control = {
+ .list = LIST_HEAD_INIT(volume_control.list),
+ .name = "Volume Control",
+ .type = UAC_FU_VOLUME,
+ /* Todo: add real Volume control code */
+ .set = generic_set_cmd,
+ .get = generic_get_cmd,
+};
+
+static struct usb_audio_control_selector feature_unit = {
+ .list = LIST_HEAD_INIT(feature_unit.list),
+ .id = FEATURE_UNIT_ID,
+ .name = "Mute & Volume Control",
+ .type = UAC_FEATURE_UNIT,
+ .desc = (struct usb_descriptor_header *)&feature_unit_desc,
+};
+
+#define OUTPUT_TERMINAL_ID 3
+static struct uac1_output_terminal_descriptor output_terminal_desc = {
+ .bLength = UAC_DT_OUTPUT_TERMINAL_SIZE,
+ .bDescriptorType = USB_DT_CS_INTERFACE,
+ .bDescriptorSubtype = UAC_OUTPUT_TERMINAL,
+ .bTerminalID = OUTPUT_TERMINAL_ID,
+ .wTerminalType = UAC_OUTPUT_TERMINAL_SPEAKER,
+ .bAssocTerminal = FEATURE_UNIT_ID,
+ .bSourceID = FEATURE_UNIT_ID,
+};
+
+/* B.4.1 Standard AS Interface Descriptor */
+static struct usb_interface_descriptor as_interface_alt_0_desc = {
+ .bLength = USB_DT_INTERFACE_SIZE,
+ .bDescriptorType = USB_DT_INTERFACE,
+ .bAlternateSetting = 0,
+ .bNumEndpoints = 0,
+ .bInterfaceClass = USB_CLASS_AUDIO,
+ .bInterfaceSubClass = USB_SUBCLASS_AUDIOSTREAMING,
+};
+
+static struct usb_interface_descriptor as_interface_alt_1_desc = {
+ .bLength = USB_DT_INTERFACE_SIZE,
+ .bDescriptorType = USB_DT_INTERFACE,
+ .bAlternateSetting = 1,
+ .bNumEndpoints = 1,
+ .bInterfaceClass = USB_CLASS_AUDIO,
+ .bInterfaceSubClass = USB_SUBCLASS_AUDIOSTREAMING,
+};
+
+/* B.4.2 Class-Specific AS Interface Descriptor */
+static struct uac1_as_header_descriptor as_header_desc = {
+ .bLength = UAC_DT_AS_HEADER_SIZE,
+ .bDescriptorType = USB_DT_CS_INTERFACE,
+ .bDescriptorSubtype = UAC_AS_GENERAL,
+ .bTerminalLink = INPUT_TERMINAL_ID,
+ .bDelay = 1,
+ .wFormatTag = UAC_FORMAT_TYPE_I_PCM,
+};
+
+DECLARE_UAC_FORMAT_TYPE_I_DISCRETE_DESC(1);
+
+static struct uac_format_type_i_discrete_descriptor_1 as_type_i_desc = {
+ .bLength = UAC_FORMAT_TYPE_I_DISCRETE_DESC_SIZE(1),
+ .bDescriptorType = USB_DT_CS_INTERFACE,
+ .bDescriptorSubtype = UAC_FORMAT_TYPE,
+ .bFormatType = UAC_FORMAT_TYPE_I,
+ .bSubframeSize = 2,
+ .bBitResolution = 16,
+ .bSamFreqType = 1,
+};
+
+/* Standard ISO OUT Endpoint Descriptor */
+static struct usb_endpoint_descriptor as_out_ep_desc = {
+ .bLength = USB_DT_ENDPOINT_AUDIO_SIZE,
+ .bDescriptorType = USB_DT_ENDPOINT,
+ .bEndpointAddress = USB_DIR_OUT,
+ .bmAttributes = USB_ENDPOINT_SYNC_ADAPTIVE
+ | USB_ENDPOINT_XFER_ISOC,
+ .wMaxPacketSize = cpu_to_le16(UAC1_OUT_EP_MAX_PACKET_SIZE),
+ .bInterval = 4,
+};
+
+/* Class-specific AS ISO OUT Endpoint Descriptor */
+static struct uac_iso_endpoint_descriptor as_iso_out_desc = {
+ .bLength = UAC_ISO_ENDPOINT_DESC_SIZE,
+ .bDescriptorType = USB_DT_CS_ENDPOINT,
+ .bDescriptorSubtype = UAC_EP_GENERAL,
+ .bmAttributes = 1,
+ .bLockDelayUnits = 1,
+ .wLockDelay = __constant_cpu_to_le16(1),
+};
+
+static struct usb_descriptor_header *f_audio_desc[] = {
+ (struct usb_descriptor_header *)&ac_interface_desc,
+ (struct usb_descriptor_header *)&ac_header_desc,
+
+ (struct usb_descriptor_header *)&input_terminal_desc,
+ (struct usb_descriptor_header *)&output_terminal_desc,
+ (struct usb_descriptor_header *)&feature_unit_desc,
+
+ (struct usb_descriptor_header *)&as_interface_alt_0_desc,
+ (struct usb_descriptor_header *)&as_interface_alt_1_desc,
+ (struct usb_descriptor_header *)&as_header_desc,
+
+ (struct usb_descriptor_header *)&as_type_i_desc,
+
+ (struct usb_descriptor_header *)&as_out_ep_desc,
+ (struct usb_descriptor_header *)&as_iso_out_desc,
+ NULL,
+};
+
+enum {
+ STR_AC_IF,
+ STR_INPUT_TERMINAL,
+ STR_INPUT_TERMINAL_CH_NAMES,
+ STR_FEAT_DESC_0,
+ STR_OUTPUT_TERMINAL,
+ STR_AS_IF_ALT0,
+ STR_AS_IF_ALT1,
+};
+
+static struct usb_string strings_uac1[] = {
+ [STR_AC_IF].s = "AC Interface",
+ [STR_INPUT_TERMINAL].s = "Input terminal",
+ [STR_INPUT_TERMINAL_CH_NAMES].s = "Channels",
+ [STR_FEAT_DESC_0].s = "Volume control & mute",
+ [STR_OUTPUT_TERMINAL].s = "Output terminal",
+ [STR_AS_IF_ALT0].s = "AS Interface",
+ [STR_AS_IF_ALT1].s = "AS Interface",
+ { },
+};
+
+static struct usb_gadget_strings str_uac1 = {
+ .language = 0x0409, /* en-us */
+ .strings = strings_uac1,
+};
+
+static struct usb_gadget_strings *uac1_strings[] = {
+ &str_uac1,
+ NULL,
+};
+
+/*
+ * This function is an ALSA sound card following USB Audio Class Spec 1.0.
+ */
+
+/*-------------------------------------------------------------------------*/
+struct f_audio_buf {
+ u8 *buf;
+ int actual;
+ struct list_head list;
+};
+
+static struct f_audio_buf *f_audio_buffer_alloc(int buf_size)
+{
+ struct f_audio_buf *copy_buf;
+
+ copy_buf = kzalloc(sizeof *copy_buf, GFP_ATOMIC);
+ if (!copy_buf)
+ return ERR_PTR(-ENOMEM);
+
+ copy_buf->buf = kzalloc(buf_size, GFP_ATOMIC);
+ if (!copy_buf->buf) {
+ kfree(copy_buf);
+ return ERR_PTR(-ENOMEM);
+ }
+
+ return copy_buf;
+}
+
+static void f_audio_buffer_free(struct f_audio_buf *audio_buf)
+{
+ kfree(audio_buf->buf);
+ kfree(audio_buf);
+}
+/*-------------------------------------------------------------------------*/
+
+struct f_audio {
+ struct gaudio card;
+
+ u8 ac_intf, ac_alt;
+ u8 as_intf, as_alt;
+
+ /* endpoints handle full and/or high speeds */
+ struct usb_ep *out_ep;
+
+ spinlock_t lock;
+ struct f_audio_buf *copy_buf;
+ struct work_struct playback_work;
+ struct list_head play_queue;
+
+ /* Control Set command */
+ struct list_head cs;
+ u8 set_cmd;
+ struct usb_audio_control *set_con;
+};
+
+static inline struct f_audio *func_to_audio(struct usb_function *f)
+{
+ return container_of(f, struct f_audio, card.func);
+}
+
+/*-------------------------------------------------------------------------*/
+
+static void f_audio_playback_work(struct work_struct *data)
+{
+ struct f_audio *audio = container_of(data, struct f_audio,
+ playback_work);
+ struct f_audio_buf *play_buf;
+
+ spin_lock_irq(&audio->lock);
+ if (list_empty(&audio->play_queue)) {
+ spin_unlock_irq(&audio->lock);
+ return;
+ }
+ play_buf = list_first_entry(&audio->play_queue,
+ struct f_audio_buf, list);
+ list_del(&play_buf->list);
+ spin_unlock_irq(&audio->lock);
+
+ u_audio_playback(&audio->card, play_buf->buf, play_buf->actual);
+ f_audio_buffer_free(play_buf);
+}
+
+static int f_audio_out_ep_complete(struct usb_ep *ep, struct usb_request *req)
+{
+ struct f_audio *audio = req->context;
+ struct usb_composite_dev *cdev = audio->card.func.config->cdev;
+ struct f_audio_buf *copy_buf = audio->copy_buf;
+ struct f_uac1_legacy_opts *opts;
+ int audio_buf_size;
+ int err;
+
+ opts = container_of(audio->card.func.fi, struct f_uac1_legacy_opts,
+ func_inst);
+ audio_buf_size = opts->audio_buf_size;
+
+ if (!copy_buf)
+ return -EINVAL;
+
+ /* Copy buffer is full, add it to the play_queue */
+ if (audio_buf_size - copy_buf->actual < req->actual) {
+ list_add_tail(&copy_buf->list, &audio->play_queue);
+ schedule_work(&audio->playback_work);
+ copy_buf = f_audio_buffer_alloc(audio_buf_size);
+ if (IS_ERR(copy_buf))
+ return -ENOMEM;
+ }
+
+ memcpy(copy_buf->buf + copy_buf->actual, req->buf, req->actual);
+ copy_buf->actual += req->actual;
+ audio->copy_buf = copy_buf;
+
+ err = usb_ep_queue(ep, req, GFP_ATOMIC);
+ if (err)
+ ERROR(cdev, "%s queue req: %d\n", ep->name, err);
+
+ return 0;
+
+}
+
+static void f_audio_complete(struct usb_ep *ep, struct usb_request *req)
+{
+ struct f_audio *audio = req->context;
+ int status = req->status;
+ u32 data = 0;
+ struct usb_ep *out_ep = audio->out_ep;
+
+ switch (status) {
+
+ case 0: /* normal completion? */
+ if (ep == out_ep)
+ f_audio_out_ep_complete(ep, req);
+ else if (audio->set_con) {
+ memcpy(&data, req->buf, req->length);
+ audio->set_con->set(audio->set_con, audio->set_cmd,
+ le16_to_cpu(data));
+ audio->set_con = NULL;
+ }
+ break;
+ default:
+ break;
+ }
+}
+
+static int audio_set_intf_req(struct usb_function *f,
+ const struct usb_ctrlrequest *ctrl)
+{
+ struct f_audio *audio = func_to_audio(f);
+ struct usb_composite_dev *cdev = f->config->cdev;
+ struct usb_request *req = cdev->req;
+ u8 id = ((le16_to_cpu(ctrl->wIndex) >> 8) & 0xFF);
+ u16 len = le16_to_cpu(ctrl->wLength);
+ u16 w_value = le16_to_cpu(ctrl->wValue);
+ u8 con_sel = (w_value >> 8) & 0xFF;
+ u8 cmd = (ctrl->bRequest & 0x0F);
+ struct usb_audio_control_selector *cs;
+ struct usb_audio_control *con;
+
+ DBG(cdev, "bRequest 0x%x, w_value 0x%04x, len %d, entity %d\n",
+ ctrl->bRequest, w_value, len, id);
+
+ list_for_each_entry(cs, &audio->cs, list) {
+ if (cs->id == id) {
+ list_for_each_entry(con, &cs->control, list) {
+ if (con->type == con_sel) {
+ audio->set_con = con;
+ break;
+ }
+ }
+ break;
+ }
+ }
+
+ audio->set_cmd = cmd;
+ req->context = audio;
+ req->complete = f_audio_complete;
+
+ return len;
+}
+
+static int audio_get_intf_req(struct usb_function *f,
+ const struct usb_ctrlrequest *ctrl)
+{
+ struct f_audio *audio = func_to_audio(f);
+ struct usb_composite_dev *cdev = f->config->cdev;
+ struct usb_request *req = cdev->req;
+ int value = -EOPNOTSUPP;
+ u8 id = ((le16_to_cpu(ctrl->wIndex) >> 8) & 0xFF);
+ u16 len = le16_to_cpu(ctrl->wLength);
+ u16 w_value = le16_to_cpu(ctrl->wValue);
+ u8 con_sel = (w_value >> 8) & 0xFF;
+ u8 cmd = (ctrl->bRequest & 0x0F);
+ struct usb_audio_control_selector *cs;
+ struct usb_audio_control *con;
+
+ DBG(cdev, "bRequest 0x%x, w_value 0x%04x, len %d, entity %d\n",
+ ctrl->bRequest, w_value, len, id);
+
+ list_for_each_entry(cs, &audio->cs, list) {
+ if (cs->id == id) {
+ list_for_each_entry(con, &cs->control, list) {
+ if (con->type == con_sel && con->get) {
+ value = con->get(con, cmd);
+ break;
+ }
+ }
+ break;
+ }
+ }
+
+ req->context = audio;
+ req->complete = f_audio_complete;
+ len = min_t(size_t, sizeof(value), len);
+ memcpy(req->buf, &value, len);
+
+ return len;
+}
+
+static int audio_set_endpoint_req(struct usb_function *f,
+ const struct usb_ctrlrequest *ctrl)
+{
+ struct usb_composite_dev *cdev = f->config->cdev;
+ int value = -EOPNOTSUPP;
+ u16 ep = le16_to_cpu(ctrl->wIndex);
+ u16 len = le16_to_cpu(ctrl->wLength);
+ u16 w_value = le16_to_cpu(ctrl->wValue);
+
+ DBG(cdev, "bRequest 0x%x, w_value 0x%04x, len %d, endpoint %d\n",
+ ctrl->bRequest, w_value, len, ep);
+
+ switch (ctrl->bRequest) {
+ case UAC_SET_CUR:
+ value = len;
+ break;
+
+ case UAC_SET_MIN:
+ break;
+
+ case UAC_SET_MAX:
+ break;
+
+ case UAC_SET_RES:
+ break;
+
+ case UAC_SET_MEM:
+ break;
+
+ default:
+ break;
+ }
+
+ return value;
+}
+
+static int audio_get_endpoint_req(struct usb_function *f,
+ const struct usb_ctrlrequest *ctrl)
+{
+ struct usb_composite_dev *cdev = f->config->cdev;
+ int value = -EOPNOTSUPP;
+ u8 ep = ((le16_to_cpu(ctrl->wIndex) >> 8) & 0xFF);
+ u16 len = le16_to_cpu(ctrl->wLength);
+ u16 w_value = le16_to_cpu(ctrl->wValue);
+
+ DBG(cdev, "bRequest 0x%x, w_value 0x%04x, len %d, endpoint %d\n",
+ ctrl->bRequest, w_value, len, ep);
+
+ switch (ctrl->bRequest) {
+ case UAC_GET_CUR:
+ case UAC_GET_MIN:
+ case UAC_GET_MAX:
+ case UAC_GET_RES:
+ value = len;
+ break;
+ case UAC_GET_MEM:
+ break;
+ default:
+ break;
+ }
+
+ return value;
+}
+
+static int
+f_audio_setup(struct usb_function *f, const struct usb_ctrlrequest *ctrl)
+{
+ struct usb_composite_dev *cdev = f->config->cdev;
+ struct usb_request *req = cdev->req;
+ int value = -EOPNOTSUPP;
+ u16 w_index = le16_to_cpu(ctrl->wIndex);
+ u16 w_value = le16_to_cpu(ctrl->wValue);
+ u16 w_length = le16_to_cpu(ctrl->wLength);
+
+ /* composite driver infrastructure handles everything; interface
+ * activation uses set_alt().
+ */
+ switch (ctrl->bRequestType) {
+ case USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE:
+ value = audio_set_intf_req(f, ctrl);
+ break;
+
+ case USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_INTERFACE:
+ value = audio_get_intf_req(f, ctrl);
+ break;
+
+ case USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_ENDPOINT:
+ value = audio_set_endpoint_req(f, ctrl);
+ break;
+
+ case USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_ENDPOINT:
+ value = audio_get_endpoint_req(f, ctrl);
+ break;
+
+ default:
+ ERROR(cdev, "invalid control req%02x.%02x v%04x i%04x l%d\n",
+ ctrl->bRequestType, ctrl->bRequest,
+ w_value, w_index, w_length);
+ }
+
+ /* respond with data transfer or status phase? */
+ if (value >= 0) {
+ DBG(cdev, "audio req%02x.%02x v%04x i%04x l%d\n",
+ ctrl->bRequestType, ctrl->bRequest,
+ w_value, w_index, w_length);
+ req->zero = 0;
+ req->length = value;
+ value = usb_ep_queue(cdev->gadget->ep0, req, GFP_ATOMIC);
+ if (value < 0)
+ ERROR(cdev, "audio response on err %d\n", value);
+ }
+
+ /* device either stalls (value < 0) or reports success */
+ return value;
+}
+
+static int f_audio_set_alt(struct usb_function *f, unsigned intf, unsigned alt)
+{
+ struct f_audio *audio = func_to_audio(f);
+ struct usb_composite_dev *cdev = f->config->cdev;
+ struct usb_ep *out_ep = audio->out_ep;
+ struct usb_request *req;
+ struct f_uac1_legacy_opts *opts;
+ int req_buf_size, req_count, audio_buf_size;
+ int i = 0, err = 0;
+
+ DBG(cdev, "intf %d, alt %d\n", intf, alt);
+
+ opts = container_of(f->fi, struct f_uac1_legacy_opts, func_inst);
+ req_buf_size = opts->req_buf_size;
+ req_count = opts->req_count;
+ audio_buf_size = opts->audio_buf_size;
+
+ /* No i/f has more than 2 alt settings */
+ if (alt > 1) {
+ ERROR(cdev, "%s:%d Error!\n", __func__, __LINE__);
+ return -EINVAL;
+ }
+
+ if (intf == audio->ac_intf) {
+ /* Control I/f has only 1 AltSetting - 0 */
+ if (alt) {
+ ERROR(cdev, "%s:%d Error!\n", __func__, __LINE__);
+ return -EINVAL;
+ }
+ return 0;
+ } else if (intf == audio->as_intf) {
+ if (alt == 1) {
+ err = config_ep_by_speed(cdev->gadget, f, out_ep);
+ if (err)
+ return err;
+
+ usb_ep_enable(out_ep);
+ audio->copy_buf = f_audio_buffer_alloc(audio_buf_size);
+ if (IS_ERR(audio->copy_buf))
+ return -ENOMEM;
+
+ /*
+ * allocate a bunch of read buffers
+ * and queue them all at once.
+ */
+ for (i = 0; i < req_count && err == 0; i++) {
+ req = usb_ep_alloc_request(out_ep, GFP_ATOMIC);
+ if (req) {
+ req->buf = kzalloc(req_buf_size,
+ GFP_ATOMIC);
+ if (req->buf) {
+ req->length = req_buf_size;
+ req->context = audio;
+ req->complete =
+ f_audio_complete;
+ err = usb_ep_queue(out_ep,
+ req, GFP_ATOMIC);
+ if (err)
+ ERROR(cdev,
+ "%s queue req: %d\n",
+ out_ep->name, err);
+ } else
+ err = -ENOMEM;
+ } else
+ err = -ENOMEM;
+ }
+
+ } else {
+ struct f_audio_buf *copy_buf = audio->copy_buf;
+ if (copy_buf) {
+ list_add_tail(&copy_buf->list,
+ &audio->play_queue);
+ schedule_work(&audio->playback_work);
+ }
+ }
+ audio->as_alt = alt;
+ }
+
+ return err;
+}
+
+static int f_audio_get_alt(struct usb_function *f, unsigned intf)
+{
+ struct f_audio *audio = func_to_audio(f);
+ struct usb_composite_dev *cdev = f->config->cdev;
+
+ if (intf == audio->ac_intf)
+ return audio->ac_alt;
+ else if (intf == audio->as_intf)
+ return audio->as_alt;
+ else
+ ERROR(cdev, "%s:%d Invalid Interface %d!\n",
+ __func__, __LINE__, intf);
+
+ return -EINVAL;
+}
+
+static void f_audio_disable(struct usb_function *f)
+{
+ return;
+}
+
+/*-------------------------------------------------------------------------*/
+
+static void f_audio_build_desc(struct f_audio *audio)
+{
+ struct gaudio *card = &audio->card;
+ u8 *sam_freq;
+ int rate;
+
+ /* Set channel numbers */
+ input_terminal_desc.bNrChannels = u_audio_get_playback_channels(card);
+ as_type_i_desc.bNrChannels = u_audio_get_playback_channels(card);
+
+ /* Set sample rates */
+ rate = u_audio_get_playback_rate(card);
+ sam_freq = as_type_i_desc.tSamFreq[0];
+ memcpy(sam_freq, &rate, 3);
+
+ /* Todo: Set Sample bits and other parameters */
+
+ return;
+}
+
+/* audio function driver setup/binding */
+static int
+f_audio_bind(struct usb_configuration *c, struct usb_function *f)
+{
+ struct usb_composite_dev *cdev = c->cdev;
+ struct f_audio *audio = func_to_audio(f);
+ struct usb_string *us;
+ int status;
+ struct usb_ep *ep = NULL;
+ struct f_uac1_legacy_opts *audio_opts;
+
+ audio_opts = container_of(f->fi, struct f_uac1_legacy_opts, func_inst);
+ audio->card.gadget = c->cdev->gadget;
+ /* set up ASLA audio devices */
+ if (!audio_opts->bound) {
+ status = gaudio_setup(&audio->card);
+ if (status < 0)
+ return status;
+ audio_opts->bound = true;
+ }
+ us = usb_gstrings_attach(cdev, uac1_strings, ARRAY_SIZE(strings_uac1));
+ if (IS_ERR(us))
+ return PTR_ERR(us);
+ ac_interface_desc.iInterface = us[STR_AC_IF].id;
+ input_terminal_desc.iTerminal = us[STR_INPUT_TERMINAL].id;
+ input_terminal_desc.iChannelNames = us[STR_INPUT_TERMINAL_CH_NAMES].id;
+ feature_unit_desc.iFeature = us[STR_FEAT_DESC_0].id;
+ output_terminal_desc.iTerminal = us[STR_OUTPUT_TERMINAL].id;
+ as_interface_alt_0_desc.iInterface = us[STR_AS_IF_ALT0].id;
+ as_interface_alt_1_desc.iInterface = us[STR_AS_IF_ALT1].id;
+
+
+ f_audio_build_desc(audio);
+
+ /* allocate instance-specific interface IDs, and patch descriptors */
+ status = usb_interface_id(c, f);
+ if (status < 0)
+ goto fail;
+ ac_interface_desc.bInterfaceNumber = status;
+ audio->ac_intf = status;
+ audio->ac_alt = 0;
+
+ status = usb_interface_id(c, f);
+ if (status < 0)
+ goto fail;
+ as_interface_alt_0_desc.bInterfaceNumber = status;
+ as_interface_alt_1_desc.bInterfaceNumber = status;
+ audio->as_intf = status;
+ audio->as_alt = 0;
+
+ status = -ENODEV;
+
+ /* allocate instance-specific endpoints */
+ ep = usb_ep_autoconfig(cdev->gadget, &as_out_ep_desc);
+ if (!ep)
+ goto fail;
+ audio->out_ep = ep;
+ audio->out_ep->desc = &as_out_ep_desc;
+
+ status = -ENOMEM;
+
+ /* copy descriptors, and track endpoint copies */
+ status = usb_assign_descriptors(f, f_audio_desc, f_audio_desc, NULL,
+ NULL);
+ if (status)
+ goto fail;
+ return 0;
+
+fail:
+ gaudio_cleanup(&audio->card);
+ return status;
+}
+
+/*-------------------------------------------------------------------------*/
+
+static int generic_set_cmd(struct usb_audio_control *con, u8 cmd, int value)
+{
+ con->data[cmd] = value;
+
+ return 0;
+}
+
+static int generic_get_cmd(struct usb_audio_control *con, u8 cmd)
+{
+ return con->data[cmd];
+}
+
+/* Todo: add more control selecotor dynamically */
+static int control_selector_init(struct f_audio *audio)
+{
+ INIT_LIST_HEAD(&audio->cs);
+ list_add(&feature_unit.list, &audio->cs);
+
+ INIT_LIST_HEAD(&feature_unit.control);
+ list_add(&mute_control.list, &feature_unit.control);
+ list_add(&volume_control.list, &feature_unit.control);
+
+ volume_control.data[UAC__CUR] = 0xffc0;
+ volume_control.data[UAC__MIN] = 0xe3a0;
+ volume_control.data[UAC__MAX] = 0xfff0;
+ volume_control.data[UAC__RES] = 0x0030;
+
+ return 0;
+}
+
+static inline
+struct f_uac1_legacy_opts *to_f_uac1_opts(struct config_item *item)
+{
+ return container_of(to_config_group(item), struct f_uac1_legacy_opts,
+ func_inst.group);
+}
+
+static void f_uac1_attr_release(struct config_item *item)
+{
+ struct f_uac1_legacy_opts *opts = to_f_uac1_opts(item);
+
+ usb_put_function_instance(&opts->func_inst);
+}
+
+static struct configfs_item_operations f_uac1_item_ops = {
+ .release = f_uac1_attr_release,
+};
+
+#define UAC1_INT_ATTRIBUTE(name) \
+static ssize_t f_uac1_opts_##name##_show(struct config_item *item, \
+ char *page) \
+{ \
+ struct f_uac1_legacy_opts *opts = to_f_uac1_opts(item); \
+ int result; \
+ \
+ mutex_lock(&opts->lock); \
+ result = sprintf(page, "%u\n", opts->name); \
+ mutex_unlock(&opts->lock); \
+ \
+ return result; \
+} \
+ \
+static ssize_t f_uac1_opts_##name##_store(struct config_item *item, \
+ const char *page, size_t len) \
+{ \
+ struct f_uac1_legacy_opts *opts = to_f_uac1_opts(item); \
+ int ret; \
+ u32 num; \
+ \
+ mutex_lock(&opts->lock); \
+ if (opts->refcnt) { \
+ ret = -EBUSY; \
+ goto end; \
+ } \
+ \
+ ret = kstrtou32(page, 0, &num); \
+ if (ret) \
+ goto end; \
+ \
+ opts->name = num; \
+ ret = len; \
+ \
+end: \
+ mutex_unlock(&opts->lock); \
+ return ret; \
+} \
+ \
+CONFIGFS_ATTR(f_uac1_opts_, name)
+
+UAC1_INT_ATTRIBUTE(req_buf_size);
+UAC1_INT_ATTRIBUTE(req_count);
+UAC1_INT_ATTRIBUTE(audio_buf_size);
+
+#define UAC1_STR_ATTRIBUTE(name) \
+static ssize_t f_uac1_opts_##name##_show(struct config_item *item, \
+ char *page) \
+{ \
+ struct f_uac1_legacy_opts *opts = to_f_uac1_opts(item); \
+ int result; \
+ \
+ mutex_lock(&opts->lock); \
+ result = sprintf(page, "%s\n", opts->name); \
+ mutex_unlock(&opts->lock); \
+ \
+ return result; \
+} \
+ \
+static ssize_t f_uac1_opts_##name##_store(struct config_item *item, \
+ const char *page, size_t len) \
+{ \
+ struct f_uac1_legacy_opts *opts = to_f_uac1_opts(item); \
+ int ret = -EBUSY; \
+ char *tmp; \
+ \
+ mutex_lock(&opts->lock); \
+ if (opts->refcnt) \
+ goto end; \
+ \
+ tmp = kstrndup(page, len, GFP_KERNEL); \
+ if (tmp) { \
+ ret = -ENOMEM; \
+ goto end; \
+ } \
+ if (opts->name##_alloc) \
+ kfree(opts->name); \
+ opts->name##_alloc = true; \
+ opts->name = tmp; \
+ ret = len; \
+ \
+end: \
+ mutex_unlock(&opts->lock); \
+ return ret; \
+} \
+ \
+CONFIGFS_ATTR(f_uac1_opts_, name)
+
+UAC1_STR_ATTRIBUTE(fn_play);
+UAC1_STR_ATTRIBUTE(fn_cap);
+UAC1_STR_ATTRIBUTE(fn_cntl);
+
+static struct configfs_attribute *f_uac1_attrs[] = {
+ &f_uac1_opts_attr_req_buf_size,
+ &f_uac1_opts_attr_req_count,
+ &f_uac1_opts_attr_audio_buf_size,
+ &f_uac1_opts_attr_fn_play,
+ &f_uac1_opts_attr_fn_cap,
+ &f_uac1_opts_attr_fn_cntl,
+ NULL,
+};
+
+static struct config_item_type f_uac1_func_type = {
+ .ct_item_ops = &f_uac1_item_ops,
+ .ct_attrs = f_uac1_attrs,
+ .ct_owner = THIS_MODULE,
+};
+
+static void f_audio_free_inst(struct usb_function_instance *f)
+{
+ struct f_uac1_legacy_opts *opts;
+
+ opts = container_of(f, struct f_uac1_legacy_opts, func_inst);
+ if (opts->fn_play_alloc)
+ kfree(opts->fn_play);
+ if (opts->fn_cap_alloc)
+ kfree(opts->fn_cap);
+ if (opts->fn_cntl_alloc)
+ kfree(opts->fn_cntl);
+ kfree(opts);
+}
+
+static struct usb_function_instance *f_audio_alloc_inst(void)
+{
+ struct f_uac1_legacy_opts *opts;
+
+ opts = kzalloc(sizeof(*opts), GFP_KERNEL);
+ if (!opts)
+ return ERR_PTR(-ENOMEM);
+
+ mutex_init(&opts->lock);
+ opts->func_inst.free_func_inst = f_audio_free_inst;
+
+ config_group_init_type_name(&opts->func_inst.group, "",
+ &f_uac1_func_type);
+
+ opts->req_buf_size = UAC1_OUT_EP_MAX_PACKET_SIZE;
+ opts->req_count = UAC1_REQ_COUNT;
+ opts->audio_buf_size = UAC1_AUDIO_BUF_SIZE;
+ opts->fn_play = FILE_PCM_PLAYBACK;
+ opts->fn_cap = FILE_PCM_CAPTURE;
+ opts->fn_cntl = FILE_CONTROL;
+ return &opts->func_inst;
+}
+
+static void f_audio_free(struct usb_function *f)
+{
+ struct f_audio *audio = func_to_audio(f);
+ struct f_uac1_legacy_opts *opts;
+
+ gaudio_cleanup(&audio->card);
+ opts = container_of(f->fi, struct f_uac1_legacy_opts, func_inst);
+ kfree(audio);
+ mutex_lock(&opts->lock);
+ --opts->refcnt;
+ mutex_unlock(&opts->lock);
+}
+
+static void f_audio_unbind(struct usb_configuration *c, struct usb_function *f)
+{
+ usb_free_all_descriptors(f);
+}
+
+static struct usb_function *f_audio_alloc(struct usb_function_instance *fi)
+{
+ struct f_audio *audio;
+ struct f_uac1_legacy_opts *opts;
+
+ /* allocate and initialize one new instance */
+ audio = kzalloc(sizeof(*audio), GFP_KERNEL);
+ if (!audio)
+ return ERR_PTR(-ENOMEM);
+
+ audio->card.func.name = "g_audio";
+
+ opts = container_of(fi, struct f_uac1_legacy_opts, func_inst);
+ mutex_lock(&opts->lock);
+ ++opts->refcnt;
+ mutex_unlock(&opts->lock);
+ INIT_LIST_HEAD(&audio->play_queue);
+ spin_lock_init(&audio->lock);
+
+ audio->card.func.bind = f_audio_bind;
+ audio->card.func.unbind = f_audio_unbind;
+ audio->card.func.set_alt = f_audio_set_alt;
+ audio->card.func.get_alt = f_audio_get_alt;
+ audio->card.func.setup = f_audio_setup;
+ audio->card.func.disable = f_audio_disable;
+ audio->card.func.free_func = f_audio_free;
+
+ control_selector_init(audio);
+
+ INIT_WORK(&audio->playback_work, f_audio_playback_work);
+
+ return &audio->card.func;
+}
+
+DECLARE_USB_FUNCTION_INIT(uac1_legacy, f_audio_alloc_inst, f_audio_alloc);
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Bryan Wu");
diff --git a/drivers/usb/gadget/function/f_uac2.c b/drivers/usb/gadget/function/f_uac2.c
index f6a0d3a1311b..9082ce261e70 100644
--- a/drivers/usb/gadget/function/f_uac2.c
+++ b/drivers/usb/gadget/function/f_uac2.c
@@ -13,13 +13,9 @@
#include <linux/usb/audio.h>
#include <linux/usb/audio-v2.h>
-#include <linux/platform_device.h>
#include <linux/module.h>
-#include <sound/core.h>
-#include <sound/pcm.h>
-#include <sound/pcm_params.h>
-
+#include "u_audio.h"
#include "u_uac2.h"
/*
@@ -51,506 +47,23 @@
#define UNFLW_CTRL 8
#define OVFLW_CTRL 10
-static const char *uac2_name = "snd_uac2";
-
-struct uac2_req {
- struct uac2_rtd_params *pp; /* parent param */
- struct usb_request *req;
-};
-
-struct uac2_rtd_params {
- struct snd_uac2_chip *uac2; /* parent chip */
- bool ep_enabled; /* if the ep is enabled */
- /* Size of the ring buffer */
- size_t dma_bytes;
- unsigned char *dma_area;
-
- struct snd_pcm_substream *ss;
-
- /* Ring buffer */
- ssize_t hw_ptr;
-
- void *rbuf;
-
- size_t period_size;
-
- unsigned max_psize;
- struct uac2_req *ureq;
-
- spinlock_t lock;
-};
-
-struct snd_uac2_chip {
- struct platform_device pdev;
- struct platform_driver pdrv;
-
- struct uac2_rtd_params p_prm;
- struct uac2_rtd_params c_prm;
-
- struct snd_card *card;
- struct snd_pcm *pcm;
-
- /* timekeeping for the playback endpoint */
- unsigned int p_interval;
- unsigned int p_residue;
-
- /* pre-calculated values for playback iso completion */
- unsigned int p_pktsize;
- unsigned int p_pktsize_residue;
- unsigned int p_framesize;
+struct f_uac2 {
+ struct g_audio g_audio;
+ u8 ac_intf, as_in_intf, as_out_intf;
+ u8 ac_alt, as_in_alt, as_out_alt; /* needed for get_alt() */
};
-#define BUFF_SIZE_MAX (PAGE_SIZE * 16)
-#define PRD_SIZE_MAX PAGE_SIZE
-#define MIN_PERIODS 4
-
-static struct snd_pcm_hardware uac2_pcm_hardware = {
- .info = SNDRV_PCM_INFO_INTERLEAVED | SNDRV_PCM_INFO_BLOCK_TRANSFER
- | SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_MMAP_VALID
- | SNDRV_PCM_INFO_PAUSE | SNDRV_PCM_INFO_RESUME,
- .rates = SNDRV_PCM_RATE_CONTINUOUS,
- .periods_max = BUFF_SIZE_MAX / PRD_SIZE_MAX,
- .buffer_bytes_max = BUFF_SIZE_MAX,
- .period_bytes_max = PRD_SIZE_MAX,
- .periods_min = MIN_PERIODS,
-};
-
-struct audio_dev {
- u8 ac_intf, ac_alt;
- u8 as_out_intf, as_out_alt;
- u8 as_in_intf, as_in_alt;
-
- struct usb_ep *in_ep, *out_ep;
- struct usb_function func;
-
- /* The ALSA Sound Card it represents on the USB-Client side */
- struct snd_uac2_chip uac2;
-};
-
-static inline
-struct audio_dev *func_to_agdev(struct usb_function *f)
+static inline struct f_uac2 *func_to_uac2(struct usb_function *f)
{
- return container_of(f, struct audio_dev, func);
+ return container_of(f, struct f_uac2, g_audio.func);
}
static inline
-struct audio_dev *uac2_to_agdev(struct snd_uac2_chip *u)
-{
- return container_of(u, struct audio_dev, uac2);
-}
-
-static inline
-struct snd_uac2_chip *pdev_to_uac2(struct platform_device *p)
-{
- return container_of(p, struct snd_uac2_chip, pdev);
-}
-
-static inline
-struct f_uac2_opts *agdev_to_uac2_opts(struct audio_dev *agdev)
+struct f_uac2_opts *g_audio_to_uac2_opts(struct g_audio *agdev)
{
return container_of(agdev->func.fi, struct f_uac2_opts, func_inst);
}
-static inline
-uint num_channels(uint chanmask)
-{
- uint num = 0;
-
- while (chanmask) {
- num += (chanmask & 1);
- chanmask >>= 1;
- }
-
- return num;
-}
-
-static void
-agdev_iso_complete(struct usb_ep *ep, struct usb_request *req)
-{
- unsigned pending;
- unsigned long flags;
- unsigned int hw_ptr;
- bool update_alsa = false;
- int status = req->status;
- struct uac2_req *ur = req->context;
- struct snd_pcm_substream *substream;
- struct uac2_rtd_params *prm = ur->pp;
- struct snd_uac2_chip *uac2 = prm->uac2;
-
- /* i/f shutting down */
- if (!prm->ep_enabled || req->status == -ESHUTDOWN)
- return;
-
- /*
- * We can't really do much about bad xfers.
- * Afterall, the ISOCH xfers could fail legitimately.
- */
- if (status)
- pr_debug("%s: iso_complete status(%d) %d/%d\n",
- __func__, status, req->actual, req->length);
-
- substream = prm->ss;
-
- /* Do nothing if ALSA isn't active */
- if (!substream)
- goto exit;
-
- spin_lock_irqsave(&prm->lock, flags);
-
- if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
- /*
- * For each IN packet, take the quotient of the current data
- * rate and the endpoint's interval as the base packet size.
- * If there is a residue from this division, add it to the
- * residue accumulator.
- */
- req->length = uac2->p_pktsize;
- uac2->p_residue += uac2->p_pktsize_residue;
-
- /*
- * Whenever there are more bytes in the accumulator than we
- * need to add one more sample frame, increase this packet's
- * size and decrease the accumulator.
- */
- if (uac2->p_residue / uac2->p_interval >= uac2->p_framesize) {
- req->length += uac2->p_framesize;
- uac2->p_residue -= uac2->p_framesize *
- uac2->p_interval;
- }
-
- req->actual = req->length;
- }
-
- pending = prm->hw_ptr % prm->period_size;
- pending += req->actual;
- if (pending >= prm->period_size)
- update_alsa = true;
-
- hw_ptr = prm->hw_ptr;
- prm->hw_ptr = (prm->hw_ptr + req->actual) % prm->dma_bytes;
-
- spin_unlock_irqrestore(&prm->lock, flags);
-
- /* Pack USB load in ALSA ring buffer */
- pending = prm->dma_bytes - hw_ptr;
-
- if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
- if (unlikely(pending < req->actual)) {
- memcpy(req->buf, prm->dma_area + hw_ptr, pending);
- memcpy(req->buf + pending, prm->dma_area,
- req->actual - pending);
- } else {
- memcpy(req->buf, prm->dma_area + hw_ptr, req->actual);
- }
- } else {
- if (unlikely(pending < req->actual)) {
- memcpy(prm->dma_area + hw_ptr, req->buf, pending);
- memcpy(prm->dma_area, req->buf + pending,
- req->actual - pending);
- } else {
- memcpy(prm->dma_area + hw_ptr, req->buf, req->actual);
- }
- }
-
-exit:
- if (usb_ep_queue(ep, req, GFP_ATOMIC))
- dev_err(&uac2->pdev.dev, "%d Error!\n", __LINE__);
-
- if (update_alsa)
- snd_pcm_period_elapsed(substream);
-
- return;
-}
-
-static int
-uac2_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
-{
- struct snd_uac2_chip *uac2 = snd_pcm_substream_chip(substream);
- struct audio_dev *agdev = uac2_to_agdev(uac2);
- struct f_uac2_opts *uac2_opts = agdev_to_uac2_opts(agdev);
- struct uac2_rtd_params *prm;
- unsigned long flags;
- int err = 0;
-
- if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
- prm = &uac2->p_prm;
- else
- prm = &uac2->c_prm;
-
- spin_lock_irqsave(&prm->lock, flags);
-
- /* Reset */
- prm->hw_ptr = 0;
-
- switch (cmd) {
- case SNDRV_PCM_TRIGGER_START:
- case SNDRV_PCM_TRIGGER_RESUME:
- prm->ss = substream;
- break;
- case SNDRV_PCM_TRIGGER_STOP:
- case SNDRV_PCM_TRIGGER_SUSPEND:
- prm->ss = NULL;
- break;
- default:
- err = -EINVAL;
- }
-
- spin_unlock_irqrestore(&prm->lock, flags);
-
- /* Clear buffer after Play stops */
- if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK && !prm->ss)
- memset(prm->rbuf, 0, prm->max_psize * uac2_opts->req_number);
-
- return err;
-}
-
-static snd_pcm_uframes_t uac2_pcm_pointer(struct snd_pcm_substream *substream)
-{
- struct snd_uac2_chip *uac2 = snd_pcm_substream_chip(substream);
- struct uac2_rtd_params *prm;
-
- if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
- prm = &uac2->p_prm;
- else
- prm = &uac2->c_prm;
-
- return bytes_to_frames(substream->runtime, prm->hw_ptr);
-}
-
-static int uac2_pcm_hw_params(struct snd_pcm_substream *substream,
- struct snd_pcm_hw_params *hw_params)
-{
- struct snd_uac2_chip *uac2 = snd_pcm_substream_chip(substream);
- struct uac2_rtd_params *prm;
- int err;
-
- if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
- prm = &uac2->p_prm;
- else
- prm = &uac2->c_prm;
-
- err = snd_pcm_lib_malloc_pages(substream,
- params_buffer_bytes(hw_params));
- if (err >= 0) {
- prm->dma_bytes = substream->runtime->dma_bytes;
- prm->dma_area = substream->runtime->dma_area;
- prm->period_size = params_period_bytes(hw_params);
- }
-
- return err;
-}
-
-static int uac2_pcm_hw_free(struct snd_pcm_substream *substream)
-{
- struct snd_uac2_chip *uac2 = snd_pcm_substream_chip(substream);
- struct uac2_rtd_params *prm;
-
- if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
- prm = &uac2->p_prm;
- else
- prm = &uac2->c_prm;
-
- prm->dma_area = NULL;
- prm->dma_bytes = 0;
- prm->period_size = 0;
-
- return snd_pcm_lib_free_pages(substream);
-}
-
-static int uac2_pcm_open(struct snd_pcm_substream *substream)
-{
- struct snd_uac2_chip *uac2 = snd_pcm_substream_chip(substream);
- struct snd_pcm_runtime *runtime = substream->runtime;
- struct audio_dev *audio_dev;
- struct f_uac2_opts *opts;
- int p_ssize, c_ssize;
- int p_srate, c_srate;
- int p_chmask, c_chmask;
-
- audio_dev = uac2_to_agdev(uac2);
- opts = container_of(audio_dev->func.fi, struct f_uac2_opts, func_inst);
- p_ssize = opts->p_ssize;
- c_ssize = opts->c_ssize;
- p_srate = opts->p_srate;
- c_srate = opts->c_srate;
- p_chmask = opts->p_chmask;
- c_chmask = opts->c_chmask;
- uac2->p_residue = 0;
-
- runtime->hw = uac2_pcm_hardware;
-
- if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
- spin_lock_init(&uac2->p_prm.lock);
- runtime->hw.rate_min = p_srate;
- switch (p_ssize) {
- case 3:
- runtime->hw.formats = SNDRV_PCM_FMTBIT_S24_3LE;
- break;
- case 4:
- runtime->hw.formats = SNDRV_PCM_FMTBIT_S32_LE;
- break;
- default:
- runtime->hw.formats = SNDRV_PCM_FMTBIT_S16_LE;
- break;
- }
- runtime->hw.channels_min = num_channels(p_chmask);
- runtime->hw.period_bytes_min = 2 * uac2->p_prm.max_psize
- / runtime->hw.periods_min;
- } else {
- spin_lock_init(&uac2->c_prm.lock);
- runtime->hw.rate_min = c_srate;
- switch (c_ssize) {
- case 3:
- runtime->hw.formats = SNDRV_PCM_FMTBIT_S24_3LE;
- break;
- case 4:
- runtime->hw.formats = SNDRV_PCM_FMTBIT_S32_LE;
- break;
- default:
- runtime->hw.formats = SNDRV_PCM_FMTBIT_S16_LE;
- break;
- }
- runtime->hw.channels_min = num_channels(c_chmask);
- runtime->hw.period_bytes_min = 2 * uac2->c_prm.max_psize
- / runtime->hw.periods_min;
- }
-
- runtime->hw.rate_max = runtime->hw.rate_min;
- runtime->hw.channels_max = runtime->hw.channels_min;
-
- snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIODS);
-
- return 0;
-}
-
-/* ALSA cries without these function pointers */
-static int uac2_pcm_null(struct snd_pcm_substream *substream)
-{
- return 0;
-}
-
-static struct snd_pcm_ops uac2_pcm_ops = {
- .open = uac2_pcm_open,
- .close = uac2_pcm_null,
- .ioctl = snd_pcm_lib_ioctl,
- .hw_params = uac2_pcm_hw_params,
- .hw_free = uac2_pcm_hw_free,
- .trigger = uac2_pcm_trigger,
- .pointer = uac2_pcm_pointer,
- .prepare = uac2_pcm_null,
-};
-
-static int snd_uac2_probe(struct platform_device *pdev)
-{
- struct snd_uac2_chip *uac2 = pdev_to_uac2(pdev);
- struct snd_card *card;
- struct snd_pcm *pcm;
- struct audio_dev *audio_dev;
- struct f_uac2_opts *opts;
- int err;
- int p_chmask, c_chmask;
-
- audio_dev = uac2_to_agdev(uac2);
- opts = container_of(audio_dev->func.fi, struct f_uac2_opts, func_inst);
- p_chmask = opts->p_chmask;
- c_chmask = opts->c_chmask;
-
- /* Choose any slot, with no id */
- err = snd_card_new(&pdev->dev, -1, NULL, THIS_MODULE, 0, &card);
- if (err < 0)
- return err;
-
- uac2->card = card;
-
- /*
- * Create first PCM device
- * Create a substream only for non-zero channel streams
- */
- err = snd_pcm_new(uac2->card, "UAC2 PCM", 0,
- p_chmask ? 1 : 0, c_chmask ? 1 : 0, &pcm);
- if (err < 0)
- goto snd_fail;
-
- strcpy(pcm->name, "UAC2 PCM");
- pcm->private_data = uac2;
-
- uac2->pcm = pcm;
-
- snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &uac2_pcm_ops);
- snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &uac2_pcm_ops);
-
- strcpy(card->driver, "UAC2_Gadget");
- strcpy(card->shortname, "UAC2_Gadget");
- sprintf(card->longname, "UAC2_Gadget %i", pdev->id);
-
- snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_CONTINUOUS,
- snd_dma_continuous_data(GFP_KERNEL), 0, BUFF_SIZE_MAX);
-
- err = snd_card_register(card);
- if (!err) {
- platform_set_drvdata(pdev, card);
- return 0;
- }
-
-snd_fail:
- snd_card_free(card);
-
- uac2->pcm = NULL;
- uac2->card = NULL;
-
- return err;
-}
-
-static int snd_uac2_remove(struct platform_device *pdev)
-{
- struct snd_card *card = platform_get_drvdata(pdev);
-
- if (card)
- return snd_card_free(card);
-
- return 0;
-}
-
-static void snd_uac2_release(struct device *dev)
-{
- dev_dbg(dev, "releasing '%s'\n", dev_name(dev));
-}
-
-static int alsa_uac2_init(struct audio_dev *agdev)
-{
- struct snd_uac2_chip *uac2 = &agdev->uac2;
- int err;
-
- uac2->pdrv.probe = snd_uac2_probe;
- uac2->pdrv.remove = snd_uac2_remove;
- uac2->pdrv.driver.name = uac2_name;
-
- uac2->pdev.id = 0;
- uac2->pdev.name = uac2_name;
- uac2->pdev.dev.release = snd_uac2_release;
-
- /* Register snd_uac2 driver */
- err = platform_driver_register(&uac2->pdrv);
- if (err)
- return err;
-
- /* Register snd_uac2 device */
- err = platform_device_register(&uac2->pdev);
- if (err)
- platform_driver_unregister(&uac2->pdrv);
-
- return err;
-}
-
-static void alsa_uac2_exit(struct audio_dev *agdev)
-{
- struct snd_uac2_chip *uac2 = &agdev->uac2;
-
- platform_driver_unregister(&uac2->pdrv);
- platform_device_unregister(&uac2->pdev);
-}
-
-
/* --------- USB Function Interface ------------- */
enum {
@@ -938,32 +451,6 @@ struct cntrl_range_lay3 {
__u32 dRES;
} __packed;
-static inline void
-free_ep(struct uac2_rtd_params *prm, struct usb_ep *ep)
-{
- struct snd_uac2_chip *uac2 = prm->uac2;
- struct audio_dev *agdev = uac2_to_agdev(uac2);
- struct f_uac2_opts *uac2_opts = agdev_to_uac2_opts(agdev);
- int i;
-
- if (!prm->ep_enabled)
- return;
-
- prm->ep_enabled = false;
-
- for (i = 0; i < uac2_opts->req_number; i++) {
- if (prm->ureq[i].req) {
- usb_ep_dequeue(ep, prm->ureq[i].req);
- usb_ep_free_request(ep, prm->ureq[i].req);
- prm->ureq[i].req = NULL;
- }
- }
-
- if (usb_ep_disable(ep))
- dev_err(&uac2->pdev.dev,
- "%s:%d Error!\n", __func__, __LINE__);
-}
-
static void set_ep_max_packet_size(const struct f_uac2_opts *uac2_opts,
struct usb_endpoint_descriptor *ep_desc,
unsigned int factor, bool is_playback)
@@ -990,12 +477,11 @@ static void set_ep_max_packet_size(const struct f_uac2_opts *uac2_opts,
static int
afunc_bind(struct usb_configuration *cfg, struct usb_function *fn)
{
- struct audio_dev *agdev = func_to_agdev(fn);
- struct snd_uac2_chip *uac2 = &agdev->uac2;
+ struct f_uac2 *uac2 = func_to_uac2(fn);
+ struct g_audio *agdev = func_to_g_audio(fn);
struct usb_composite_dev *cdev = cfg->cdev;
struct usb_gadget *gadget = cdev->gadget;
- struct device *dev = &uac2->pdev.dev;
- struct uac2_rtd_params *prm;
+ struct device *dev = &gadget->dev;
struct f_uac2_opts *uac2_opts;
struct usb_string *us;
int ret;
@@ -1042,8 +528,8 @@ afunc_bind(struct usb_configuration *cfg, struct usb_function *fn)
return ret;
}
std_ac_if_desc.bInterfaceNumber = ret;
- agdev->ac_intf = ret;
- agdev->ac_alt = 0;
+ uac2->ac_intf = ret;
+ uac2->ac_alt = 0;
ret = usb_interface_id(cfg, fn);
if (ret < 0) {
@@ -1052,8 +538,8 @@ afunc_bind(struct usb_configuration *cfg, struct usb_function *fn)
}
std_as_out_if0_desc.bInterfaceNumber = ret;
std_as_out_if1_desc.bInterfaceNumber = ret;
- agdev->as_out_intf = ret;
- agdev->as_out_alt = 0;
+ uac2->as_out_intf = ret;
+ uac2->as_out_alt = 0;
ret = usb_interface_id(cfg, fn);
if (ret < 0) {
@@ -1062,8 +548,14 @@ afunc_bind(struct usb_configuration *cfg, struct usb_function *fn)
}
std_as_in_if0_desc.bInterfaceNumber = ret;
std_as_in_if1_desc.bInterfaceNumber = ret;
- agdev->as_in_intf = ret;
- agdev->as_in_alt = 0;
+ uac2->as_in_intf = ret;
+ uac2->as_in_alt = 0;
+
+ /* Calculate wMaxPacketSize according to audio bandwidth */
+ set_ep_max_packet_size(uac2_opts, &fs_epin_desc, 1000, true);
+ set_ep_max_packet_size(uac2_opts, &fs_epout_desc, 1000, false);
+ set_ep_max_packet_size(uac2_opts, &hs_epin_desc, 8000, true);
+ set_ep_max_packet_size(uac2_opts, &hs_epout_desc, 8000, false);
agdev->out_ep = usb_ep_autoconfig(gadget, &fs_epout_desc);
if (!agdev->out_ep) {
@@ -1077,14 +569,10 @@ afunc_bind(struct usb_configuration *cfg, struct usb_function *fn)
return ret;
}
- uac2->p_prm.uac2 = uac2;
- uac2->c_prm.uac2 = uac2;
-
- /* Calculate wMaxPacketSize according to audio bandwidth */
- set_ep_max_packet_size(uac2_opts, &fs_epin_desc, 1000, true);
- set_ep_max_packet_size(uac2_opts, &fs_epout_desc, 1000, false);
- set_ep_max_packet_size(uac2_opts, &hs_epin_desc, 8000, true);
- set_ep_max_packet_size(uac2_opts, &hs_epout_desc, 8000, false);
+ agdev->in_ep_maxpsize = max(fs_epin_desc.wMaxPacketSize,
+ hs_epin_desc.wMaxPacketSize);
+ agdev->out_ep_maxpsize = max(fs_epout_desc.wMaxPacketSize,
+ hs_epout_desc.wMaxPacketSize);
hs_epout_desc.bEndpointAddress = fs_epout_desc.bEndpointAddress;
hs_epin_desc.bEndpointAddress = fs_epin_desc.bEndpointAddress;
@@ -1094,48 +582,23 @@ afunc_bind(struct usb_configuration *cfg, struct usb_function *fn)
if (ret)
return ret;
- prm = &agdev->uac2.c_prm;
- prm->max_psize = hs_epout_desc.wMaxPacketSize;
- prm->ureq = kcalloc(uac2_opts->req_number, sizeof(struct uac2_req),
- GFP_KERNEL);
- if (!prm->ureq) {
- ret = -ENOMEM;
- goto err_free_descs;
- }
- prm->rbuf = kcalloc(uac2_opts->req_number, prm->max_psize, GFP_KERNEL);
- if (!prm->rbuf) {
- prm->max_psize = 0;
- ret = -ENOMEM;
- goto err_free_descs;
- }
-
- prm = &agdev->uac2.p_prm;
- prm->max_psize = hs_epin_desc.wMaxPacketSize;
- prm->ureq = kcalloc(uac2_opts->req_number, sizeof(struct uac2_req),
- GFP_KERNEL);
- if (!prm->ureq) {
- ret = -ENOMEM;
- goto err_free_descs;
- }
- prm->rbuf = kcalloc(uac2_opts->req_number, prm->max_psize, GFP_KERNEL);
- if (!prm->rbuf) {
- prm->max_psize = 0;
- ret = -ENOMEM;
- goto err_no_memory;
- }
+ agdev->gadget = gadget;
- ret = alsa_uac2_init(agdev);
+ agdev->params.p_chmask = uac2_opts->p_chmask;
+ agdev->params.p_srate = uac2_opts->p_srate;
+ agdev->params.p_ssize = uac2_opts->p_ssize;
+ agdev->params.c_chmask = uac2_opts->c_chmask;
+ agdev->params.c_srate = uac2_opts->c_srate;
+ agdev->params.c_ssize = uac2_opts->c_ssize;
+ agdev->params.req_number = uac2_opts->req_number;
+ ret = g_audio_setup(agdev, "UAC2 PCM", "UAC2_Gadget");
if (ret)
- goto err_no_memory;
+ goto err_free_descs;
return 0;
-err_no_memory:
- kfree(agdev->uac2.p_prm.ureq);
- kfree(agdev->uac2.c_prm.ureq);
- kfree(agdev->uac2.p_prm.rbuf);
- kfree(agdev->uac2.c_prm.rbuf);
err_free_descs:
usb_free_all_descriptors(fn);
+ agdev->gadget = NULL;
return ret;
}
@@ -1143,15 +606,10 @@ static int
afunc_set_alt(struct usb_function *fn, unsigned intf, unsigned alt)
{
struct usb_composite_dev *cdev = fn->config->cdev;
- struct audio_dev *agdev = func_to_agdev(fn);
- struct f_uac2_opts *opts = agdev_to_uac2_opts(agdev);
- struct snd_uac2_chip *uac2 = &agdev->uac2;
+ struct f_uac2 *uac2 = func_to_uac2(fn);
struct usb_gadget *gadget = cdev->gadget;
- struct device *dev = &uac2->pdev.dev;
- struct usb_request *req;
- struct usb_ep *ep;
- struct uac2_rtd_params *prm;
- int req_len, i;
+ struct device *dev = &gadget->dev;
+ int ret = 0;
/* No i/f has more than 2 alt settings */
if (alt > 1) {
@@ -1159,7 +617,7 @@ afunc_set_alt(struct usb_function *fn, unsigned intf, unsigned alt)
return -EINVAL;
}
- if (intf == agdev->ac_intf) {
+ if (intf == uac2->ac_intf) {
/* Control I/f has only 1 AltSetting - 0 */
if (alt) {
dev_err(dev, "%s:%d Error!\n", __func__, __LINE__);
@@ -1168,95 +626,42 @@ afunc_set_alt(struct usb_function *fn, unsigned intf, unsigned alt)
return 0;
}
- if (intf == agdev->as_out_intf) {
- ep = agdev->out_ep;
- prm = &uac2->c_prm;
- config_ep_by_speed(gadget, fn, ep);
- agdev->as_out_alt = alt;
- req_len = prm->max_psize;
- } else if (intf == agdev->as_in_intf) {
- unsigned int factor, rate;
- struct usb_endpoint_descriptor *ep_desc;
-
- ep = agdev->in_ep;
- prm = &uac2->p_prm;
- config_ep_by_speed(gadget, fn, ep);
- agdev->as_in_alt = alt;
-
- /* pre-calculate the playback endpoint's interval */
- if (gadget->speed == USB_SPEED_FULL) {
- ep_desc = &fs_epin_desc;
- factor = 1000;
- } else {
- ep_desc = &hs_epin_desc;
- factor = 8000;
- }
-
- /* pre-compute some values for iso_complete() */
- uac2->p_framesize = opts->p_ssize *
- num_channels(opts->p_chmask);
- rate = opts->p_srate * uac2->p_framesize;
- uac2->p_interval = factor / (1 << (ep_desc->bInterval - 1));
- uac2->p_pktsize = min_t(unsigned int, rate / uac2->p_interval,
- prm->max_psize);
+ if (intf == uac2->as_out_intf) {
+ uac2->as_out_alt = alt;
- if (uac2->p_pktsize < prm->max_psize)
- uac2->p_pktsize_residue = rate % uac2->p_interval;
+ if (alt)
+ ret = u_audio_start_capture(&uac2->g_audio);
else
- uac2->p_pktsize_residue = 0;
+ u_audio_stop_capture(&uac2->g_audio);
+ } else if (intf == uac2->as_in_intf) {
+ uac2->as_in_alt = alt;
- req_len = uac2->p_pktsize;
- uac2->p_residue = 0;
+ if (alt)
+ ret = u_audio_start_playback(&uac2->g_audio);
+ else
+ u_audio_stop_playback(&uac2->g_audio);
} else {
dev_err(dev, "%s:%d Error!\n", __func__, __LINE__);
return -EINVAL;
}
- if (alt == 0) {
- free_ep(prm, ep);
- return 0;
- }
-
- prm->ep_enabled = true;
- usb_ep_enable(ep);
-
- for (i = 0; i < opts->req_number; i++) {
- if (!prm->ureq[i].req) {
- req = usb_ep_alloc_request(ep, GFP_ATOMIC);
- if (req == NULL)
- return -ENOMEM;
-
- prm->ureq[i].req = req;
- prm->ureq[i].pp = prm;
-
- req->zero = 0;
- req->context = &prm->ureq[i];
- req->length = req_len;
- req->complete = agdev_iso_complete;
- req->buf = prm->rbuf + i * prm->max_psize;
- }
-
- if (usb_ep_queue(ep, prm->ureq[i].req, GFP_ATOMIC))
- dev_err(dev, "%s:%d Error!\n", __func__, __LINE__);
- }
-
- return 0;
+ return ret;
}
static int
afunc_get_alt(struct usb_function *fn, unsigned intf)
{
- struct audio_dev *agdev = func_to_agdev(fn);
- struct snd_uac2_chip *uac2 = &agdev->uac2;
-
- if (intf == agdev->ac_intf)
- return agdev->ac_alt;
- else if (intf == agdev->as_out_intf)
- return agdev->as_out_alt;
- else if (intf == agdev->as_in_intf)
- return agdev->as_in_alt;
+ struct f_uac2 *uac2 = func_to_uac2(fn);
+ struct g_audio *agdev = func_to_g_audio(fn);
+
+ if (intf == uac2->ac_intf)
+ return uac2->ac_alt;
+ else if (intf == uac2->as_out_intf)
+ return uac2->as_out_alt;
+ else if (intf == uac2->as_in_intf)
+ return uac2->as_in_alt;
else
- dev_err(&uac2->pdev.dev,
+ dev_err(&agdev->gadget->dev,
"%s:%d Invalid Interface %d!\n",
__func__, __LINE__, intf);
@@ -1266,22 +671,19 @@ afunc_get_alt(struct usb_function *fn, unsigned intf)
static void
afunc_disable(struct usb_function *fn)
{
- struct audio_dev *agdev = func_to_agdev(fn);
- struct snd_uac2_chip *uac2 = &agdev->uac2;
-
- free_ep(&uac2->p_prm, agdev->in_ep);
- agdev->as_in_alt = 0;
+ struct f_uac2 *uac2 = func_to_uac2(fn);
- free_ep(&uac2->c_prm, agdev->out_ep);
- agdev->as_out_alt = 0;
+ uac2->as_in_alt = 0;
+ uac2->as_out_alt = 0;
+ u_audio_stop_capture(&uac2->g_audio);
+ u_audio_stop_playback(&uac2->g_audio);
}
static int
in_rq_cur(struct usb_function *fn, const struct usb_ctrlrequest *cr)
{
struct usb_request *req = fn->config->cdev->req;
- struct audio_dev *agdev = func_to_agdev(fn);
- struct snd_uac2_chip *uac2 = &agdev->uac2;
+ struct g_audio *agdev = func_to_g_audio(fn);
struct f_uac2_opts *opts;
u16 w_length = le16_to_cpu(cr->wLength);
u16 w_index = le16_to_cpu(cr->wIndex);
@@ -1291,7 +693,7 @@ in_rq_cur(struct usb_function *fn, const struct usb_ctrlrequest *cr)
int value = -EOPNOTSUPP;
int p_srate, c_srate;
- opts = agdev_to_uac2_opts(agdev);
+ opts = g_audio_to_uac2_opts(agdev);
p_srate = opts->p_srate;
c_srate = opts->c_srate;
@@ -1310,7 +712,7 @@ in_rq_cur(struct usb_function *fn, const struct usb_ctrlrequest *cr)
*(u8 *)req->buf = 1;
value = min_t(unsigned, w_length, 1);
} else {
- dev_err(&uac2->pdev.dev,
+ dev_err(&agdev->gadget->dev,
"%s:%d control_selector=%d TODO!\n",
__func__, __LINE__, control_selector);
}
@@ -1322,8 +724,7 @@ static int
in_rq_range(struct usb_function *fn, const struct usb_ctrlrequest *cr)
{
struct usb_request *req = fn->config->cdev->req;
- struct audio_dev *agdev = func_to_agdev(fn);
- struct snd_uac2_chip *uac2 = &agdev->uac2;
+ struct g_audio *agdev = func_to_g_audio(fn);
struct f_uac2_opts *opts;
u16 w_length = le16_to_cpu(cr->wLength);
u16 w_index = le16_to_cpu(cr->wIndex);
@@ -1334,7 +735,7 @@ in_rq_range(struct usb_function *fn, const struct usb_ctrlrequest *cr)
int value = -EOPNOTSUPP;
int p_srate, c_srate;
- opts = agdev_to_uac2_opts(agdev);
+ opts = g_audio_to_uac2_opts(agdev);
p_srate = opts->p_srate;
c_srate = opts->c_srate;
@@ -1353,7 +754,7 @@ in_rq_range(struct usb_function *fn, const struct usb_ctrlrequest *cr)
value = min_t(unsigned, w_length, sizeof r);
memcpy(req->buf, &r, value);
} else {
- dev_err(&uac2->pdev.dev,
+ dev_err(&agdev->gadget->dev,
"%s:%d control_selector=%d TODO!\n",
__func__, __LINE__, control_selector);
}
@@ -1388,13 +789,13 @@ out_rq_cur(struct usb_function *fn, const struct usb_ctrlrequest *cr)
static int
setup_rq_inf(struct usb_function *fn, const struct usb_ctrlrequest *cr)
{
- struct audio_dev *agdev = func_to_agdev(fn);
- struct snd_uac2_chip *uac2 = &agdev->uac2;
+ struct f_uac2 *uac2 = func_to_uac2(fn);
+ struct g_audio *agdev = func_to_g_audio(fn);
u16 w_index = le16_to_cpu(cr->wIndex);
u8 intf = w_index & 0xff;
- if (intf != agdev->ac_intf) {
- dev_err(&uac2->pdev.dev,
+ if (intf != uac2->ac_intf) {
+ dev_err(&agdev->gadget->dev,
"%s:%d Error!\n", __func__, __LINE__);
return -EOPNOTSUPP;
}
@@ -1411,8 +812,7 @@ static int
afunc_setup(struct usb_function *fn, const struct usb_ctrlrequest *cr)
{
struct usb_composite_dev *cdev = fn->config->cdev;
- struct audio_dev *agdev = func_to_agdev(fn);
- struct snd_uac2_chip *uac2 = &agdev->uac2;
+ struct g_audio *agdev = func_to_g_audio(fn);
struct usb_request *req = cdev->req;
u16 w_length = le16_to_cpu(cr->wLength);
int value = -EOPNOTSUPP;
@@ -1424,14 +824,15 @@ afunc_setup(struct usb_function *fn, const struct usb_ctrlrequest *cr)
if ((cr->bRequestType & USB_RECIP_MASK) == USB_RECIP_INTERFACE)
value = setup_rq_inf(fn, cr);
else
- dev_err(&uac2->pdev.dev, "%s:%d Error!\n", __func__, __LINE__);
+ dev_err(&agdev->gadget->dev, "%s:%d Error!\n",
+ __func__, __LINE__);
if (value >= 0) {
req->length = value;
req->zero = value < w_length;
value = usb_ep_queue(cdev->gadget->ep0, req, GFP_ATOMIC);
if (value < 0) {
- dev_err(&uac2->pdev.dev,
+ dev_err(&agdev->gadget->dev,
"%s:%d Error!\n", __func__, __LINE__);
req->status = 0;
}
@@ -1557,10 +958,10 @@ static struct usb_function_instance *afunc_alloc_inst(void)
static void afunc_free(struct usb_function *f)
{
- struct audio_dev *agdev;
+ struct g_audio *agdev;
struct f_uac2_opts *opts;
- agdev = func_to_agdev(f);
+ agdev = func_to_g_audio(f);
opts = container_of(f->fi, struct f_uac2_opts, func_inst);
kfree(agdev);
mutex_lock(&opts->lock);
@@ -1570,27 +971,21 @@ static void afunc_free(struct usb_function *f)
static void afunc_unbind(struct usb_configuration *c, struct usb_function *f)
{
- struct audio_dev *agdev = func_to_agdev(f);
- struct uac2_rtd_params *prm;
+ struct g_audio *agdev = func_to_g_audio(f);
- alsa_uac2_exit(agdev);
-
- prm = &agdev->uac2.p_prm;
- kfree(prm->rbuf);
-
- prm = &agdev->uac2.c_prm;
- kfree(prm->rbuf);
- kfree(prm->ureq);
+ g_audio_cleanup(agdev);
usb_free_all_descriptors(f);
+
+ agdev->gadget = NULL;
}
static struct usb_function *afunc_alloc(struct usb_function_instance *fi)
{
- struct audio_dev *agdev;
+ struct f_uac2 *uac2;
struct f_uac2_opts *opts;
- agdev = kzalloc(sizeof(*agdev), GFP_KERNEL);
- if (agdev == NULL)
+ uac2 = kzalloc(sizeof(*uac2), GFP_KERNEL);
+ if (uac2 == NULL)
return ERR_PTR(-ENOMEM);
opts = container_of(fi, struct f_uac2_opts, func_inst);
@@ -1598,16 +993,16 @@ static struct usb_function *afunc_alloc(struct usb_function_instance *fi)
++opts->refcnt;
mutex_unlock(&opts->lock);
- agdev->func.name = "uac2_func";
- agdev->func.bind = afunc_bind;
- agdev->func.unbind = afunc_unbind;
- agdev->func.set_alt = afunc_set_alt;
- agdev->func.get_alt = afunc_get_alt;
- agdev->func.disable = afunc_disable;
- agdev->func.setup = afunc_setup;
- agdev->func.free_func = afunc_free;
+ uac2->g_audio.func.name = "uac2_func";
+ uac2->g_audio.func.bind = afunc_bind;
+ uac2->g_audio.func.unbind = afunc_unbind;
+ uac2->g_audio.func.set_alt = afunc_set_alt;
+ uac2->g_audio.func.get_alt = afunc_get_alt;
+ uac2->g_audio.func.disable = afunc_disable;
+ uac2->g_audio.func.setup = afunc_setup;
+ uac2->g_audio.func.free_func = afunc_free;
- return &agdev->func;
+ return &uac2->g_audio.func;
}
DECLARE_USB_FUNCTION_INIT(uac2, afunc_alloc_inst, afunc_alloc);
diff --git a/drivers/usb/gadget/function/storage_common.h b/drivers/usb/gadget/function/storage_common.h
index e69848994cb4..e0814a960132 100644
--- a/drivers/usb/gadget/function/storage_common.h
+++ b/drivers/usb/gadget/function/storage_common.h
@@ -133,9 +133,10 @@ static inline bool fsg_lun_is_open(struct fsg_lun *curlun)
#define FSG_MAX_LUNS 16
enum fsg_buffer_state {
+ BUF_STATE_SENDING = -2,
+ BUF_STATE_RECEIVING,
BUF_STATE_EMPTY = 0,
- BUF_STATE_FULL,
- BUF_STATE_BUSY
+ BUF_STATE_FULL
};
struct fsg_buffhd {
@@ -151,23 +152,14 @@ struct fsg_buffhd {
unsigned int bulk_out_intended_length;
struct usb_request *inreq;
- int inreq_busy;
struct usb_request *outreq;
- int outreq_busy;
};
enum fsg_state {
- /* This one isn't used anywhere */
- FSG_STATE_COMMAND_PHASE = -10,
- FSG_STATE_DATA_PHASE,
- FSG_STATE_STATUS_PHASE,
-
- FSG_STATE_IDLE = 0,
+ FSG_STATE_NORMAL,
FSG_STATE_ABORT_BULK_OUT,
- FSG_STATE_RESET,
- FSG_STATE_INTERFACE_CHANGE,
+ FSG_STATE_PROTOCOL_RESET,
FSG_STATE_CONFIG_CHANGE,
- FSG_STATE_DISCONNECT,
FSG_STATE_EXIT,
FSG_STATE_TERMINATED
};
diff --git a/drivers/usb/gadget/function/u_audio.c b/drivers/usb/gadget/function/u_audio.c
new file mode 100644
index 000000000000..5dd73b9e5172
--- /dev/null
+++ b/drivers/usb/gadget/function/u_audio.c
@@ -0,0 +1,662 @@
+/*
+ * u_audio.c -- interface to USB gadget "ALSA sound card" utilities
+ *
+ * Copyright (C) 2016
+ * Author: Ruslan Bilovol <ruslan.bilovol@gmail.com>
+ *
+ * Sound card implementation was cut-and-pasted with changes
+ * from f_uac2.c and has:
+ * Copyright (C) 2011
+ * Yadwinder Singh (yadi.brar01@gmail.com)
+ * Jaswinder Singh (jaswinder.singh@linaro.org)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/module.h>
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
+
+#include "u_audio.h"
+
+#define BUFF_SIZE_MAX (PAGE_SIZE * 16)
+#define PRD_SIZE_MAX PAGE_SIZE
+#define MIN_PERIODS 4
+
+struct uac_req {
+ struct uac_rtd_params *pp; /* parent param */
+ struct usb_request *req;
+};
+
+/* Runtime data params for one stream */
+struct uac_rtd_params {
+ struct snd_uac_chip *uac; /* parent chip */
+ bool ep_enabled; /* if the ep is enabled */
+ /* Size of the ring buffer */
+ size_t dma_bytes;
+ unsigned char *dma_area;
+
+ struct snd_pcm_substream *ss;
+
+ /* Ring buffer */
+ ssize_t hw_ptr;
+
+ void *rbuf;
+
+ size_t period_size;
+
+ unsigned max_psize; /* MaxPacketSize of endpoint */
+ struct uac_req *ureq;
+
+ spinlock_t lock;
+};
+
+struct snd_uac_chip {
+ struct g_audio *audio_dev;
+
+ struct uac_rtd_params p_prm;
+ struct uac_rtd_params c_prm;
+
+ struct snd_card *card;
+ struct snd_pcm *pcm;
+
+ /* timekeeping for the playback endpoint */
+ unsigned int p_interval;
+ unsigned int p_residue;
+
+ /* pre-calculated values for playback iso completion */
+ unsigned int p_pktsize;
+ unsigned int p_pktsize_residue;
+ unsigned int p_framesize;
+};
+
+static struct snd_pcm_hardware uac_pcm_hardware = {
+ .info = SNDRV_PCM_INFO_INTERLEAVED | SNDRV_PCM_INFO_BLOCK_TRANSFER
+ | SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_MMAP_VALID
+ | SNDRV_PCM_INFO_PAUSE | SNDRV_PCM_INFO_RESUME,
+ .rates = SNDRV_PCM_RATE_CONTINUOUS,
+ .periods_max = BUFF_SIZE_MAX / PRD_SIZE_MAX,
+ .buffer_bytes_max = BUFF_SIZE_MAX,
+ .period_bytes_max = PRD_SIZE_MAX,
+ .periods_min = MIN_PERIODS,
+};
+
+static void u_audio_iso_complete(struct usb_ep *ep, struct usb_request *req)
+{
+ unsigned pending;
+ unsigned long flags;
+ unsigned int hw_ptr;
+ bool update_alsa = false;
+ int status = req->status;
+ struct uac_req *ur = req->context;
+ struct snd_pcm_substream *substream;
+ struct uac_rtd_params *prm = ur->pp;
+ struct snd_uac_chip *uac = prm->uac;
+
+ /* i/f shutting down */
+ if (!prm->ep_enabled || req->status == -ESHUTDOWN)
+ return;
+
+ /*
+ * We can't really do much about bad xfers.
+ * Afterall, the ISOCH xfers could fail legitimately.
+ */
+ if (status)
+ pr_debug("%s: iso_complete status(%d) %d/%d\n",
+ __func__, status, req->actual, req->length);
+
+ substream = prm->ss;
+
+ /* Do nothing if ALSA isn't active */
+ if (!substream)
+ goto exit;
+
+ spin_lock_irqsave(&prm->lock, flags);
+
+ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
+ /*
+ * For each IN packet, take the quotient of the current data
+ * rate and the endpoint's interval as the base packet size.
+ * If there is a residue from this division, add it to the
+ * residue accumulator.
+ */
+ req->length = uac->p_pktsize;
+ uac->p_residue += uac->p_pktsize_residue;
+
+ /*
+ * Whenever there are more bytes in the accumulator than we
+ * need to add one more sample frame, increase this packet's
+ * size and decrease the accumulator.
+ */
+ if (uac->p_residue / uac->p_interval >= uac->p_framesize) {
+ req->length += uac->p_framesize;
+ uac->p_residue -= uac->p_framesize *
+ uac->p_interval;
+ }
+
+ req->actual = req->length;
+ }
+
+ pending = prm->hw_ptr % prm->period_size;
+ pending += req->actual;
+ if (pending >= prm->period_size)
+ update_alsa = true;
+
+ hw_ptr = prm->hw_ptr;
+ prm->hw_ptr = (prm->hw_ptr + req->actual) % prm->dma_bytes;
+
+ spin_unlock_irqrestore(&prm->lock, flags);
+
+ /* Pack USB load in ALSA ring buffer */
+ pending = prm->dma_bytes - hw_ptr;
+
+ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
+ if (unlikely(pending < req->actual)) {
+ memcpy(req->buf, prm->dma_area + hw_ptr, pending);
+ memcpy(req->buf + pending, prm->dma_area,
+ req->actual - pending);
+ } else {
+ memcpy(req->buf, prm->dma_area + hw_ptr, req->actual);
+ }
+ } else {
+ if (unlikely(pending < req->actual)) {
+ memcpy(prm->dma_area + hw_ptr, req->buf, pending);
+ memcpy(prm->dma_area, req->buf + pending,
+ req->actual - pending);
+ } else {
+ memcpy(prm->dma_area + hw_ptr, req->buf, req->actual);
+ }
+ }
+
+exit:
+ if (usb_ep_queue(ep, req, GFP_ATOMIC))
+ dev_err(uac->card->dev, "%d Error!\n", __LINE__);
+
+ if (update_alsa)
+ snd_pcm_period_elapsed(substream);
+}
+
+static int uac_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
+{
+ struct snd_uac_chip *uac = snd_pcm_substream_chip(substream);
+ struct uac_rtd_params *prm;
+ struct g_audio *audio_dev;
+ struct uac_params *params;
+ unsigned long flags;
+ int err = 0;
+
+ audio_dev = uac->audio_dev;
+ params = &audio_dev->params;
+
+ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
+ prm = &uac->p_prm;
+ else
+ prm = &uac->c_prm;
+
+ spin_lock_irqsave(&prm->lock, flags);
+
+ /* Reset */
+ prm->hw_ptr = 0;
+
+ switch (cmd) {
+ case SNDRV_PCM_TRIGGER_START:
+ case SNDRV_PCM_TRIGGER_RESUME:
+ prm->ss = substream;
+ break;
+ case SNDRV_PCM_TRIGGER_STOP:
+ case SNDRV_PCM_TRIGGER_SUSPEND:
+ prm->ss = NULL;
+ break;
+ default:
+ err = -EINVAL;
+ }
+
+ spin_unlock_irqrestore(&prm->lock, flags);
+
+ /* Clear buffer after Play stops */
+ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK && !prm->ss)
+ memset(prm->rbuf, 0, prm->max_psize * params->req_number);
+
+ return err;
+}
+
+static snd_pcm_uframes_t uac_pcm_pointer(struct snd_pcm_substream *substream)
+{
+ struct snd_uac_chip *uac = snd_pcm_substream_chip(substream);
+ struct uac_rtd_params *prm;
+
+ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
+ prm = &uac->p_prm;
+ else
+ prm = &uac->c_prm;
+
+ return bytes_to_frames(substream->runtime, prm->hw_ptr);
+}
+
+static int uac_pcm_hw_params(struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params *hw_params)
+{
+ struct snd_uac_chip *uac = snd_pcm_substream_chip(substream);
+ struct uac_rtd_params *prm;
+ int err;
+
+ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
+ prm = &uac->p_prm;
+ else
+ prm = &uac->c_prm;
+
+ err = snd_pcm_lib_malloc_pages(substream,
+ params_buffer_bytes(hw_params));
+ if (err >= 0) {
+ prm->dma_bytes = substream->runtime->dma_bytes;
+ prm->dma_area = substream->runtime->dma_area;
+ prm->period_size = params_period_bytes(hw_params);
+ }
+
+ return err;
+}
+
+static int uac_pcm_hw_free(struct snd_pcm_substream *substream)
+{
+ struct snd_uac_chip *uac = snd_pcm_substream_chip(substream);
+ struct uac_rtd_params *prm;
+
+ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
+ prm = &uac->p_prm;
+ else
+ prm = &uac->c_prm;
+
+ prm->dma_area = NULL;
+ prm->dma_bytes = 0;
+ prm->period_size = 0;
+
+ return snd_pcm_lib_free_pages(substream);
+}
+
+static int uac_pcm_open(struct snd_pcm_substream *substream)
+{
+ struct snd_uac_chip *uac = snd_pcm_substream_chip(substream);
+ struct snd_pcm_runtime *runtime = substream->runtime;
+ struct g_audio *audio_dev;
+ struct uac_params *params;
+ int p_ssize, c_ssize;
+ int p_srate, c_srate;
+ int p_chmask, c_chmask;
+
+ audio_dev = uac->audio_dev;
+ params = &audio_dev->params;
+ p_ssize = params->p_ssize;
+ c_ssize = params->c_ssize;
+ p_srate = params->p_srate;
+ c_srate = params->c_srate;
+ p_chmask = params->p_chmask;
+ c_chmask = params->c_chmask;
+ uac->p_residue = 0;
+
+ runtime->hw = uac_pcm_hardware;
+
+ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
+ spin_lock_init(&uac->p_prm.lock);
+ runtime->hw.rate_min = p_srate;
+ switch (p_ssize) {
+ case 3:
+ runtime->hw.formats = SNDRV_PCM_FMTBIT_S24_3LE;
+ break;
+ case 4:
+ runtime->hw.formats = SNDRV_PCM_FMTBIT_S32_LE;
+ break;
+ default:
+ runtime->hw.formats = SNDRV_PCM_FMTBIT_S16_LE;
+ break;
+ }
+ runtime->hw.channels_min = num_channels(p_chmask);
+ runtime->hw.period_bytes_min = 2 * uac->p_prm.max_psize
+ / runtime->hw.periods_min;
+ } else {
+ spin_lock_init(&uac->c_prm.lock);
+ runtime->hw.rate_min = c_srate;
+ switch (c_ssize) {
+ case 3:
+ runtime->hw.formats = SNDRV_PCM_FMTBIT_S24_3LE;
+ break;
+ case 4:
+ runtime->hw.formats = SNDRV_PCM_FMTBIT_S32_LE;
+ break;
+ default:
+ runtime->hw.formats = SNDRV_PCM_FMTBIT_S16_LE;
+ break;
+ }
+ runtime->hw.channels_min = num_channels(c_chmask);
+ runtime->hw.period_bytes_min = 2 * uac->c_prm.max_psize
+ / runtime->hw.periods_min;
+ }
+
+ runtime->hw.rate_max = runtime->hw.rate_min;
+ runtime->hw.channels_max = runtime->hw.channels_min;
+
+ snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIODS);
+
+ return 0;
+}
+
+/* ALSA cries without these function pointers */
+static int uac_pcm_null(struct snd_pcm_substream *substream)
+{
+ return 0;
+}
+
+static struct snd_pcm_ops uac_pcm_ops = {
+ .open = uac_pcm_open,
+ .close = uac_pcm_null,
+ .ioctl = snd_pcm_lib_ioctl,
+ .hw_params = uac_pcm_hw_params,
+ .hw_free = uac_pcm_hw_free,
+ .trigger = uac_pcm_trigger,
+ .pointer = uac_pcm_pointer,
+ .prepare = uac_pcm_null,
+};
+
+static inline void free_ep(struct uac_rtd_params *prm, struct usb_ep *ep)
+{
+ struct snd_uac_chip *uac = prm->uac;
+ struct g_audio *audio_dev;
+ struct uac_params *params;
+ int i;
+
+ if (!prm->ep_enabled)
+ return;
+
+ prm->ep_enabled = false;
+
+ audio_dev = uac->audio_dev;
+ params = &audio_dev->params;
+
+ for (i = 0; i < params->req_number; i++) {
+ if (prm->ureq[i].req) {
+ usb_ep_dequeue(ep, prm->ureq[i].req);
+ usb_ep_free_request(ep, prm->ureq[i].req);
+ prm->ureq[i].req = NULL;
+ }
+ }
+
+ if (usb_ep_disable(ep))
+ dev_err(uac->card->dev, "%s:%d Error!\n", __func__, __LINE__);
+}
+
+
+int u_audio_start_capture(struct g_audio *audio_dev)
+{
+ struct snd_uac_chip *uac = audio_dev->uac;
+ struct usb_gadget *gadget = audio_dev->gadget;
+ struct device *dev = &gadget->dev;
+ struct usb_request *req;
+ struct usb_ep *ep;
+ struct uac_rtd_params *prm;
+ struct uac_params *params = &audio_dev->params;
+ int req_len, i;
+
+ ep = audio_dev->out_ep;
+ prm = &uac->c_prm;
+ config_ep_by_speed(gadget, &audio_dev->func, ep);
+ req_len = prm->max_psize;
+
+ prm->ep_enabled = true;
+ usb_ep_enable(ep);
+
+ for (i = 0; i < params->req_number; i++) {
+ if (!prm->ureq[i].req) {
+ req = usb_ep_alloc_request(ep, GFP_ATOMIC);
+ if (req == NULL)
+ return -ENOMEM;
+
+ prm->ureq[i].req = req;
+ prm->ureq[i].pp = prm;
+
+ req->zero = 0;
+ req->context = &prm->ureq[i];
+ req->length = req_len;
+ req->complete = u_audio_iso_complete;
+ req->buf = prm->rbuf + i * prm->max_psize;
+ }
+
+ if (usb_ep_queue(ep, prm->ureq[i].req, GFP_ATOMIC))
+ dev_err(dev, "%s:%d Error!\n", __func__, __LINE__);
+ }
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(u_audio_start_capture);
+
+void u_audio_stop_capture(struct g_audio *audio_dev)
+{
+ struct snd_uac_chip *uac = audio_dev->uac;
+
+ free_ep(&uac->c_prm, audio_dev->out_ep);
+}
+EXPORT_SYMBOL_GPL(u_audio_stop_capture);
+
+int u_audio_start_playback(struct g_audio *audio_dev)
+{
+ struct snd_uac_chip *uac = audio_dev->uac;
+ struct usb_gadget *gadget = audio_dev->gadget;
+ struct device *dev = &gadget->dev;
+ struct usb_request *req;
+ struct usb_ep *ep;
+ struct uac_rtd_params *prm;
+ struct uac_params *params = &audio_dev->params;
+ unsigned int factor, rate;
+ const struct usb_endpoint_descriptor *ep_desc;
+ int req_len, i;
+
+ ep = audio_dev->in_ep;
+ prm = &uac->p_prm;
+ config_ep_by_speed(gadget, &audio_dev->func, ep);
+
+ ep_desc = ep->desc;
+
+ /* pre-calculate the playback endpoint's interval */
+ if (gadget->speed == USB_SPEED_FULL)
+ factor = 1000;
+ else
+ factor = 8000;
+
+ /* pre-compute some values for iso_complete() */
+ uac->p_framesize = params->p_ssize *
+ num_channels(params->p_chmask);
+ rate = params->p_srate * uac->p_framesize;
+ uac->p_interval = factor / (1 << (ep_desc->bInterval - 1));
+ uac->p_pktsize = min_t(unsigned int, rate / uac->p_interval,
+ prm->max_psize);
+
+ if (uac->p_pktsize < prm->max_psize)
+ uac->p_pktsize_residue = rate % uac->p_interval;
+ else
+ uac->p_pktsize_residue = 0;
+
+ req_len = uac->p_pktsize;
+ uac->p_residue = 0;
+
+ prm->ep_enabled = true;
+ usb_ep_enable(ep);
+
+ for (i = 0; i < params->req_number; i++) {
+ if (!prm->ureq[i].req) {
+ req = usb_ep_alloc_request(ep, GFP_ATOMIC);
+ if (req == NULL)
+ return -ENOMEM;
+
+ prm->ureq[i].req = req;
+ prm->ureq[i].pp = prm;
+
+ req->zero = 0;
+ req->context = &prm->ureq[i];
+ req->length = req_len;
+ req->complete = u_audio_iso_complete;
+ req->buf = prm->rbuf + i * prm->max_psize;
+ }
+
+ if (usb_ep_queue(ep, prm->ureq[i].req, GFP_ATOMIC))
+ dev_err(dev, "%s:%d Error!\n", __func__, __LINE__);
+ }
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(u_audio_start_playback);
+
+void u_audio_stop_playback(struct g_audio *audio_dev)
+{
+ struct snd_uac_chip *uac = audio_dev->uac;
+
+ free_ep(&uac->p_prm, audio_dev->in_ep);
+}
+EXPORT_SYMBOL_GPL(u_audio_stop_playback);
+
+int g_audio_setup(struct g_audio *g_audio, const char *pcm_name,
+ const char *card_name)
+{
+ struct snd_uac_chip *uac;
+ struct snd_card *card;
+ struct snd_pcm *pcm;
+ struct uac_params *params;
+ int p_chmask, c_chmask;
+ int err;
+
+ if (!g_audio)
+ return -EINVAL;
+
+ uac = kzalloc(sizeof(*uac), GFP_KERNEL);
+ if (!uac)
+ return -ENOMEM;
+ g_audio->uac = uac;
+ uac->audio_dev = g_audio;
+
+ params = &g_audio->params;
+ p_chmask = params->p_chmask;
+ c_chmask = params->c_chmask;
+
+ if (c_chmask) {
+ struct uac_rtd_params *prm = &uac->c_prm;
+
+ uac->c_prm.uac = uac;
+ prm->max_psize = g_audio->out_ep_maxpsize;
+
+ prm->ureq = kcalloc(params->req_number, sizeof(struct uac_req),
+ GFP_KERNEL);
+ if (!prm->ureq) {
+ err = -ENOMEM;
+ goto fail;
+ }
+
+ prm->rbuf = kcalloc(params->req_number, prm->max_psize,
+ GFP_KERNEL);
+ if (!prm->rbuf) {
+ prm->max_psize = 0;
+ err = -ENOMEM;
+ goto fail;
+ }
+ }
+
+ if (p_chmask) {
+ struct uac_rtd_params *prm = &uac->p_prm;
+
+ uac->p_prm.uac = uac;
+ prm->max_psize = g_audio->in_ep_maxpsize;
+
+ prm->ureq = kcalloc(params->req_number, sizeof(struct uac_req),
+ GFP_KERNEL);
+ if (!prm->ureq) {
+ err = -ENOMEM;
+ goto fail;
+ }
+
+ prm->rbuf = kcalloc(params->req_number, prm->max_psize,
+ GFP_KERNEL);
+ if (!prm->rbuf) {
+ prm->max_psize = 0;
+ err = -ENOMEM;
+ goto fail;
+ }
+ }
+
+ /* Choose any slot, with no id */
+ err = snd_card_new(&g_audio->gadget->dev,
+ -1, NULL, THIS_MODULE, 0, &card);
+ if (err < 0)
+ goto fail;
+
+ uac->card = card;
+
+ /*
+ * Create first PCM device
+ * Create a substream only for non-zero channel streams
+ */
+ err = snd_pcm_new(uac->card, pcm_name, 0,
+ p_chmask ? 1 : 0, c_chmask ? 1 : 0, &pcm);
+ if (err < 0)
+ goto snd_fail;
+
+ strcpy(pcm->name, pcm_name);
+ pcm->private_data = uac;
+ uac->pcm = pcm;
+
+ snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &uac_pcm_ops);
+ snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &uac_pcm_ops);
+
+ strcpy(card->driver, card_name);
+ strcpy(card->shortname, card_name);
+ sprintf(card->longname, "%s %i", card_name, card->dev->id);
+
+ snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_CONTINUOUS,
+ snd_dma_continuous_data(GFP_KERNEL), 0, BUFF_SIZE_MAX);
+
+ err = snd_card_register(card);
+
+ if (!err)
+ return 0;
+
+snd_fail:
+ snd_card_free(card);
+fail:
+ kfree(uac->p_prm.ureq);
+ kfree(uac->c_prm.ureq);
+ kfree(uac->p_prm.rbuf);
+ kfree(uac->c_prm.rbuf);
+ kfree(uac);
+
+ return err;
+}
+EXPORT_SYMBOL_GPL(g_audio_setup);
+
+void g_audio_cleanup(struct g_audio *g_audio)
+{
+ struct snd_uac_chip *uac;
+ struct snd_card *card;
+
+ if (!g_audio || !g_audio->uac)
+ return;
+
+ uac = g_audio->uac;
+ card = uac->card;
+ if (card)
+ snd_card_free(card);
+
+ kfree(uac->p_prm.ureq);
+ kfree(uac->c_prm.ureq);
+ kfree(uac->p_prm.rbuf);
+ kfree(uac->c_prm.rbuf);
+ kfree(uac);
+}
+EXPORT_SYMBOL_GPL(g_audio_cleanup);
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("USB gadget \"ALSA sound card\" utilities");
+MODULE_AUTHOR("Ruslan Bilovol");
diff --git a/drivers/usb/gadget/function/u_audio.h b/drivers/usb/gadget/function/u_audio.h
new file mode 100644
index 000000000000..07e13784cbb8
--- /dev/null
+++ b/drivers/usb/gadget/function/u_audio.h
@@ -0,0 +1,95 @@
+/*
+ * u_audio.h -- interface to USB gadget "ALSA sound card" utilities
+ *
+ * Copyright (C) 2016
+ * Author: Ruslan Bilovol <ruslan.bilovol@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#ifndef __U_AUDIO_H
+#define __U_AUDIO_H
+
+#include <linux/usb/composite.h>
+
+struct uac_params {
+ /* playback */
+ int p_chmask; /* channel mask */
+ int p_srate; /* rate in Hz */
+ int p_ssize; /* sample size */
+
+ /* capture */
+ int c_chmask; /* channel mask */
+ int c_srate; /* rate in Hz */
+ int c_ssize; /* sample size */
+
+ int req_number; /* number of preallocated requests */
+};
+
+struct g_audio {
+ struct usb_function func;
+ struct usb_gadget *gadget;
+
+ struct usb_ep *in_ep;
+ struct usb_ep *out_ep;
+
+ /* Max packet size for all in_ep possible speeds */
+ unsigned int in_ep_maxpsize;
+ /* Max packet size for all out_ep possible speeds */
+ unsigned int out_ep_maxpsize;
+
+ /* The ALSA Sound Card it represents on the USB-Client side */
+ struct snd_uac_chip *uac;
+
+ struct uac_params params;
+};
+
+static inline struct g_audio *func_to_g_audio(struct usb_function *f)
+{
+ return container_of(f, struct g_audio, func);
+}
+
+static inline uint num_channels(uint chanmask)
+{
+ uint num = 0;
+
+ while (chanmask) {
+ num += (chanmask & 1);
+ chanmask >>= 1;
+ }
+
+ return num;
+}
+
+/*
+ * g_audio_setup - initialize one virtual ALSA sound card
+ * @g_audio: struct with filled params, in_ep_maxpsize, out_ep_maxpsize
+ * @pcm_name: the id string for a PCM instance of this sound card
+ * @card_name: name of this soundcard
+ *
+ * This sets up the single virtual ALSA sound card that may be exported by a
+ * gadget driver using this framework.
+ *
+ * Context: may sleep
+ *
+ * Returns zero on success, or a negative error on failure.
+ */
+int g_audio_setup(struct g_audio *g_audio, const char *pcm_name,
+ const char *card_name);
+void g_audio_cleanup(struct g_audio *g_audio);
+
+int u_audio_start_capture(struct g_audio *g_audio);
+void u_audio_stop_capture(struct g_audio *g_audio);
+int u_audio_start_playback(struct g_audio *g_audio);
+void u_audio_stop_playback(struct g_audio *g_audio);
+
+#endif /* __U_AUDIO_H */
diff --git a/drivers/usb/gadget/function/u_fs.h b/drivers/usb/gadget/function/u_fs.h
index 4378cc2fcac3..540f1c48c1a8 100644
--- a/drivers/usb/gadget/function/u_fs.h
+++ b/drivers/usb/gadget/function/u_fs.h
@@ -216,6 +216,9 @@ struct ffs_data {
#define FFS_FL_CALL_CLOSED_CALLBACK 0
#define FFS_FL_BOUND 1
+ /* For waking up blocked threads when function is enabled. */
+ wait_queue_head_t wait;
+
/* Active function */
struct ffs_function *func;
diff --git a/drivers/usb/gadget/function/u_uac1.h b/drivers/usb/gadget/function/u_uac1.h
index 5c2ac8e8456d..6f188fd8633f 100644
--- a/drivers/usb/gadget/function/u_uac1.h
+++ b/drivers/usb/gadget/function/u_uac1.h
@@ -1,82 +1,41 @@
/*
- * u_uac1.h -- interface to USB gadget "ALSA AUDIO" utilities
+ * u_uac1.h - Utility definitions for UAC1 function
*
- * Copyright (C) 2008 Bryan Wu <cooloney@kernel.org>
- * Copyright (C) 2008 Analog Devices, Inc
+ * Copyright (C) 2016 Ruslan Bilovol <ruslan.bilovol@gmail.com>
*
- * Enter bugs at http://blackfin.uclinux.org/
- *
- * Licensed under the GPL-2 or later.
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
*/
-#ifndef __U_AUDIO_H
-#define __U_AUDIO_H
+#ifndef __U_UAC1_H
+#define __U_UAC1_H
-#include <linux/device.h>
-#include <linux/err.h>
-#include <linux/usb/audio.h>
#include <linux/usb/composite.h>
-#include <sound/core.h>
-#include <sound/pcm.h>
-#include <sound/pcm_params.h>
-
-#define FILE_PCM_PLAYBACK "/dev/snd/pcmC0D0p"
-#define FILE_PCM_CAPTURE "/dev/snd/pcmC0D0c"
-#define FILE_CONTROL "/dev/snd/controlC0"
-
#define UAC1_OUT_EP_MAX_PACKET_SIZE 200
-#define UAC1_REQ_COUNT 256
-#define UAC1_AUDIO_BUF_SIZE 48000
-
-/*
- * This represents the USB side of an audio card device, managed by a USB
- * function which provides control and stream interfaces.
- */
-
-struct gaudio_snd_dev {
- struct gaudio *card;
- struct file *filp;
- struct snd_pcm_substream *substream;
- int access;
- int format;
- int channels;
- int rate;
-};
-
-struct gaudio {
- struct usb_function func;
- struct usb_gadget *gadget;
+#define UAC1_DEF_CCHMASK 0x3
+#define UAC1_DEF_CSRATE 48000
+#define UAC1_DEF_CSSIZE 2
+#define UAC1_DEF_PCHMASK 0x3
+#define UAC1_DEF_PSRATE 48000
+#define UAC1_DEF_PSSIZE 2
+#define UAC1_DEF_REQ_NUM 2
- /* ALSA sound device interfaces */
- struct gaudio_snd_dev control;
- struct gaudio_snd_dev playback;
- struct gaudio_snd_dev capture;
-
- /* TODO */
-};
struct f_uac1_opts {
struct usb_function_instance func_inst;
- int req_buf_size;
- int req_count;
- int audio_buf_size;
- char *fn_play;
- char *fn_cap;
- char *fn_cntl;
+ int c_chmask;
+ int c_srate;
+ int c_ssize;
+ int p_chmask;
+ int p_srate;
+ int p_ssize;
+ int req_number;
unsigned bound:1;
- unsigned fn_play_alloc:1;
- unsigned fn_cap_alloc:1;
- unsigned fn_cntl_alloc:1;
+
struct mutex lock;
int refcnt;
};
-int gaudio_setup(struct gaudio *card);
-void gaudio_cleanup(struct gaudio *the_card);
-
-size_t u_audio_playback(struct gaudio *card, void *buf, size_t count);
-int u_audio_get_playback_channels(struct gaudio *card);
-int u_audio_get_playback_rate(struct gaudio *card);
-
-#endif /* __U_AUDIO_H */
+#endif /* __U_UAC1_H */
diff --git a/drivers/usb/gadget/function/u_uac1.c b/drivers/usb/gadget/function/u_uac1_legacy.c
index c78c84138a28..8aa76b4dc117 100644
--- a/drivers/usb/gadget/function/u_uac1.c
+++ b/drivers/usb/gadget/function/u_uac1_legacy.c
@@ -18,7 +18,7 @@
#include <linux/random.h>
#include <linux/syscalls.h>
-#include "u_uac1.h"
+#include "u_uac1_legacy.h"
/*
* This component encapsulates the ALSA devices for USB audio gadget
@@ -205,10 +205,11 @@ static int gaudio_open_snd_dev(struct gaudio *card)
{
struct snd_pcm_file *pcm_file;
struct gaudio_snd_dev *snd;
- struct f_uac1_opts *opts;
+ struct f_uac1_legacy_opts *opts;
char *fn_play, *fn_cap, *fn_cntl;
- opts = container_of(card->func.fi, struct f_uac1_opts, func_inst);
+ opts = container_of(card->func.fi, struct f_uac1_legacy_opts,
+ func_inst);
fn_play = opts->fn_play;
fn_cap = opts->fn_cap;
fn_cntl = opts->fn_cntl;
diff --git a/drivers/usb/gadget/function/u_uac1_legacy.h b/drivers/usb/gadget/function/u_uac1_legacy.h
new file mode 100644
index 000000000000..d715b1af56a4
--- /dev/null
+++ b/drivers/usb/gadget/function/u_uac1_legacy.h
@@ -0,0 +1,82 @@
+/*
+ * u_uac1.h -- interface to USB gadget "ALSA AUDIO" utilities
+ *
+ * Copyright (C) 2008 Bryan Wu <cooloney@kernel.org>
+ * Copyright (C) 2008 Analog Devices, Inc
+ *
+ * Enter bugs at http://blackfin.uclinux.org/
+ *
+ * Licensed under the GPL-2 or later.
+ */
+
+#ifndef __U_UAC1_LEGACY_H
+#define __U_UAC1_LEGACY_H
+
+#include <linux/device.h>
+#include <linux/err.h>
+#include <linux/usb/audio.h>
+#include <linux/usb/composite.h>
+
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
+
+#define FILE_PCM_PLAYBACK "/dev/snd/pcmC0D0p"
+#define FILE_PCM_CAPTURE "/dev/snd/pcmC0D0c"
+#define FILE_CONTROL "/dev/snd/controlC0"
+
+#define UAC1_OUT_EP_MAX_PACKET_SIZE 200
+#define UAC1_REQ_COUNT 256
+#define UAC1_AUDIO_BUF_SIZE 48000
+
+/*
+ * This represents the USB side of an audio card device, managed by a USB
+ * function which provides control and stream interfaces.
+ */
+
+struct gaudio_snd_dev {
+ struct gaudio *card;
+ struct file *filp;
+ struct snd_pcm_substream *substream;
+ int access;
+ int format;
+ int channels;
+ int rate;
+};
+
+struct gaudio {
+ struct usb_function func;
+ struct usb_gadget *gadget;
+
+ /* ALSA sound device interfaces */
+ struct gaudio_snd_dev control;
+ struct gaudio_snd_dev playback;
+ struct gaudio_snd_dev capture;
+
+ /* TODO */
+};
+
+struct f_uac1_legacy_opts {
+ struct usb_function_instance func_inst;
+ int req_buf_size;
+ int req_count;
+ int audio_buf_size;
+ char *fn_play;
+ char *fn_cap;
+ char *fn_cntl;
+ unsigned bound:1;
+ unsigned fn_play_alloc:1;
+ unsigned fn_cap_alloc:1;
+ unsigned fn_cntl_alloc:1;
+ struct mutex lock;
+ int refcnt;
+};
+
+int gaudio_setup(struct gaudio *card);
+void gaudio_cleanup(struct gaudio *the_card);
+
+size_t u_audio_playback(struct gaudio *card, void *buf, size_t count);
+int u_audio_get_playback_channels(struct gaudio *card);
+int u_audio_get_playback_rate(struct gaudio *card);
+
+#endif /* __U_UAC1_LEGACY_H */
diff --git a/drivers/usb/gadget/legacy/Kconfig b/drivers/usb/gadget/legacy/Kconfig
index 0b36878eb5fd..a12fb459dbd9 100644
--- a/drivers/usb/gadget/legacy/Kconfig
+++ b/drivers/usb/gadget/legacy/Kconfig
@@ -54,8 +54,10 @@ config USB_AUDIO
depends on SND
select USB_LIBCOMPOSITE
select SND_PCM
- select USB_F_UAC1 if GADGET_UAC1
+ select USB_F_UAC1 if (GADGET_UAC1 && !GADGET_UAC1_LEGACY)
+ select USB_F_UAC1_LEGACY if (GADGET_UAC1 && GADGET_UAC1_LEGACY)
select USB_F_UAC2 if !GADGET_UAC1
+ select USB_U_AUDIO if (USB_F_UAC2 || USB_F_UAC1)
help
This Gadget Audio driver is compatible with USB Audio Class
specification 2.0. It implements 1 AudioControl interface,
@@ -73,10 +75,17 @@ config USB_AUDIO
dynamically linked module called "g_audio".
config GADGET_UAC1
- bool "UAC 1.0 (Legacy)"
+ bool "UAC 1.0"
depends on USB_AUDIO
help
- If you instead want older UAC Spec-1.0 driver that also has audio
+ If you instead want older USB Audio Class specification 1.0 support
+ with similar driver capabilities.
+
+config GADGET_UAC1_LEGACY
+ bool "UAC 1.0 (Legacy)"
+ depends on GADGET_UAC1
+ help
+ If you instead want legacy UAC Spec-1.0 driver that also has audio
paths hardwired to the Audio codec chip on-board and doesn't work
without one.
diff --git a/drivers/usb/gadget/legacy/audio.c b/drivers/usb/gadget/legacy/audio.c
index 8a39f42a4d56..1f5cdbe162df 100644
--- a/drivers/usb/gadget/legacy/audio.c
+++ b/drivers/usb/gadget/legacy/audio.c
@@ -53,8 +53,41 @@ static int c_ssize = UAC2_DEF_CSSIZE;
module_param(c_ssize, uint, S_IRUGO);
MODULE_PARM_DESC(c_ssize, "Capture Sample Size(bytes)");
#else
+#ifndef CONFIG_GADGET_UAC1_LEGACY
#include "u_uac1.h"
+/* Playback(USB-IN) Default Stereo - Fl/Fr */
+static int p_chmask = UAC1_DEF_PCHMASK;
+module_param(p_chmask, uint, S_IRUGO);
+MODULE_PARM_DESC(p_chmask, "Playback Channel Mask");
+
+/* Playback Default 48 KHz */
+static int p_srate = UAC1_DEF_PSRATE;
+module_param(p_srate, uint, S_IRUGO);
+MODULE_PARM_DESC(p_srate, "Playback Sampling Rate");
+
+/* Playback Default 16bits/sample */
+static int p_ssize = UAC1_DEF_PSSIZE;
+module_param(p_ssize, uint, S_IRUGO);
+MODULE_PARM_DESC(p_ssize, "Playback Sample Size(bytes)");
+
+/* Capture(USB-OUT) Default Stereo - Fl/Fr */
+static int c_chmask = UAC1_DEF_CCHMASK;
+module_param(c_chmask, uint, S_IRUGO);
+MODULE_PARM_DESC(c_chmask, "Capture Channel Mask");
+
+/* Capture Default 48 KHz */
+static int c_srate = UAC1_DEF_CSRATE;
+module_param(c_srate, uint, S_IRUGO);
+MODULE_PARM_DESC(c_srate, "Capture Sampling Rate");
+
+/* Capture Default 16bits/sample */
+static int c_ssize = UAC1_DEF_CSSIZE;
+module_param(c_ssize, uint, S_IRUGO);
+MODULE_PARM_DESC(c_ssize, "Capture Sample Size(bytes)");
+#else /* CONFIG_GADGET_UAC1_LEGACY */
+#include "u_uac1_legacy.h"
+
static char *fn_play = FILE_PCM_PLAYBACK;
module_param(fn_play, charp, S_IRUGO);
MODULE_PARM_DESC(fn_play, "Playback PCM device file name");
@@ -78,6 +111,7 @@ MODULE_PARM_DESC(req_count, "ISO OUT endpoint request count");
static int audio_buf_size = UAC1_AUDIO_BUF_SIZE;
module_param(audio_buf_size, int, S_IRUGO);
MODULE_PARM_DESC(audio_buf_size, "Audio buffer size");
+#endif /* CONFIG_GADGET_UAC1_LEGACY */
#endif
/* string IDs are assigned dynamically */
@@ -125,7 +159,7 @@ static struct usb_device_descriptor device_desc = {
/* .bcdUSB = DYNAMIC */
-#ifdef CONFIG_GADGET_UAC1
+#ifdef CONFIG_GADGET_UAC1_LEGACY
.bDeviceClass = USB_CLASS_PER_INTERFACE,
.bDeviceSubClass = 0,
.bDeviceProtocol = 0,
@@ -207,7 +241,11 @@ static int audio_bind(struct usb_composite_dev *cdev)
#ifndef CONFIG_GADGET_UAC1
struct f_uac2_opts *uac2_opts;
#else
+#ifndef CONFIG_GADGET_UAC1_LEGACY
struct f_uac1_opts *uac1_opts;
+#else
+ struct f_uac1_legacy_opts *uac1_opts;
+#endif
#endif
int status;
@@ -216,7 +254,11 @@ static int audio_bind(struct usb_composite_dev *cdev)
if (IS_ERR(fi_uac2))
return PTR_ERR(fi_uac2);
#else
+#ifndef CONFIG_GADGET_UAC1_LEGACY
fi_uac1 = usb_get_function_instance("uac1");
+#else
+ fi_uac1 = usb_get_function_instance("uac1_legacy");
+#endif
if (IS_ERR(fi_uac1))
return PTR_ERR(fi_uac1);
#endif
@@ -231,13 +273,24 @@ static int audio_bind(struct usb_composite_dev *cdev)
uac2_opts->c_ssize = c_ssize;
uac2_opts->req_number = UAC2_DEF_REQ_NUM;
#else
+#ifndef CONFIG_GADGET_UAC1_LEGACY
uac1_opts = container_of(fi_uac1, struct f_uac1_opts, func_inst);
+ uac1_opts->p_chmask = p_chmask;
+ uac1_opts->p_srate = p_srate;
+ uac1_opts->p_ssize = p_ssize;
+ uac1_opts->c_chmask = c_chmask;
+ uac1_opts->c_srate = c_srate;
+ uac1_opts->c_ssize = c_ssize;
+ uac1_opts->req_number = UAC1_DEF_REQ_NUM;
+#else /* CONFIG_GADGET_UAC1_LEGACY */
+ uac1_opts = container_of(fi_uac1, struct f_uac1_legacy_opts, func_inst);
uac1_opts->fn_play = fn_play;
uac1_opts->fn_cap = fn_cap;
uac1_opts->fn_cntl = fn_cntl;
uac1_opts->req_buf_size = req_buf_size;
uac1_opts->req_count = req_count;
uac1_opts->audio_buf_size = audio_buf_size;
+#endif /* CONFIG_GADGET_UAC1_LEGACY */
#endif
status = usb_string_ids_tab(cdev, strings_dev);
diff --git a/drivers/usb/gadget/legacy/inode.c b/drivers/usb/gadget/legacy/inode.c
index b9ca0a26cbd9..684900fcfe24 100644
--- a/drivers/usb/gadget/legacy/inode.c
+++ b/drivers/usb/gadget/legacy/inode.c
@@ -1183,8 +1183,10 @@ dev_release (struct inode *inode, struct file *fd)
/* closing ep0 === shutdown all */
- if (dev->gadget_registered)
+ if (dev->gadget_registered) {
usb_gadget_unregister_driver (&gadgetfs_driver);
+ dev->gadget_registered = false;
+ }
/* at this point "good" hardware has disconnected the
* device from USB; the host won't see it any more.
@@ -1677,9 +1679,10 @@ static void
gadgetfs_suspend (struct usb_gadget *gadget)
{
struct dev_data *dev = get_gadget_data (gadget);
+ unsigned long flags;
INFO (dev, "suspended from state %d\n", dev->state);
- spin_lock (&dev->lock);
+ spin_lock_irqsave(&dev->lock, flags);
switch (dev->state) {
case STATE_DEV_SETUP: // VERY odd... host died??
case STATE_DEV_CONNECTED:
@@ -1690,7 +1693,7 @@ gadgetfs_suspend (struct usb_gadget *gadget)
default:
break;
}
- spin_unlock (&dev->lock);
+ spin_unlock_irqrestore(&dev->lock, flags);
}
static struct usb_gadget_driver gadgetfs_driver = {
diff --git a/drivers/usb/gadget/legacy/mass_storage.c b/drivers/usb/gadget/legacy/mass_storage.c
index 125974f32f50..e99ab57ee3e5 100644
--- a/drivers/usb/gadget/legacy/mass_storage.c
+++ b/drivers/usb/gadget/legacy/mass_storage.c
@@ -210,7 +210,6 @@ static int msg_bind(struct usb_composite_dev *cdev)
usb_composite_overwrite_options(cdev, &coverwrite);
dev_info(&cdev->gadget->dev,
DRIVER_DESC ", version: " DRIVER_VERSION "\n");
- set_bit(0, &msg_registered);
return 0;
fail_otg_desc:
@@ -257,7 +256,12 @@ MODULE_LICENSE("GPL");
static int __init msg_init(void)
{
- return usb_composite_probe(&msg_driver);
+ int ret;
+
+ ret = usb_composite_probe(&msg_driver);
+ set_bit(0, &msg_registered);
+
+ return ret;
}
module_init(msg_init);
diff --git a/drivers/usb/gadget/udc/Kconfig b/drivers/usb/gadget/udc/Kconfig
index 1c14c283cc47..9ffb11ec9ed9 100644
--- a/drivers/usb/gadget/udc/Kconfig
+++ b/drivers/usb/gadget/udc/Kconfig
@@ -55,7 +55,7 @@ config USB_LPC32XX
config USB_ATMEL_USBA
tristate "Atmel USBA"
- depends on ((AVR32 && !OF) || ARCH_AT91)
+ depends on ARCH_AT91
help
USBA is the integrated high-speed USB Device controller on
the AT32AP700x, some AT91SAM9 and AT91CAP9 processors from Atmel.
@@ -256,7 +256,7 @@ config USB_MV_U3D
controller, which support super speed USB peripheral.
config USB_SNP_CORE
- depends on USB_AMD5536UDC
+ depends on (USB_AMD5536UDC || USB_SNP_UDC_PLAT)
tristate
help
This enables core driver support for Synopsys USB 2.0 Device
@@ -269,6 +269,20 @@ config USB_SNP_CORE
This IP is different to the High Speed OTG IP that can be enabled
by selecting USB_DWC2 or USB_DWC3 options.
+config USB_SNP_UDC_PLAT
+ tristate "Synopsys USB 2.0 Device controller"
+ depends on (USB_GADGET && OF)
+ select USB_GADGET_DUALSPEED
+ select USB_SNP_CORE
+ default ARCH_BCM_IPROC
+ help
+ This adds Platform Device support for Synopsys Designware core
+ AHB subsystem USB2.0 Device Controller (UDC).
+
+ This driver works with UDCs integrated into Broadcom's Northstar2
+ and Cygnus SoCs.
+
+ If unsure, say N.
#
# Controllers available in both integrated and discrete versions
#
diff --git a/drivers/usb/gadget/udc/Makefile b/drivers/usb/gadget/udc/Makefile
index 626e1f1c62da..ea9e1c7f1923 100644
--- a/drivers/usb/gadget/udc/Makefile
+++ b/drivers/usb/gadget/udc/Makefile
@@ -10,7 +10,7 @@ obj-$(CONFIG_USB_GADGET) += udc-core.o
obj-$(CONFIG_USB_DUMMY_HCD) += dummy_hcd.o
obj-$(CONFIG_USB_NET2272) += net2272.o
obj-$(CONFIG_USB_NET2280) += net2280.o
-obj-$(CONFIG_USB_SNP_CORE) += amd5536udc.o
+obj-$(CONFIG_USB_SNP_CORE) += snps_udc_core.o
obj-$(CONFIG_USB_AMD5536UDC) += amd5536udc_pci.o
obj-$(CONFIG_USB_PXA25X) += pxa25x_udc.o
obj-$(CONFIG_USB_PXA27X) += pxa27x_udc.o
@@ -37,4 +37,5 @@ obj-$(CONFIG_USB_FOTG210_UDC) += fotg210-udc.o
obj-$(CONFIG_USB_MV_U3D) += mv_u3d_core.o
obj-$(CONFIG_USB_GR_UDC) += gr_udc.o
obj-$(CONFIG_USB_GADGET_XILINX) += udc-xilinx.o
+obj-$(CONFIG_USB_SNP_UDC_PLAT) += snps_udc_plat.o
obj-$(CONFIG_USB_BDC_UDC) += bdc/
diff --git a/drivers/usb/gadget/udc/amd5536udc.h b/drivers/usb/gadget/udc/amd5536udc.h
index fae49bf3833e..4fe22d432af2 100644
--- a/drivers/usb/gadget/udc/amd5536udc.h
+++ b/drivers/usb/gadget/udc/amd5536udc.h
@@ -16,6 +16,7 @@
/* debug control */
/* #define UDC_VERBOSE */
+#include <linux/extcon.h>
#include <linux/usb/ch9.h>
#include <linux/usb/gadget.h>
@@ -28,6 +29,9 @@
#define UDC_HSA0_REV 1
#define UDC_HSB1_REV 2
+/* Broadcom chip rev. */
+#define UDC_BCM_REV 10
+
/*
* SETUP usb commands
* needed, because some SETUP's are handled in hw, but must be passed to
@@ -112,6 +116,7 @@
#define UDC_DEVCTL_BRLEN_MASK 0x00ff0000
#define UDC_DEVCTL_BRLEN_OFS 16
+#define UDC_DEVCTL_SRX_FLUSH 14
#define UDC_DEVCTL_CSR_DONE 13
#define UDC_DEVCTL_DEVNAK 12
#define UDC_DEVCTL_SD 10
@@ -563,6 +568,16 @@ struct udc {
u16 cur_config;
u16 cur_intf;
u16 cur_alt;
+
+ /* for platform device and extcon support */
+ struct device *dev;
+ struct phy *udc_phy;
+ struct extcon_dev *edev;
+ struct extcon_specific_cable_nb extcon_nb;
+ struct notifier_block nb;
+ struct delayed_work drd_work;
+ struct workqueue_struct *drd_wq;
+ u32 conn_type;
};
#define to_amd5536_udc(g) (container_of((g), struct udc, gadget))
@@ -578,6 +593,7 @@ int udc_enable_dev_setup_interrupts(struct udc *dev);
int udc_mask_unused_interrupts(struct udc *dev);
irqreturn_t udc_irq(int irq, void *pdev);
void gadget_release(struct device *pdev);
+void empty_req_queue(struct udc_ep *ep);
void udc_basic_init(struct udc *dev);
void free_dma_pools(struct udc *dev);
int init_dma_pools(struct udc *dev);
@@ -639,7 +655,7 @@ MODULE_PARM_DESC(use_fullspeed, "true for fullspeed only");
/* debug macros ------------------------------------------------------------*/
-#define DBG(udc , args...) dev_dbg(&(udc)->pdev->dev, args)
+#define DBG(udc , args...) dev_dbg(udc->dev, args)
#ifdef UDC_VERBOSE
#define VDBG DBG
diff --git a/drivers/usb/gadget/udc/amd5536udc_pci.c b/drivers/usb/gadget/udc/amd5536udc_pci.c
index 2a2d0a96fe24..57a13f080a79 100644
--- a/drivers/usb/gadget/udc/amd5536udc_pci.c
+++ b/drivers/usb/gadget/udc/amd5536udc_pci.c
@@ -168,6 +168,7 @@ static int udc_pci_probe(
dev->phys_addr = resource;
dev->irq = pdev->irq;
dev->pdev = pdev;
+ dev->dev = &pdev->dev;
/* general probing */
if (udc_probe(dev)) {
diff --git a/drivers/usb/gadget/udc/atmel_usba_udc.c b/drivers/usb/gadget/udc/atmel_usba_udc.c
index 3ccc34176a5a..98d71400f8a1 100644
--- a/drivers/usb/gadget/udc/atmel_usba_udc.c
+++ b/drivers/usb/gadget/udc/atmel_usba_udc.c
@@ -152,7 +152,7 @@ static int regs_dbg_open(struct inode *inode, struct file *file)
spin_lock_irq(&udc->lock);
for (i = 0; i < inode->i_size / 4; i++)
- data[i] = usba_io_readl(udc->regs + i * 4);
+ data[i] = readl_relaxed(udc->regs + i * 4);
spin_unlock_irq(&udc->lock);
file->private_data = data;
@@ -1369,7 +1369,7 @@ static int handle_ep0_setup(struct usba_udc *udc, struct usba_ep *ep,
if (crq->wLength != cpu_to_le16(sizeof(status)))
goto stall;
ep->state = DATA_STAGE_IN;
- usba_io_writew(status, ep->fifo);
+ writew_relaxed(status, ep->fifo);
usba_ep_writel(ep, SET_STA, USBA_TX_PK_RDY);
break;
}
diff --git a/drivers/usb/gadget/udc/atmel_usba_udc.h b/drivers/usb/gadget/udc/atmel_usba_udc.h
index 9551b704bfd3..f8ebe0389bd4 100644
--- a/drivers/usb/gadget/udc/atmel_usba_udc.h
+++ b/drivers/usb/gadget/udc/atmel_usba_udc.h
@@ -43,13 +43,8 @@
#define USBA_REMOTE_WAKE_UP (1 << 10)
#define USBA_PULLD_DIS (1 << 11)
-#if defined(CONFIG_AVR32)
-#define USBA_ENABLE_MASK USBA_EN_USBA
-#define USBA_DISABLE_MASK 0
-#elif defined(CONFIG_ARCH_AT91)
#define USBA_ENABLE_MASK (USBA_EN_USBA | USBA_PULLD_DIS)
#define USBA_DISABLE_MASK USBA_DETACH
-#endif /* CONFIG_ARCH_AT91 */
/* Bitfields in FNUM */
#define USBA_MICRO_FRAME_NUM_OFFSET 0
@@ -191,28 +186,18 @@
| USBA_BF(name, value))
/* Register access macros */
-#ifdef CONFIG_AVR32
-#define usba_io_readl __raw_readl
-#define usba_io_writel __raw_writel
-#define usba_io_writew __raw_writew
-#else
-#define usba_io_readl readl_relaxed
-#define usba_io_writel writel_relaxed
-#define usba_io_writew writew_relaxed
-#endif
-
#define usba_readl(udc, reg) \
- usba_io_readl((udc)->regs + USBA_##reg)
+ readl_relaxed((udc)->regs + USBA_##reg)
#define usba_writel(udc, reg, value) \
- usba_io_writel((value), (udc)->regs + USBA_##reg)
+ writel_relaxed((value), (udc)->regs + USBA_##reg)
#define usba_ep_readl(ep, reg) \
- usba_io_readl((ep)->ep_regs + USBA_EPT_##reg)
+ readl_relaxed((ep)->ep_regs + USBA_EPT_##reg)
#define usba_ep_writel(ep, reg, value) \
- usba_io_writel((value), (ep)->ep_regs + USBA_EPT_##reg)
+ writel_relaxed((value), (ep)->ep_regs + USBA_EPT_##reg)
#define usba_dma_readl(ep, reg) \
- usba_io_readl((ep)->dma_regs + USBA_DMA_##reg)
+ readl_relaxed((ep)->dma_regs + USBA_DMA_##reg)
#define usba_dma_writel(ep, reg, value) \
- usba_io_writel((value), (ep)->dma_regs + USBA_DMA_##reg)
+ writel_relaxed((value), (ep)->dma_regs + USBA_DMA_##reg)
/* Calculate base address for a given endpoint or DMA controller */
#define USBA_EPT_BASE(x) (0x100 + (x) * 0x20)
diff --git a/drivers/usb/gadget/udc/bdc/bdc_core.c b/drivers/usb/gadget/udc/bdc/bdc_core.c
index ccb9c213cc9f..e9bd8d4abca0 100644
--- a/drivers/usb/gadget/udc/bdc/bdc_core.c
+++ b/drivers/usb/gadget/udc/bdc/bdc_core.c
@@ -475,7 +475,7 @@ static int bdc_probe(struct platform_device *pdev)
bdc->dev = dev;
dev_dbg(bdc->dev, "bdc->regs: %p irq=%d\n", bdc->regs, bdc->irq);
- temp = bdc_readl(bdc->regs, BDC_BDCSC);
+ temp = bdc_readl(bdc->regs, BDC_BDCCAP1);
if ((temp & BDC_P64) &&
!dma_set_mask_and_coherent(dev, DMA_BIT_MASK(64))) {
dev_dbg(bdc->dev, "Using 64-bit address\n");
diff --git a/drivers/usb/gadget/udc/core.c b/drivers/usb/gadget/udc/core.c
index efce68e9a8e0..e6f04eee95c4 100644
--- a/drivers/usb/gadget/udc/core.c
+++ b/drivers/usb/gadget/udc/core.c
@@ -23,6 +23,7 @@
#include <linux/list.h>
#include <linux/err.h>
#include <linux/dma-mapping.h>
+#include <linux/sched/task_stack.h>
#include <linux/workqueue.h>
#include <linux/usb/ch9.h>
@@ -139,10 +140,8 @@ int usb_ep_disable(struct usb_ep *ep)
goto out;
ret = ep->ops->disable(ep);
- if (ret) {
- ret = ret;
+ if (ret)
goto out;
- }
ep->enabled = false;
@@ -798,6 +797,14 @@ int usb_gadget_map_request_by_dev(struct device *dev,
req->num_mapped_sgs = mapped;
} else {
+ if (is_vmalloc_addr(req->buf)) {
+ dev_err(dev, "buffer is not dma capable\n");
+ return -EFAULT;
+ } else if (object_is_on_stack(req->buf)) {
+ dev_err(dev, "buffer is on stack\n");
+ return -EFAULT;
+ }
+
req->dma = dma_map_single(dev, req->buf, req->length,
is_in ? DMA_TO_DEVICE : DMA_FROM_DEVICE);
@@ -1058,6 +1065,23 @@ static inline void usb_gadget_udc_stop(struct usb_udc *udc)
}
/**
+ * usb_gadget_udc_set_speed - tells usb device controller speed supported by
+ * current driver
+ * @udc: The device we want to set maximum speed
+ * @speed: The maximum speed to allowed to run
+ *
+ * This call is issued by the UDC Class driver before calling
+ * usb_gadget_udc_start() in order to make sure that we don't try to
+ * connect on speeds the gadget driver doesn't support.
+ */
+static inline void usb_gadget_udc_set_speed(struct usb_udc *udc,
+ enum usb_device_speed speed)
+{
+ if (udc->gadget->ops->udc_set_speed)
+ udc->gadget->ops->udc_set_speed(udc->gadget, speed);
+}
+
+/**
* usb_udc_release - release the usb_udc struct
* @dev: the dev member within usb_udc
*
@@ -1290,6 +1314,9 @@ static int udc_bind_to_driver(struct usb_udc *udc, struct usb_gadget_driver *dri
udc->dev.driver = &driver->driver;
udc->gadget->dev.driver = &driver->driver;
+ if (driver->max_speed < udc->gadget->max_speed)
+ usb_gadget_udc_set_speed(udc, driver->max_speed);
+
ret = driver->bind(udc->gadget, driver);
if (ret)
goto err1;
@@ -1442,6 +1469,18 @@ static ssize_t state_show(struct device *dev, struct device_attribute *attr,
}
static DEVICE_ATTR_RO(state);
+static ssize_t function_show(struct device *dev, struct device_attribute *attr,
+ char *buf)
+{
+ struct usb_udc *udc = container_of(dev, struct usb_udc, dev);
+ struct usb_gadget_driver *drv = udc->driver;
+
+ if (!drv || !drv->function)
+ return 0;
+ return scnprintf(buf, PAGE_SIZE, "%s\n", drv->function);
+}
+static DEVICE_ATTR_RO(function);
+
#define USB_UDC_SPEED_ATTR(name, param) \
ssize_t name##_show(struct device *dev, \
struct device_attribute *attr, char *buf) \
@@ -1477,6 +1516,7 @@ static struct attribute *usb_udc_attrs[] = {
&dev_attr_srp.attr,
&dev_attr_soft_connect.attr,
&dev_attr_state.attr,
+ &dev_attr_function.attr,
&dev_attr_current_speed.attr,
&dev_attr_maximum_speed.attr,
diff --git a/drivers/usb/gadget/udc/dummy_hcd.c b/drivers/usb/gadget/udc/dummy_hcd.c
index ccabb51cb98d..3c3760315910 100644
--- a/drivers/usb/gadget/udc/dummy_hcd.c
+++ b/drivers/usb/gadget/udc/dummy_hcd.c
@@ -442,23 +442,16 @@ static void set_link_state(struct dummy_hcd *dum_hcd)
/* Report reset and disconnect events to the driver */
if (dum->driver && (disconnect || reset)) {
stop_activity(dum);
- spin_unlock(&dum->lock);
if (reset)
usb_gadget_udc_reset(&dum->gadget, dum->driver);
else
dum->driver->disconnect(&dum->gadget);
- spin_lock(&dum->lock);
}
} else if (dum_hcd->active != dum_hcd->old_active) {
- if (dum_hcd->old_active && dum->driver->suspend) {
- spin_unlock(&dum->lock);
+ if (dum_hcd->old_active && dum->driver->suspend)
dum->driver->suspend(&dum->gadget);
- spin_lock(&dum->lock);
- } else if (!dum_hcd->old_active && dum->driver->resume) {
- spin_unlock(&dum->lock);
+ else if (!dum_hcd->old_active && dum->driver->resume)
dum->driver->resume(&dum->gadget);
- spin_lock(&dum->lock);
- }
}
dum_hcd->old_status = dum_hcd->port_status;
@@ -888,22 +881,6 @@ static int dummy_pullup(struct usb_gadget *_gadget, int value)
unsigned long flags;
dum = gadget_dev_to_dummy(&_gadget->dev);
-
- if (value && dum->driver) {
- if (mod_data.is_super_speed)
- dum->gadget.speed = dum->driver->max_speed;
- else if (mod_data.is_high_speed)
- dum->gadget.speed = min_t(u8, USB_SPEED_HIGH,
- dum->driver->max_speed);
- else
- dum->gadget.speed = USB_SPEED_FULL;
- dummy_udc_update_ep0(dum);
-
- if (dum->gadget.speed < dum->driver->max_speed)
- dev_dbg(udc_dev(dum), "This device can perform faster"
- " if you connect it to a %s port...\n",
- usb_speed_string(dum->driver->max_speed));
- }
dum_hcd = gadget_to_dummy_hcd(_gadget);
spin_lock_irqsave(&dum->lock, flags);
@@ -915,6 +892,28 @@ static int dummy_pullup(struct usb_gadget *_gadget, int value)
return 0;
}
+static void dummy_udc_set_speed(struct usb_gadget *_gadget,
+ enum usb_device_speed speed)
+{
+ struct dummy *dum;
+
+ dum = gadget_dev_to_dummy(&_gadget->dev);
+
+ if (mod_data.is_super_speed)
+ dum->gadget.speed = min_t(u8, USB_SPEED_SUPER, speed);
+ else if (mod_data.is_high_speed)
+ dum->gadget.speed = min_t(u8, USB_SPEED_HIGH, speed);
+ else
+ dum->gadget.speed = USB_SPEED_FULL;
+
+ dummy_udc_update_ep0(dum);
+
+ if (dum->gadget.speed < speed)
+ dev_dbg(udc_dev(dum), "This device can perform faster"
+ " if you connect it to a %s port...\n",
+ usb_speed_string(speed));
+}
+
static int dummy_udc_start(struct usb_gadget *g,
struct usb_gadget_driver *driver);
static int dummy_udc_stop(struct usb_gadget *g);
@@ -926,6 +925,7 @@ static const struct usb_gadget_ops dummy_ops = {
.pullup = dummy_pullup,
.udc_start = dummy_udc_start,
.udc_stop = dummy_udc_stop,
+ .udc_set_speed = dummy_udc_set_speed,
};
/*-------------------------------------------------------------------------*/
@@ -983,7 +983,9 @@ static int dummy_udc_stop(struct usb_gadget *g)
struct dummy_hcd *dum_hcd = gadget_to_dummy_hcd(g);
struct dummy *dum = dum_hcd->dum;
+ spin_lock_irq(&dum->lock);
dum->driver = NULL;
+ spin_unlock_irq(&dum->lock);
return 0;
}
diff --git a/drivers/usb/gadget/udc/mv_udc_core.c b/drivers/usb/gadget/udc/mv_udc_core.c
index 76f56c5762f9..8a708d0a1042 100644
--- a/drivers/usb/gadget/udc/mv_udc_core.c
+++ b/drivers/usb/gadget/udc/mv_udc_core.c
@@ -960,9 +960,9 @@ static const struct usb_ep_ops mv_ep_ops = {
.fifo_flush = mv_ep_fifo_flush, /* flush fifo */
};
-static void udc_clock_enable(struct mv_udc *udc)
+static int udc_clock_enable(struct mv_udc *udc)
{
- clk_prepare_enable(udc->clk);
+ return clk_prepare_enable(udc->clk);
}
static void udc_clock_disable(struct mv_udc *udc)
@@ -1070,7 +1070,10 @@ static int mv_udc_enable_internal(struct mv_udc *udc)
return 0;
dev_dbg(&udc->dev->dev, "enable udc\n");
- udc_clock_enable(udc);
+ retval = udc_clock_enable(udc);
+ if (retval)
+ return retval;
+
if (udc->pdata->phy_init) {
retval = udc->pdata->phy_init(udc->phy_regs);
if (retval) {
diff --git a/drivers/usb/gadget/udc/net2280.c b/drivers/usb/gadget/udc/net2280.c
index 6cf07857eaca..f608c1f85e61 100644
--- a/drivers/usb/gadget/udc/net2280.c
+++ b/drivers/usb/gadget/udc/net2280.c
@@ -2470,11 +2470,8 @@ static void stop_activity(struct net2280 *dev, struct usb_gadget_driver *driver)
nuke(&dev->ep[i]);
/* report disconnect; the driver is already quiesced */
- if (driver) {
- spin_unlock(&dev->lock);
+ if (driver)
driver->disconnect(&dev->gadget);
- spin_lock(&dev->lock);
- }
usb_reinit(dev);
}
@@ -3348,8 +3345,6 @@ next_endpoints:
BIT(PCI_RETRY_ABORT_INTERRUPT))
static void handle_stat1_irqs(struct net2280 *dev, u32 stat)
-__releases(dev->lock)
-__acquires(dev->lock)
{
struct net2280_ep *ep;
u32 tmp, num, mask, scratch;
@@ -3390,14 +3385,12 @@ __acquires(dev->lock)
if (disconnect || reset) {
stop_activity(dev, dev->driver);
ep0_start(dev);
- spin_unlock(&dev->lock);
if (reset)
usb_gadget_udc_reset
(&dev->gadget, dev->driver);
else
(dev->driver->disconnect)
(&dev->gadget);
- spin_lock(&dev->lock);
return;
}
}
@@ -3573,7 +3566,6 @@ static void net2280_remove(struct pci_dev *pdev)
BUG_ON(dev->driver);
/* then clean up the resources we allocated during probe() */
- net2280_led_shutdown(dev);
if (dev->requests) {
int i;
for (i = 1; i < 5; i++) {
@@ -3588,8 +3580,10 @@ static void net2280_remove(struct pci_dev *pdev)
free_irq(pdev->irq, dev);
if (dev->quirks & PLX_PCIE)
pci_disable_msi(pdev);
- if (dev->regs)
+ if (dev->regs) {
+ net2280_led_shutdown(dev);
iounmap(dev->regs);
+ }
if (dev->region)
release_mem_region(pci_resource_start(pdev, 0),
pci_resource_len(pdev, 0));
diff --git a/drivers/usb/gadget/udc/renesas_usb3.c b/drivers/usb/gadget/udc/renesas_usb3.c
index 5a2d845fb1a6..d8278322d5ac 100644
--- a/drivers/usb/gadget/udc/renesas_usb3.c
+++ b/drivers/usb/gadget/udc/renesas_usb3.c
@@ -9,6 +9,7 @@
*/
#include <linux/delay.h>
+#include <linux/dma-mapping.h>
#include <linux/err.h>
#include <linux/extcon.h>
#include <linux/interrupt.h>
@@ -27,6 +28,8 @@
#define USB3_AXI_INT_ENA 0x00c
#define USB3_DMA_INT_STA 0x010
#define USB3_DMA_INT_ENA 0x014
+#define USB3_DMA_CH0_CON(n) (0x030 + ((n) - 1) * 0x10) /* n = 1 to 4 */
+#define USB3_DMA_CH0_PRD_ADR(n) (0x034 + ((n) - 1) * 0x10) /* n = 1 to 4 */
#define USB3_USB_COM_CON 0x200
#define USB3_USB20_CON 0x204
#define USB3_USB30_CON 0x208
@@ -64,6 +67,22 @@
/* AXI_INT_ENA and AXI_INT_STA */
#define AXI_INT_DMAINT BIT(31)
#define AXI_INT_EPCINT BIT(30)
+/* PRD's n = from 1 to 4 */
+#define AXI_INT_PRDEN_CLR_STA_SHIFT(n) (16 + (n) - 1)
+#define AXI_INT_PRDERR_STA_SHIFT(n) (0 + (n) - 1)
+#define AXI_INT_PRDEN_CLR_STA(n) (1 << AXI_INT_PRDEN_CLR_STA_SHIFT(n))
+#define AXI_INT_PRDERR_STA(n) (1 << AXI_INT_PRDERR_STA_SHIFT(n))
+
+/* DMA_INT_ENA and DMA_INT_STA */
+#define DMA_INT(n) BIT(n)
+
+/* DMA_CH0_CONn */
+#define DMA_CON_PIPE_DIR BIT(15) /* 1: In Transfer */
+#define DMA_CON_PIPE_NO_SHIFT 8
+#define DMA_CON_PIPE_NO_MASK GENMASK(12, DMA_CON_PIPE_NO_SHIFT)
+#define DMA_COM_PIPE_NO(n) (((n) << DMA_CON_PIPE_NO_SHIFT) & \
+ DMA_CON_PIPE_NO_MASK)
+#define DMA_CON_PRD_EN BIT(0)
/* LCLKSEL */
#define LCLKSEL_LSEL BIT(18)
@@ -231,8 +250,50 @@
#define USB3_EP0_BUF_SIZE 8
#define USB3_MAX_NUM_PIPES 30
#define USB3_WAIT_US 3
+#define USB3_DMA_NUM_SETTING_AREA 4
+/*
+ * To avoid double-meaning of "0" (xferred 65536 bytes or received zlp if
+ * buffer size is 65536), this driver uses the maximum size per a entry is
+ * 32768 bytes.
+ */
+#define USB3_DMA_MAX_XFER_SIZE 32768
+#define USB3_DMA_PRD_SIZE 4096
struct renesas_usb3;
+
+/* Physical Region Descriptor Table */
+struct renesas_usb3_prd {
+ u32 word1;
+#define USB3_PRD1_E BIT(30) /* the end of chain */
+#define USB3_PRD1_U BIT(29) /* completion of transfer */
+#define USB3_PRD1_D BIT(28) /* Error occurred */
+#define USB3_PRD1_INT BIT(27) /* Interrupt occurred */
+#define USB3_PRD1_LST BIT(26) /* Last Packet */
+#define USB3_PRD1_B_INC BIT(24)
+#define USB3_PRD1_MPS_8 0
+#define USB3_PRD1_MPS_16 BIT(21)
+#define USB3_PRD1_MPS_32 BIT(22)
+#define USB3_PRD1_MPS_64 (BIT(22) | BIT(21))
+#define USB3_PRD1_MPS_512 BIT(23)
+#define USB3_PRD1_MPS_1024 (BIT(23) | BIT(21))
+#define USB3_PRD1_MPS_RESERVED (BIT(23) | BIT(22) | BIT(21))
+#define USB3_PRD1_SIZE_MASK GENMASK(15, 0)
+
+ u32 bap;
+};
+#define USB3_DMA_NUM_PRD_ENTRIES (USB3_DMA_PRD_SIZE / \
+ sizeof(struct renesas_usb3_prd))
+#define USB3_DMA_MAX_XFER_SIZE_ALL_PRDS (USB3_DMA_PRD_SIZE / \
+ sizeof(struct renesas_usb3_prd) * \
+ USB3_DMA_MAX_XFER_SIZE)
+
+struct renesas_usb3_dma {
+ struct renesas_usb3_prd *prd;
+ dma_addr_t prd_dma;
+ int num; /* Setting area number (from 1 to 4) */
+ bool used;
+};
+
struct renesas_usb3_request {
struct usb_request req;
struct list_head queue;
@@ -242,6 +303,7 @@ struct renesas_usb3_request {
struct renesas_usb3_ep {
struct usb_ep ep;
struct renesas_usb3 *usb3;
+ struct renesas_usb3_dma *dma;
int num;
char ep_name[USB3_EP_NAME_SIZE];
struct list_head queue;
@@ -270,6 +332,8 @@ struct renesas_usb3 {
struct renesas_usb3_ep *usb3_ep;
int num_usb3_eps;
+ struct renesas_usb3_dma dma[USB3_DMA_NUM_SETTING_AREA];
+
spinlock_t lock;
int disabled_count;
@@ -298,8 +362,18 @@ struct renesas_usb3 {
(i) < (usb3)->num_usb3_eps; \
(i)++, usb3_ep = usb3_get_ep(usb3, (i)))
+#define usb3_get_dma(usb3, i) (&(usb3)->dma[i])
+#define usb3_for_each_dma(usb3, dma, i) \
+ for ((i) = 0, dma = usb3_get_dma((usb3), (i)); \
+ (i) < USB3_DMA_NUM_SETTING_AREA; \
+ (i)++, dma = usb3_get_dma((usb3), (i)))
+
static const char udc_name[] = "renesas_usb3";
+static bool use_dma = 1;
+module_param(use_dma, bool, 0644);
+MODULE_PARM_DESC(use_dma, "use dedicated DMAC");
+
static void usb3_write(struct renesas_usb3 *usb3, u32 data, u32 offs)
{
iowrite32(data, usb3->reg + offs);
@@ -623,7 +697,6 @@ static void renesas_usb3_stop_controller(struct renesas_usb3 *usb3)
{
usb3_disconnect(usb3);
usb3_write(usb3, 0, USB3_P0_INT_ENA);
- usb3_write(usb3, 0, USB3_PN_INT_ENA);
usb3_write(usb3, 0, USB3_USB_OTG_INT_ENA);
usb3_write(usb3, 0, USB3_USB_INT_ENA_1);
usb3_write(usb3, 0, USB3_USB_INT_ENA_2);
@@ -1060,6 +1133,273 @@ static void usb3_start_pipe0(struct renesas_usb3_ep *usb3_ep,
usb3_p0_xfer(usb3_ep, usb3_req);
}
+static void usb3_enable_dma_pipen(struct renesas_usb3 *usb3)
+{
+ usb3_set_bit(usb3, PN_CON_DATAIF_EN, USB3_PN_CON);
+}
+
+static void usb3_disable_dma_pipen(struct renesas_usb3 *usb3)
+{
+ usb3_clear_bit(usb3, PN_CON_DATAIF_EN, USB3_PN_CON);
+}
+
+static void usb3_enable_dma_irq(struct renesas_usb3 *usb3, int num)
+{
+ usb3_set_bit(usb3, DMA_INT(num), USB3_DMA_INT_ENA);
+}
+
+static void usb3_disable_dma_irq(struct renesas_usb3 *usb3, int num)
+{
+ usb3_clear_bit(usb3, DMA_INT(num), USB3_DMA_INT_ENA);
+}
+
+static u32 usb3_dma_mps_to_prd_word1(struct renesas_usb3_ep *usb3_ep)
+{
+ switch (usb3_ep->ep.maxpacket) {
+ case 8:
+ return USB3_PRD1_MPS_8;
+ case 16:
+ return USB3_PRD1_MPS_16;
+ case 32:
+ return USB3_PRD1_MPS_32;
+ case 64:
+ return USB3_PRD1_MPS_64;
+ case 512:
+ return USB3_PRD1_MPS_512;
+ case 1024:
+ return USB3_PRD1_MPS_1024;
+ default:
+ return USB3_PRD1_MPS_RESERVED;
+ }
+}
+
+static bool usb3_dma_get_setting_area(struct renesas_usb3_ep *usb3_ep,
+ struct renesas_usb3_request *usb3_req)
+{
+ struct renesas_usb3 *usb3 = usb3_ep_to_usb3(usb3_ep);
+ struct renesas_usb3_dma *dma;
+ int i;
+ bool ret = false;
+
+ if (usb3_req->req.length > USB3_DMA_MAX_XFER_SIZE_ALL_PRDS) {
+ dev_dbg(usb3_to_dev(usb3), "%s: the length is too big (%d)\n",
+ __func__, usb3_req->req.length);
+ return false;
+ }
+
+ /* The driver doesn't handle zero-length packet via dmac */
+ if (!usb3_req->req.length)
+ return false;
+
+ if (usb3_dma_mps_to_prd_word1(usb3_ep) == USB3_PRD1_MPS_RESERVED)
+ return false;
+
+ usb3_for_each_dma(usb3, dma, i) {
+ if (dma->used)
+ continue;
+
+ if (usb_gadget_map_request(&usb3->gadget, &usb3_req->req,
+ usb3_ep->dir_in) < 0)
+ break;
+
+ dma->used = true;
+ usb3_ep->dma = dma;
+ ret = true;
+ break;
+ }
+
+ return ret;
+}
+
+static void usb3_dma_put_setting_area(struct renesas_usb3_ep *usb3_ep,
+ struct renesas_usb3_request *usb3_req)
+{
+ struct renesas_usb3 *usb3 = usb3_ep_to_usb3(usb3_ep);
+ int i;
+ struct renesas_usb3_dma *dma;
+
+ usb3_for_each_dma(usb3, dma, i) {
+ if (usb3_ep->dma == dma) {
+ usb_gadget_unmap_request(&usb3->gadget, &usb3_req->req,
+ usb3_ep->dir_in);
+ dma->used = false;
+ usb3_ep->dma = NULL;
+ break;
+ }
+ }
+}
+
+static void usb3_dma_fill_prd(struct renesas_usb3_ep *usb3_ep,
+ struct renesas_usb3_request *usb3_req)
+{
+ struct renesas_usb3_prd *cur_prd = usb3_ep->dma->prd;
+ u32 remain = usb3_req->req.length;
+ u32 dma = usb3_req->req.dma;
+ u32 len;
+ int i = 0;
+
+ do {
+ len = min_t(u32, remain, USB3_DMA_MAX_XFER_SIZE) &
+ USB3_PRD1_SIZE_MASK;
+ cur_prd->word1 = usb3_dma_mps_to_prd_word1(usb3_ep) |
+ USB3_PRD1_B_INC | len;
+ cur_prd->bap = dma;
+ remain -= len;
+ dma += len;
+ if (!remain || (i + 1) < USB3_DMA_NUM_PRD_ENTRIES)
+ break;
+
+ cur_prd++;
+ i++;
+ } while (1);
+
+ cur_prd->word1 |= USB3_PRD1_E | USB3_PRD1_INT;
+ if (usb3_ep->dir_in)
+ cur_prd->word1 |= USB3_PRD1_LST;
+}
+
+static void usb3_dma_kick_prd(struct renesas_usb3_ep *usb3_ep)
+{
+ struct renesas_usb3_dma *dma = usb3_ep->dma;
+ struct renesas_usb3 *usb3 = usb3_ep_to_usb3(usb3_ep);
+ u32 dma_con = DMA_COM_PIPE_NO(usb3_ep->num) | DMA_CON_PRD_EN;
+
+ if (usb3_ep->dir_in)
+ dma_con |= DMA_CON_PIPE_DIR;
+
+ wmb(); /* prd entries should be in system memory here */
+
+ usb3_write(usb3, 1 << usb3_ep->num, USB3_DMA_INT_STA);
+ usb3_write(usb3, AXI_INT_PRDEN_CLR_STA(dma->num) |
+ AXI_INT_PRDERR_STA(dma->num), USB3_AXI_INT_STA);
+
+ usb3_write(usb3, dma->prd_dma, USB3_DMA_CH0_PRD_ADR(dma->num));
+ usb3_write(usb3, dma_con, USB3_DMA_CH0_CON(dma->num));
+ usb3_enable_dma_irq(usb3, usb3_ep->num);
+}
+
+static void usb3_dma_stop_prd(struct renesas_usb3_ep *usb3_ep)
+{
+ struct renesas_usb3 *usb3 = usb3_ep_to_usb3(usb3_ep);
+ struct renesas_usb3_dma *dma = usb3_ep->dma;
+
+ usb3_disable_dma_irq(usb3, usb3_ep->num);
+ usb3_write(usb3, 0, USB3_DMA_CH0_CON(dma->num));
+}
+
+static int usb3_dma_update_status(struct renesas_usb3_ep *usb3_ep,
+ struct renesas_usb3_request *usb3_req)
+{
+ struct renesas_usb3_prd *cur_prd = usb3_ep->dma->prd;
+ struct usb_request *req = &usb3_req->req;
+ u32 remain, len;
+ int i = 0;
+ int status = 0;
+
+ rmb(); /* The controller updated prd entries */
+
+ do {
+ if (cur_prd->word1 & USB3_PRD1_D)
+ status = -EIO;
+ if (cur_prd->word1 & USB3_PRD1_E)
+ len = req->length % USB3_DMA_MAX_XFER_SIZE;
+ else
+ len = USB3_DMA_MAX_XFER_SIZE;
+ remain = cur_prd->word1 & USB3_PRD1_SIZE_MASK;
+ req->actual += len - remain;
+
+ if (cur_prd->word1 & USB3_PRD1_E ||
+ (i + 1) < USB3_DMA_NUM_PRD_ENTRIES)
+ break;
+
+ cur_prd++;
+ i++;
+ } while (1);
+
+ return status;
+}
+
+static bool usb3_dma_try_start(struct renesas_usb3_ep *usb3_ep,
+ struct renesas_usb3_request *usb3_req)
+{
+ struct renesas_usb3 *usb3 = usb3_ep_to_usb3(usb3_ep);
+
+ if (!use_dma)
+ return false;
+
+ if (usb3_dma_get_setting_area(usb3_ep, usb3_req)) {
+ usb3_pn_stop(usb3);
+ usb3_enable_dma_pipen(usb3);
+ usb3_dma_fill_prd(usb3_ep, usb3_req);
+ usb3_dma_kick_prd(usb3_ep);
+ usb3_pn_start(usb3);
+ return true;
+ }
+
+ return false;
+}
+
+static int usb3_dma_try_stop(struct renesas_usb3_ep *usb3_ep,
+ struct renesas_usb3_request *usb3_req)
+{
+ struct renesas_usb3 *usb3 = usb3_ep_to_usb3(usb3_ep);
+ unsigned long flags;
+ int status = 0;
+
+ spin_lock_irqsave(&usb3->lock, flags);
+ if (!usb3_ep->dma)
+ goto out;
+
+ if (!usb3_pn_change(usb3, usb3_ep->num))
+ usb3_disable_dma_pipen(usb3);
+ usb3_dma_stop_prd(usb3_ep);
+ status = usb3_dma_update_status(usb3_ep, usb3_req);
+ usb3_dma_put_setting_area(usb3_ep, usb3_req);
+
+out:
+ spin_unlock_irqrestore(&usb3->lock, flags);
+ return status;
+}
+
+static int renesas_usb3_dma_free_prd(struct renesas_usb3 *usb3,
+ struct device *dev)
+{
+ int i;
+ struct renesas_usb3_dma *dma;
+
+ usb3_for_each_dma(usb3, dma, i) {
+ if (dma->prd) {
+ dma_free_coherent(dev, USB3_DMA_MAX_XFER_SIZE,
+ dma->prd, dma->prd_dma);
+ dma->prd = NULL;
+ }
+ }
+
+ return 0;
+}
+
+static int renesas_usb3_dma_alloc_prd(struct renesas_usb3 *usb3,
+ struct device *dev)
+{
+ int i;
+ struct renesas_usb3_dma *dma;
+
+ if (!use_dma)
+ return 0;
+
+ usb3_for_each_dma(usb3, dma, i) {
+ dma->prd = dma_alloc_coherent(dev, USB3_DMA_PRD_SIZE,
+ &dma->prd_dma, GFP_KERNEL);
+ if (!dma->prd) {
+ renesas_usb3_dma_free_prd(usb3, dev);
+ return -ENOMEM;
+ }
+ dma->num = i + 1;
+ }
+
+ return 0;
+}
+
static void usb3_start_pipen(struct renesas_usb3_ep *usb3_ep,
struct renesas_usb3_request *usb3_req)
{
@@ -1079,6 +1419,10 @@ static void usb3_start_pipen(struct renesas_usb3_ep *usb3_ep,
goto out;
usb3_ep->started = true;
+
+ if (usb3_dma_try_start(usb3_ep, usb3_req))
+ goto out;
+
usb3_pn_start(usb3);
if (usb3_ep->dir_in) {
@@ -1475,7 +1819,13 @@ static void usb3_request_done_pipen(struct renesas_usb3 *usb3,
struct renesas_usb3_request *usb3_req,
int status)
{
- usb3_pn_stop(usb3);
+ unsigned long flags;
+
+ spin_lock_irqsave(&usb3->lock, flags);
+ if (usb3_pn_change(usb3, usb3_ep->num))
+ usb3_pn_stop(usb3);
+ spin_unlock_irqrestore(&usb3->lock, flags);
+
usb3_disable_pipe_irq(usb3, usb3_ep->num);
usb3_request_done(usb3_ep, usb3_req, status);
@@ -1504,30 +1854,46 @@ static void usb3_irq_epc_pipen_bfrdy(struct renesas_usb3 *usb3, int num)
{
struct renesas_usb3_ep *usb3_ep = usb3_get_ep(usb3, num);
struct renesas_usb3_request *usb3_req = usb3_get_request(usb3_ep);
+ bool done = false;
if (!usb3_req)
return;
+ spin_lock(&usb3->lock);
+ if (usb3_pn_change(usb3, num))
+ goto out;
+
if (usb3_ep->dir_in) {
/* Do not stop the IN pipe here to detect LSTTR interrupt */
if (!usb3_write_pipe(usb3_ep, usb3_req, USB3_PN_WRITE))
usb3_clear_bit(usb3, PN_INT_BFRDY, USB3_PN_INT_ENA);
} else {
if (!usb3_read_pipe(usb3_ep, usb3_req, USB3_PN_READ))
- usb3_request_done_pipen(usb3, usb3_ep, usb3_req, 0);
+ done = true;
}
+
+out:
+ /* need to unlock because usb3_request_done_pipen() locks it */
+ spin_unlock(&usb3->lock);
+
+ if (done)
+ usb3_request_done_pipen(usb3, usb3_ep, usb3_req, 0);
}
static void usb3_irq_epc_pipen(struct renesas_usb3 *usb3, int num)
{
u32 pn_int_sta;
- if (usb3_pn_change(usb3, num) < 0)
+ spin_lock(&usb3->lock);
+ if (usb3_pn_change(usb3, num) < 0) {
+ spin_unlock(&usb3->lock);
return;
+ }
pn_int_sta = usb3_read(usb3, USB3_PN_INT_STA);
pn_int_sta &= usb3_read(usb3, USB3_PN_INT_ENA);
usb3_write(usb3, pn_int_sta, USB3_PN_INT_STA);
+ spin_unlock(&usb3->lock);
if (pn_int_sta & PN_INT_LSTTR)
usb3_irq_epc_pipen_lsttr(usb3, num);
if (pn_int_sta & PN_INT_BFRDY)
@@ -1582,12 +1948,49 @@ static void usb3_irq_epc(struct renesas_usb3 *usb3)
}
}
+static void usb3_irq_dma_int(struct renesas_usb3 *usb3, u32 dma_sta)
+{
+ struct renesas_usb3_ep *usb3_ep;
+ struct renesas_usb3_request *usb3_req;
+ int i, status;
+
+ for (i = 0; i < usb3->num_usb3_eps; i++) {
+ if (!(dma_sta & DMA_INT(i)))
+ continue;
+
+ usb3_ep = usb3_get_ep(usb3, i);
+ if (!(usb3_read(usb3, USB3_AXI_INT_STA) &
+ AXI_INT_PRDEN_CLR_STA(usb3_ep->dma->num)))
+ continue;
+
+ usb3_req = usb3_get_request(usb3_ep);
+ status = usb3_dma_try_stop(usb3_ep, usb3_req);
+ usb3_request_done_pipen(usb3, usb3_ep, usb3_req, status);
+ }
+}
+
+static void usb3_irq_dma(struct renesas_usb3 *usb3)
+{
+ u32 dma_sta = usb3_read(usb3, USB3_DMA_INT_STA);
+
+ dma_sta &= usb3_read(usb3, USB3_DMA_INT_ENA);
+ if (dma_sta) {
+ usb3_write(usb3, dma_sta, USB3_DMA_INT_STA);
+ usb3_irq_dma_int(usb3, dma_sta);
+ }
+}
+
static irqreturn_t renesas_usb3_irq(int irq, void *_usb3)
{
struct renesas_usb3 *usb3 = _usb3;
irqreturn_t ret = IRQ_NONE;
u32 axi_int_sta = usb3_read(usb3, USB3_AXI_INT_STA);
+ if (axi_int_sta & AXI_INT_DMAINT) {
+ usb3_irq_dma(usb3);
+ ret = IRQ_HANDLED;
+ }
+
if (axi_int_sta & AXI_INT_EPCINT) {
usb3_irq_epc(usb3);
ret = IRQ_HANDLED;
@@ -1660,6 +2063,7 @@ static int usb3_disable_pipe_n(struct renesas_usb3_ep *usb3_ep)
spin_lock_irqsave(&usb3->lock, flags);
if (!usb3_pn_change(usb3, usb3_ep->num)) {
+ usb3_write(usb3, 0, USB3_PN_INT_ENA);
usb3_write(usb3, 0, USB3_PN_RAMMAP);
usb3_clear_bit(usb3, PN_CON_EN, USB3_PN_CON);
}
@@ -1686,6 +2090,7 @@ static int renesas_usb3_ep_disable(struct usb_ep *_ep)
usb3_req = usb3_get_request(usb3_ep);
if (!usb3_req)
break;
+ usb3_dma_try_stop(usb3_ep, usb3_req);
usb3_request_done(usb3_ep, usb3_req, -ESHUTDOWN);
} while (1);
@@ -1733,6 +2138,7 @@ static int renesas_usb3_ep_dequeue(struct usb_ep *_ep, struct usb_request *_req)
dev_dbg(usb3_to_dev(usb3), "ep_dequeue: ep%2d, %u\n", usb3_ep->num,
_req->length);
+ usb3_dma_try_stop(usb3_ep, usb3_req);
usb3_request_done_pipen(usb3, usb3_ep, usb3_req, -ECONNRESET);
return 0;
@@ -1799,6 +2205,9 @@ static int renesas_usb3_start(struct usb_gadget *gadget,
/* hook up the driver */
usb3->driver = driver;
+ pm_runtime_enable(usb3_to_dev(usb3));
+ pm_runtime_get_sync(usb3_to_dev(usb3));
+
renesas_usb3_init_controller(usb3);
return 0;
@@ -1807,14 +2216,14 @@ static int renesas_usb3_start(struct usb_gadget *gadget,
static int renesas_usb3_stop(struct usb_gadget *gadget)
{
struct renesas_usb3 *usb3 = gadget_to_renesas_usb3(gadget);
- unsigned long flags;
- spin_lock_irqsave(&usb3->lock, flags);
usb3->softconnect = false;
usb3->gadget.speed = USB_SPEED_UNKNOWN;
usb3->driver = NULL;
renesas_usb3_stop_controller(usb3);
- spin_unlock_irqrestore(&usb3->lock, flags);
+
+ pm_runtime_put(usb3_to_dev(usb3));
+ pm_runtime_disable(usb3_to_dev(usb3));
return 0;
}
@@ -1891,10 +2300,8 @@ static int renesas_usb3_remove(struct platform_device *pdev)
device_remove_file(&pdev->dev, &dev_attr_role);
- pm_runtime_put(&pdev->dev);
- pm_runtime_disable(&pdev->dev);
-
usb_del_gadget_udc(&usb3->gadget);
+ renesas_usb3_dma_free_prd(usb3, &pdev->dev);
__renesas_usb3_ep_free_request(usb3->ep0_req);
@@ -2089,6 +2496,10 @@ static int renesas_usb3_probe(struct platform_device *pdev)
if (!usb3->ep0_req)
return -ENOMEM;
+ ret = renesas_usb3_dma_alloc_prd(usb3, &pdev->dev);
+ if (ret < 0)
+ goto err_alloc_prd;
+
ret = usb_add_gadget_udc(&pdev->dev, &usb3->gadget);
if (ret < 0)
goto err_add_udc;
@@ -2099,9 +2510,6 @@ static int renesas_usb3_probe(struct platform_device *pdev)
usb3->workaround_for_vbus = priv->workaround_for_vbus;
- pm_runtime_enable(&pdev->dev);
- pm_runtime_get_sync(&pdev->dev);
-
dev_info(&pdev->dev, "probed\n");
return 0;
@@ -2110,6 +2518,9 @@ err_dev_create:
usb_del_gadget_udc(&usb3->gadget);
err_add_udc:
+ renesas_usb3_dma_free_prd(usb3, &pdev->dev);
+
+err_alloc_prd:
__renesas_usb3_ep_free_request(usb3->ep0_req);
return ret;
diff --git a/drivers/usb/gadget/udc/amd5536udc.c b/drivers/usb/gadget/udc/snps_udc_core.c
index 4ecd2f20ea48..38a165dbf924 100644
--- a/drivers/usb/gadget/udc/amd5536udc.c
+++ b/drivers/usb/gadget/udc/snps_udc_core.c
@@ -41,7 +41,6 @@
#include "amd5536udc.h"
static void udc_tasklet_disconnect(unsigned long);
-static void empty_req_queue(struct udc_ep *);
static void udc_setup_endpoints(struct udc *dev);
static void udc_soft_reset(struct udc *dev);
static struct udc_request *udc_alloc_bna_dummy(struct udc_ep *ep);
@@ -209,18 +208,18 @@ static void print_regs(struct udc *dev)
if (use_dma && use_dma_ppb && !use_dma_ppb_du) {
DBG(dev, "DMA mode = PPBNDU (packet per buffer "
"WITHOUT desc. update)\n");
- dev_info(&dev->pdev->dev, "DMA mode (%s)\n", "PPBNDU");
+ dev_info(dev->dev, "DMA mode (%s)\n", "PPBNDU");
} else if (use_dma && use_dma_ppb && use_dma_ppb_du) {
DBG(dev, "DMA mode = PPBDU (packet per buffer "
"WITH desc. update)\n");
- dev_info(&dev->pdev->dev, "DMA mode (%s)\n", "PPBDU");
+ dev_info(dev->dev, "DMA mode (%s)\n", "PPBDU");
}
if (use_dma && use_dma_bufferfill_mode) {
DBG(dev, "DMA mode = BF (buffer fill mode)\n");
- dev_info(&dev->pdev->dev, "DMA mode (%s)\n", "BF");
+ dev_info(dev->dev, "DMA mode (%s)\n", "BF");
}
if (!use_dma)
- dev_info(&dev->pdev->dev, "FIFO mode\n");
+ dev_info(dev->dev, "FIFO mode\n");
DBG(dev, "-------------------------------------------------------\n");
}
@@ -1244,7 +1243,7 @@ finished:
}
/* Empty request queue of an endpoint; caller holds spinlock */
-static void empty_req_queue(struct udc_ep *ep)
+void empty_req_queue(struct udc_ep *ep)
{
struct udc_request *req;
@@ -1256,6 +1255,7 @@ static void empty_req_queue(struct udc_ep *ep)
complete_req(ep, req, -ESHUTDOWN);
}
}
+EXPORT_SYMBOL_GPL(empty_req_queue);
/* Dequeues a request packet, called by gadget driver */
static int udc_dequeue(struct usb_ep *usbep, struct usb_request *usbreq)
@@ -1623,8 +1623,11 @@ static void udc_setup_endpoints(struct udc *dev)
/* Bringup after Connect event, initial bringup to be ready for ep0 events */
static void usb_connect(struct udc *dev)
{
+ /* Return if already connected */
+ if (dev->connected)
+ return;
- dev_info(&dev->pdev->dev, "USB Connect\n");
+ dev_info(dev->dev, "USB Connect\n");
dev->connected = 1;
@@ -1641,8 +1644,11 @@ static void usb_connect(struct udc *dev)
*/
static void usb_disconnect(struct udc *dev)
{
+ /* Return if already disconnected */
+ if (!dev->connected)
+ return;
- dev_info(&dev->pdev->dev, "USB Disconnect\n");
+ dev_info(dev->dev, "USB Disconnect\n");
dev->connected = 0;
@@ -1715,11 +1721,15 @@ static void udc_soft_reset(struct udc *dev)
/* device int. status reset */
writel(UDC_DEV_MSK_DISABLE, &dev->regs->irqsts);
- spin_lock_irqsave(&udc_irq_spinlock, flags);
- writel(AMD_BIT(UDC_DEVCFG_SOFTRESET), &dev->regs->cfg);
- readl(&dev->regs->cfg);
- spin_unlock_irqrestore(&udc_irq_spinlock, flags);
-
+ /* Don't do this for Broadcom UDC since this is a reserved
+ * bit.
+ */
+ if (dev->chiprev != UDC_BCM_REV) {
+ spin_lock_irqsave(&udc_irq_spinlock, flags);
+ writel(AMD_BIT(UDC_DEVCFG_SOFTRESET), &dev->regs->cfg);
+ readl(&dev->regs->cfg);
+ spin_unlock_irqrestore(&udc_irq_spinlock, flags);
+ }
}
/* RDE timer callback to set RDE bit */
@@ -2106,7 +2116,7 @@ static irqreturn_t udc_data_out_isr(struct udc *dev, int ep_ix)
}
/* HE event ? */
if (tmp & AMD_BIT(UDC_EPSTS_HE)) {
- dev_err(&dev->pdev->dev, "HE ep%dout occurred\n", ep->num);
+ dev_err(dev->dev, "HE ep%dout occurred\n", ep->num);
/* clear HE */
writel(tmp | AMD_BIT(UDC_EPSTS_HE), &ep->regs->sts);
@@ -2305,7 +2315,7 @@ static irqreturn_t udc_data_in_isr(struct udc *dev, int ep_ix)
if (use_dma) {
/* BNA ? */
if (epsts & AMD_BIT(UDC_EPSTS_BNA)) {
- dev_err(&dev->pdev->dev,
+ dev_err(dev->dev,
"BNA ep%din occurred - DESPTR = %08lx\n",
ep->num,
(unsigned long) readl(&ep->regs->desptr));
@@ -2318,7 +2328,7 @@ static irqreturn_t udc_data_in_isr(struct udc *dev, int ep_ix)
}
/* HE event ? */
if (epsts & AMD_BIT(UDC_EPSTS_HE)) {
- dev_err(&dev->pdev->dev,
+ dev_err(dev->dev,
"HE ep%dn occurred - DESPTR = %08lx\n",
ep->num, (unsigned long) readl(&ep->regs->desptr));
@@ -2956,7 +2966,7 @@ __acquires(dev->lock)
/* link up all endpoints */
udc_setup_endpoints(dev);
- dev_info(&dev->pdev->dev, "Connect: %s\n",
+ dev_info(dev->dev, "Connect: %s\n",
usb_speed_string(dev->gadget.speed));
/* init ep 0 */
@@ -3097,7 +3107,7 @@ int init_dma_pools(struct udc *dev)
}
/* DMA setup */
- dev->data_requests = dma_pool_create("data_requests", NULL,
+ dev->data_requests = dma_pool_create("data_requests", dev->dev,
sizeof(struct udc_data_dma), 0, 0);
if (!dev->data_requests) {
DBG(dev, "can't get request data pool\n");
@@ -3108,7 +3118,7 @@ int init_dma_pools(struct udc *dev)
dev->ep[UDC_EP0IN_IX].dma = &dev->regs->ctl;
/* dma desc for setup data */
- dev->stp_requests = dma_pool_create("setup requests", NULL,
+ dev->stp_requests = dma_pool_create("setup requests", dev->dev,
sizeof(struct udc_stp_dma), 0, 0);
if (!dev->stp_requests) {
DBG(dev, "can't get stp request pool\n");
@@ -3168,24 +3178,30 @@ int udc_probe(struct udc *dev)
/* init registers, interrupts, ... */
startup_registers(dev);
- dev_info(&dev->pdev->dev, "%s\n", mod_desc);
+ dev_info(dev->dev, "%s\n", mod_desc);
snprintf(tmp, sizeof(tmp), "%d", dev->irq);
- dev_info(&dev->pdev->dev,
- "irq %s, pci mem %08lx, chip rev %02x(Geode5536 %s)\n",
- tmp, dev->phys_addr, dev->chiprev,
- (dev->chiprev == UDC_HSA0_REV) ? "A0" : "B1");
- strcpy(tmp, UDC_DRIVER_VERSION_STRING);
- if (dev->chiprev == UDC_HSA0_REV) {
- dev_err(&dev->pdev->dev, "chip revision is A0; too old\n");
- retval = -ENODEV;
- goto finished;
+
+ /* Print this device info for AMD chips only*/
+ if (dev->chiprev == UDC_HSA0_REV ||
+ dev->chiprev == UDC_HSB1_REV) {
+ dev_info(dev->dev, "irq %s, pci mem %08lx, chip rev %02x(Geode5536 %s)\n",
+ tmp, dev->phys_addr, dev->chiprev,
+ (dev->chiprev == UDC_HSA0_REV) ?
+ "A0" : "B1");
+ strcpy(tmp, UDC_DRIVER_VERSION_STRING);
+ if (dev->chiprev == UDC_HSA0_REV) {
+ dev_err(dev->dev, "chip revision is A0; too old\n");
+ retval = -ENODEV;
+ goto finished;
+ }
+ dev_info(dev->dev,
+ "driver version: %s(for Geode5536 B1)\n", tmp);
}
- dev_info(&dev->pdev->dev,
- "driver version: %s(for Geode5536 B1)\n", tmp);
+
udc = dev;
- retval = usb_add_gadget_udc_release(&udc->pdev->dev, &dev->gadget,
+ retval = usb_add_gadget_udc_release(udc->dev, &dev->gadget,
gadget_release);
if (retval)
goto finished;
diff --git a/drivers/usb/gadget/udc/snps_udc_plat.c b/drivers/usb/gadget/udc/snps_udc_plat.c
new file mode 100644
index 000000000000..2e11f19e07ae
--- /dev/null
+++ b/drivers/usb/gadget/udc/snps_udc_plat.c
@@ -0,0 +1,344 @@
+/*
+ * snps_udc_plat.c - Synopsys UDC Platform Driver
+ *
+ * Copyright (C) 2016 Broadcom
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation version 2.
+ *
+ * This program is distributed "as is" WITHOUT ANY WARRANTY of any
+ * kind, whether express or implied; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/extcon.h>
+#include <linux/of_address.h>
+#include <linux/of_irq.h>
+#include <linux/of_gpio.h>
+#include <linux/platform_device.h>
+#include <linux/phy/phy.h>
+#include <linux/module.h>
+#include <linux/dmapool.h>
+#include <linux/interrupt.h>
+#include <linux/moduleparam.h>
+#include "amd5536udc.h"
+
+/* description */
+#define UDC_MOD_DESCRIPTION "Synopsys UDC platform driver"
+
+void start_udc(struct udc *udc)
+{
+ if (udc->driver) {
+ dev_info(udc->dev, "Connecting...\n");
+ udc_enable_dev_setup_interrupts(udc);
+ udc_basic_init(udc);
+ udc->connected = 1;
+ }
+}
+
+void stop_udc(struct udc *udc)
+{
+ int tmp;
+ u32 reg;
+
+ spin_lock(&udc->lock);
+
+ /* Flush the receieve fifo */
+ reg = readl(&udc->regs->ctl);
+ reg |= AMD_BIT(UDC_DEVCTL_SRX_FLUSH);
+ writel(reg, &udc->regs->ctl);
+
+ reg = readl(&udc->regs->ctl);
+ reg &= ~(AMD_BIT(UDC_DEVCTL_SRX_FLUSH));
+ writel(reg, &udc->regs->ctl);
+ dev_dbg(udc->dev, "ep rx queue flushed\n");
+
+ /* Mask interrupts. Required more so when the
+ * UDC is connected to a DRD phy.
+ */
+ udc_mask_unused_interrupts(udc);
+
+ /* Disconnect gadget driver */
+ if (udc->driver) {
+ spin_unlock(&udc->lock);
+ udc->driver->disconnect(&udc->gadget);
+ spin_lock(&udc->lock);
+
+ /* empty queues */
+ for (tmp = 0; tmp < UDC_EP_NUM; tmp++)
+ empty_req_queue(&udc->ep[tmp]);
+ }
+ udc->connected = 0;
+
+ spin_unlock(&udc->lock);
+ dev_info(udc->dev, "Device disconnected\n");
+}
+
+void udc_drd_work(struct work_struct *work)
+{
+ struct udc *udc;
+
+ udc = container_of(to_delayed_work(work),
+ struct udc, drd_work);
+
+ if (udc->conn_type) {
+ dev_dbg(udc->dev, "idle -> device\n");
+ start_udc(udc);
+ } else {
+ dev_dbg(udc->dev, "device -> idle\n");
+ stop_udc(udc);
+ }
+}
+
+static int usbd_connect_notify(struct notifier_block *self,
+ unsigned long event, void *ptr)
+{
+ struct udc *udc = container_of(self, struct udc, nb);
+
+ dev_dbg(udc->dev, "%s: event: %lu\n", __func__, event);
+
+ udc->conn_type = event;
+
+ schedule_delayed_work(&udc->drd_work, 0);
+
+ return NOTIFY_OK;
+}
+
+static int udc_plat_probe(struct platform_device *pdev)
+{
+ struct device *dev = &pdev->dev;
+ struct resource *res;
+ struct udc *udc;
+ int ret;
+
+ udc = devm_kzalloc(dev, sizeof(*udc), GFP_KERNEL);
+ if (!udc)
+ return -ENOMEM;
+
+ spin_lock_init(&udc->lock);
+ udc->dev = dev;
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ udc->virt_addr = devm_ioremap_resource(dev, res);
+ if (IS_ERR(udc->regs))
+ return PTR_ERR(udc->regs);
+
+ /* udc csr registers base */
+ udc->csr = udc->virt_addr + UDC_CSR_ADDR;
+
+ /* dev registers base */
+ udc->regs = udc->virt_addr + UDC_DEVCFG_ADDR;
+
+ /* ep registers base */
+ udc->ep_regs = udc->virt_addr + UDC_EPREGS_ADDR;
+
+ /* fifo's base */
+ udc->rxfifo = (u32 __iomem *)(udc->virt_addr + UDC_RXFIFO_ADDR);
+ udc->txfifo = (u32 __iomem *)(udc->virt_addr + UDC_TXFIFO_ADDR);
+
+ udc->phys_addr = (unsigned long)res->start;
+
+ udc->irq = irq_of_parse_and_map(dev->of_node, 0);
+ if (udc->irq <= 0) {
+ dev_err(dev, "Can't parse and map interrupt\n");
+ return -EINVAL;
+ }
+
+ udc->udc_phy = devm_of_phy_get_by_index(dev, dev->of_node, 0);
+ if (IS_ERR(udc->udc_phy)) {
+ dev_err(dev, "Failed to obtain phy from device tree\n");
+ return PTR_ERR(udc->udc_phy);
+ }
+
+ ret = phy_init(udc->udc_phy);
+ if (ret) {
+ dev_err(dev, "UDC phy init failed");
+ return ret;
+ }
+
+ ret = phy_power_on(udc->udc_phy);
+ if (ret) {
+ dev_err(dev, "UDC phy power on failed");
+ phy_exit(udc->udc_phy);
+ return ret;
+ }
+
+ /* Register for extcon if supported */
+ if (of_get_property(dev->of_node, "extcon", NULL)) {
+ udc->edev = extcon_get_edev_by_phandle(dev, 0);
+ if (IS_ERR(udc->edev)) {
+ if (PTR_ERR(udc->edev) == -EPROBE_DEFER)
+ return -EPROBE_DEFER;
+ dev_err(dev, "Invalid or missing extcon\n");
+ ret = PTR_ERR(udc->edev);
+ goto exit_phy;
+ }
+
+ udc->nb.notifier_call = usbd_connect_notify;
+ ret = extcon_register_notifier(udc->edev, EXTCON_USB,
+ &udc->nb);
+ if (ret < 0) {
+ dev_err(dev, "Can't register extcon device\n");
+ goto exit_phy;
+ }
+
+ ret = extcon_get_cable_state_(udc->edev, EXTCON_USB);
+ if (ret < 0) {
+ dev_err(dev, "Can't get cable state\n");
+ goto exit_extcon;
+ } else if (ret) {
+ udc->conn_type = ret;
+ }
+ INIT_DELAYED_WORK(&udc->drd_work, udc_drd_work);
+ }
+
+ /* init dma pools */
+ if (use_dma) {
+ ret = init_dma_pools(udc);
+ if (ret != 0)
+ goto exit_extcon;
+ }
+
+ ret = devm_request_irq(dev, udc->irq, udc_irq, IRQF_SHARED,
+ "snps-udc", udc);
+ if (ret < 0) {
+ dev_err(dev, "Request irq %d failed for UDC\n", udc->irq);
+ goto exit_dma;
+ }
+
+ platform_set_drvdata(pdev, udc);
+ udc->chiprev = UDC_BCM_REV;
+
+ if (udc_probe(udc)) {
+ ret = -ENODEV;
+ goto exit_dma;
+ }
+ dev_info(dev, "Synopsys UDC platform driver probe successful\n");
+
+ return 0;
+
+exit_dma:
+ if (use_dma)
+ free_dma_pools(udc);
+exit_extcon:
+ if (udc->edev)
+ extcon_unregister_notifier(udc->edev, EXTCON_USB, &udc->nb);
+exit_phy:
+ if (udc->udc_phy) {
+ phy_power_off(udc->udc_phy);
+ phy_exit(udc->udc_phy);
+ }
+ return ret;
+}
+
+static int udc_plat_remove(struct platform_device *pdev)
+{
+ struct udc *dev;
+
+ dev = platform_get_drvdata(pdev);
+
+ usb_del_gadget_udc(&dev->gadget);
+ /* gadget driver must not be registered */
+ if (WARN_ON(dev->driver))
+ return 0;
+
+ /* dma pool cleanup */
+ free_dma_pools(dev);
+
+ udc_remove(dev);
+
+ platform_set_drvdata(pdev, NULL);
+
+ if (dev->drd_wq) {
+ flush_workqueue(dev->drd_wq);
+ destroy_workqueue(dev->drd_wq);
+ }
+
+ phy_power_off(dev->udc_phy);
+ phy_exit(dev->udc_phy);
+ extcon_unregister_notifier(dev->edev, EXTCON_USB, &dev->nb);
+
+ dev_info(&pdev->dev, "Synopsys UDC platform driver removed\n");
+
+ return 0;
+}
+
+#ifdef CONFIG_PM_SLEEP
+static int udc_plat_suspend(struct device *dev)
+{
+ struct udc *udc;
+
+ udc = dev_get_drvdata(dev);
+ stop_udc(udc);
+
+ if (extcon_get_cable_state_(udc->edev, EXTCON_USB) > 0) {
+ dev_dbg(udc->dev, "device -> idle\n");
+ stop_udc(udc);
+ }
+ phy_power_off(udc->udc_phy);
+ phy_exit(udc->udc_phy);
+
+ return 0;
+}
+
+static int udc_plat_resume(struct device *dev)
+{
+ struct udc *udc;
+ int ret;
+
+ udc = dev_get_drvdata(dev);
+
+ ret = phy_init(udc->udc_phy);
+ if (ret) {
+ dev_err(udc->dev, "UDC phy init failure");
+ return ret;
+ }
+
+ ret = phy_power_on(udc->udc_phy);
+ if (ret) {
+ dev_err(udc->dev, "UDC phy power on failure");
+ phy_exit(udc->udc_phy);
+ return ret;
+ }
+
+ if (extcon_get_cable_state_(udc->edev, EXTCON_USB) > 0) {
+ dev_dbg(udc->dev, "idle -> device\n");
+ start_udc(udc);
+ }
+
+ return 0;
+}
+static const struct dev_pm_ops udc_plat_pm_ops = {
+ .suspend = udc_plat_suspend,
+ .resume = udc_plat_resume,
+};
+#endif
+
+#if defined(CONFIG_OF)
+static const struct of_device_id of_udc_match[] = {
+ { .compatible = "brcm,ns2-udc", },
+ { .compatible = "brcm,cygnus-udc", },
+ { .compatible = "brcm,iproc-udc", },
+ { }
+};
+MODULE_DEVICE_TABLE(of, of_udc_match);
+#endif
+
+static struct platform_driver udc_plat_driver = {
+ .probe = udc_plat_probe,
+ .remove = udc_plat_remove,
+ .driver = {
+ .name = "snps-udc-plat",
+ .of_match_table = of_match_ptr(of_udc_match),
+#ifdef CONFIG_PM_SLEEP
+ .pm = &udc_plat_pm_ops,
+#endif
+ },
+};
+module_platform_driver(udc_plat_driver);
+
+MODULE_DESCRIPTION(UDC_MOD_DESCRIPTION);
+MODULE_AUTHOR("Broadcom");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/usb/gadget/udc/udc-xilinx.c b/drivers/usb/gadget/udc/udc-xilinx.c
index 588e2531b8b8..de207a90571e 100644
--- a/drivers/usb/gadget/udc/udc-xilinx.c
+++ b/drivers/usb/gadget/udc/udc-xilinx.c
@@ -1151,7 +1151,7 @@ static int xudc_ep_dequeue(struct usb_ep *_ep, struct usb_request *_req)
break;
}
if (&req->usb_req != _req) {
- spin_unlock_irqrestore(&ep->udc->lock, flags);
+ spin_unlock_irqrestore(&udc->lock, flags);
return -EINVAL;
}
xudc_done(ep, req, -ECONNRESET);
diff --git a/drivers/usb/host/Kconfig b/drivers/usb/host/Kconfig
index ababb91d654a..fa5692dec832 100644
--- a/drivers/usb/host/Kconfig
+++ b/drivers/usb/host/Kconfig
@@ -473,8 +473,12 @@ config USB_OHCI_HCD_AT91
config USB_OHCI_HCD_OMAP3
tristate "OHCI support for OMAP3 and later chips"
depends on (ARCH_OMAP3 || ARCH_OMAP4 || SOC_OMAP5)
+ select USB_OHCI_HCD_PLATFORM
default y
- ---help---
+ help
+ This option is deprecated now and the driver was removed, use
+ USB_OHCI_HCD_PLATFORM instead.
+
Enables support for the on-chip OHCI controller on
OMAP3 and later chips.
@@ -627,7 +631,11 @@ config USB_UHCI_SUPPORT_NON_PCI_HC
config USB_UHCI_PLATFORM
bool
- default y if ARCH_VT8500
+ default y if (ARCH_VT8500 || ARCH_ASPEED)
+
+config USB_UHCI_ASPEED
+ bool
+ default y if ARCH_ASPEED
config USB_UHCI_BIG_ENDIAN_MMIO
bool
diff --git a/drivers/usb/host/Makefile b/drivers/usb/host/Makefile
index c77b0a38557b..cf2691fffcc0 100644
--- a/drivers/usb/host/Makefile
+++ b/drivers/usb/host/Makefile
@@ -52,7 +52,6 @@ obj-$(CONFIG_USB_OHCI_HCD_PCI) += ohci-pci.o
obj-$(CONFIG_USB_OHCI_HCD_PLATFORM) += ohci-platform.o
obj-$(CONFIG_USB_OHCI_EXYNOS) += ohci-exynos.o
obj-$(CONFIG_USB_OHCI_HCD_OMAP1) += ohci-omap.o
-obj-$(CONFIG_USB_OHCI_HCD_OMAP3) += ohci-omap3.o
obj-$(CONFIG_USB_OHCI_HCD_SPEAR) += ohci-spear.o
obj-$(CONFIG_USB_OHCI_HCD_STI) += ohci-st.o
obj-$(CONFIG_USB_OHCI_HCD_AT91) += ohci-at91.o
diff --git a/drivers/usb/host/ehci-exynos.c b/drivers/usb/host/ehci-exynos.c
index 7a603f66a9bc..26b641100639 100644
--- a/drivers/usb/host/ehci-exynos.c
+++ b/drivers/usb/host/ehci-exynos.c
@@ -279,7 +279,9 @@ static int exynos_ehci_resume(struct device *dev)
struct exynos_ehci_hcd *exynos_ehci = to_exynos_ehci(hcd);
int ret;
- clk_prepare_enable(exynos_ehci->clk);
+ ret = clk_prepare_enable(exynos_ehci->clk);
+ if (ret)
+ return ret;
ret = exynos_ehci_phy_enable(dev);
if (ret) {
diff --git a/drivers/usb/host/ehci-sched.c b/drivers/usb/host/ehci-sched.c
index 980a6b3b2da2..6bc6304672bc 100644
--- a/drivers/usb/host/ehci-sched.c
+++ b/drivers/usb/host/ehci-sched.c
@@ -1105,7 +1105,7 @@ iso_stream_init(
addr |= epnum << 8;
addr |= dev->devnum;
stream->ps.usecs = HS_USECS_ISO(maxp);
- think_time = dev->tt ? dev->tt->think_time : 0;
+ think_time = dev->tt->think_time;
stream->ps.tt_usecs = NS_TO_US(think_time + usb_calc_bus_time(
dev->speed, is_input, 1, maxp));
hs_transfers = max(1u, (maxp + 187) / 188);
diff --git a/drivers/usb/host/ehci-timer.c b/drivers/usb/host/ehci-timer.c
index 3893b5bafd87..0b6cdb723192 100644
--- a/drivers/usb/host/ehci-timer.c
+++ b/drivers/usb/host/ehci-timer.c
@@ -424,7 +424,7 @@ static enum hrtimer_restart ehci_hrtimer_func(struct hrtimer *t)
*/
now = ktime_get();
for_each_set_bit(e, &events, EHCI_HRTIMER_NUM_EVENTS) {
- if (now >= ehci->hr_timeouts[e])
+ if (ktime_compare(now, ehci->hr_timeouts[e]) >= 0)
event_handlers[e](ehci);
else
ehci_enable_event(ehci, e, false);
diff --git a/drivers/usb/host/fotg210-hcd.c b/drivers/usb/host/fotg210-hcd.c
index ced08dc229ad..457cc6525abd 100644
--- a/drivers/usb/host/fotg210-hcd.c
+++ b/drivers/usb/host/fotg210-hcd.c
@@ -1380,7 +1380,7 @@ static enum hrtimer_restart fotg210_hrtimer_func(struct hrtimer *t)
*/
now = ktime_get();
for_each_set_bit(e, &events, FOTG210_HRTIMER_NUM_EVENTS) {
- if (now >= fotg210->hr_timeouts[e])
+ if (ktime_compare(now, fotg210->hr_timeouts[e]) >= 0)
event_handlers[e](fotg210);
else
fotg210_enable_event(fotg210, e, false);
diff --git a/drivers/usb/host/ohci-omap3.c b/drivers/usb/host/ohci-omap3.c
deleted file mode 100644
index ec15aebe8786..000000000000
--- a/drivers/usb/host/ohci-omap3.c
+++ /dev/null
@@ -1,211 +0,0 @@
-/*
- * ohci-omap3.c - driver for OHCI on OMAP3 and later processors
- *
- * Bus Glue for OMAP3 USBHOST 3 port OHCI controller
- * This controller is also used in later OMAPs and AM35x chips
- *
- * Copyright (C) 2007-2010 Texas Instruments, Inc.
- * Author: Vikram Pandita <vikram.pandita@ti.com>
- * Author: Anand Gadiyar <gadiyar@ti.com>
- * Author: Keshava Munegowda <keshava_mgowda@ti.com>
- *
- * Based on ehci-omap.c and some other ohci glue layers
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- *
- * TODO (last updated Feb 27, 2011):
- * - add kernel-doc
- */
-
-#include <linux/dma-mapping.h>
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/of.h>
-#include <linux/usb/otg.h>
-#include <linux/platform_device.h>
-#include <linux/pm_runtime.h>
-#include <linux/usb.h>
-#include <linux/usb/hcd.h>
-
-#include "ohci.h"
-
-#define DRIVER_DESC "OHCI OMAP3 driver"
-
-static const char hcd_name[] = "ohci-omap3";
-static struct hc_driver __read_mostly ohci_omap3_hc_driver;
-
-/*
- * configure so an HC device and id are always provided
- * always called with process context; sleeping is OK
- */
-
-/**
- * ohci_hcd_omap3_probe - initialize OMAP-based HCDs
- *
- * Allocates basic resources for this USB host controller, and
- * then invokes the start() method for the HCD associated with it
- * through the hotplug entry's driver_data.
- */
-static int ohci_hcd_omap3_probe(struct platform_device *pdev)
-{
- struct device *dev = &pdev->dev;
- struct ohci_hcd *ohci;
- struct usb_hcd *hcd = NULL;
- void __iomem *regs = NULL;
- struct resource *res;
- int ret;
- int irq;
-
- if (usb_disabled())
- return -ENODEV;
-
- if (!dev->parent) {
- dev_err(dev, "Missing parent device\n");
- return -ENODEV;
- }
-
- irq = platform_get_irq(pdev, 0);
- if (irq < 0) {
- dev_err(dev, "OHCI irq failed\n");
- return -ENODEV;
- }
-
- res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- if (!res) {
- dev_err(dev, "UHH OHCI get resource failed\n");
- return -ENOMEM;
- }
-
- regs = ioremap(res->start, resource_size(res));
- if (!regs) {
- dev_err(dev, "UHH OHCI ioremap failed\n");
- return -ENOMEM;
- }
-
- /*
- * Right now device-tree probed devices don't get dma_mask set.
- * Since shared usb code relies on it, set it here for now.
- * Once we have dma capability bindings this can go away.
- */
- ret = dma_coerce_mask_and_coherent(dev, DMA_BIT_MASK(32));
- if (ret)
- goto err_io;
-
- ret = -ENODEV;
- hcd = usb_create_hcd(&ohci_omap3_hc_driver, dev,
- dev_name(dev));
- if (!hcd) {
- dev_err(dev, "usb_create_hcd failed\n");
- goto err_io;
- }
-
- hcd->rsrc_start = res->start;
- hcd->rsrc_len = resource_size(res);
- hcd->regs = regs;
-
- pm_runtime_enable(dev);
- pm_runtime_get_sync(dev);
-
- ohci = hcd_to_ohci(hcd);
- /*
- * RemoteWakeupConnected has to be set explicitly before
- * calling ohci_run. The reset value of RWC is 0.
- */
- ohci->hc_control = OHCI_CTRL_RWC;
-
- ret = usb_add_hcd(hcd, irq, 0);
- if (ret) {
- dev_dbg(dev, "failed to add hcd with err %d\n", ret);
- goto err_add_hcd;
- }
- device_wakeup_enable(hcd->self.controller);
-
- return 0;
-
-err_add_hcd:
- pm_runtime_put_sync(dev);
- usb_put_hcd(hcd);
-
-err_io:
- iounmap(regs);
-
- return ret;
-}
-
-/*
- * may be called without controller electrically present
- * may be called with controller, bus, and devices active
- */
-
-/**
- * ohci_hcd_omap3_remove - shutdown processing for OHCI HCDs
- * @pdev: USB Host Controller being removed
- *
- * Reverses the effect of ohci_hcd_omap3_probe(), first invoking
- * the HCD's stop() method. It is always called from a thread
- * context, normally "rmmod", "apmd", or something similar.
- */
-static int ohci_hcd_omap3_remove(struct platform_device *pdev)
-{
- struct device *dev = &pdev->dev;
- struct usb_hcd *hcd = dev_get_drvdata(dev);
-
- iounmap(hcd->regs);
- usb_remove_hcd(hcd);
- pm_runtime_put_sync(dev);
- pm_runtime_disable(dev);
- usb_put_hcd(hcd);
- return 0;
-}
-
-static const struct of_device_id omap_ohci_dt_ids[] = {
- { .compatible = "ti,ohci-omap3" },
- { }
-};
-
-MODULE_DEVICE_TABLE(of, omap_ohci_dt_ids);
-
-static struct platform_driver ohci_hcd_omap3_driver = {
- .probe = ohci_hcd_omap3_probe,
- .remove = ohci_hcd_omap3_remove,
- .shutdown = usb_hcd_platform_shutdown,
- .driver = {
- .name = "ohci-omap3",
- .of_match_table = omap_ohci_dt_ids,
- },
-};
-
-static int __init ohci_omap3_init(void)
-{
- if (usb_disabled())
- return -ENODEV;
-
- pr_info("%s: " DRIVER_DESC "\n", hcd_name);
-
- ohci_init_driver(&ohci_omap3_hc_driver, NULL);
- return platform_driver_register(&ohci_hcd_omap3_driver);
-}
-module_init(ohci_omap3_init);
-
-static void __exit ohci_omap3_cleanup(void)
-{
- platform_driver_unregister(&ohci_hcd_omap3_driver);
-}
-module_exit(ohci_omap3_cleanup);
-
-MODULE_DESCRIPTION(DRIVER_DESC);
-MODULE_ALIAS("platform:ohci-omap3");
-MODULE_AUTHOR("Anand Gadiyar <gadiyar@ti.com>");
-MODULE_LICENSE("GPL");
diff --git a/drivers/usb/host/ohci-platform.c b/drivers/usb/host/ohci-platform.c
index 6368fce43197..61fe2b985070 100644
--- a/drivers/usb/host/ohci-platform.c
+++ b/drivers/usb/host/ohci-platform.c
@@ -24,6 +24,7 @@
#include <linux/err.h>
#include <linux/phy/phy.h>
#include <linux/platform_device.h>
+#include <linux/pm_runtime.h>
#include <linux/reset.h>
#include <linux/usb/ohci_pdriver.h>
#include <linux/usb.h>
@@ -163,6 +164,10 @@ static int ohci_platform_probe(struct platform_device *dev)
if (of_property_read_bool(dev->dev.of_node, "no-big-frame-no"))
ohci->flags |= OHCI_QUIRK_FRAME_NO;
+ if (of_property_read_bool(dev->dev.of_node,
+ "remote-wakeup-connected"))
+ ohci->hc_control = OHCI_CTRL_RWC;
+
of_property_read_u32(dev->dev.of_node, "num-ports",
&ohci->num_ports);
@@ -242,6 +247,8 @@ static int ohci_platform_probe(struct platform_device *dev)
}
#endif
+ pm_runtime_set_active(&dev->dev);
+ pm_runtime_enable(&dev->dev);
if (pdata->power_on) {
err = pdata->power_on(dev);
if (err < 0)
@@ -271,6 +278,7 @@ err_power:
if (pdata->power_off)
pdata->power_off(dev);
err_reset:
+ pm_runtime_disable(&dev->dev);
while (--rst >= 0)
reset_control_assert(priv->resets[rst]);
err_put_clks:
@@ -292,6 +300,7 @@ static int ohci_platform_remove(struct platform_device *dev)
struct ohci_platform_priv *priv = hcd_to_ohci_priv(hcd);
int clk, rst;
+ pm_runtime_get_sync(&dev->dev);
usb_remove_hcd(hcd);
if (pdata->power_off)
@@ -305,6 +314,9 @@ static int ohci_platform_remove(struct platform_device *dev)
usb_put_hcd(hcd);
+ pm_runtime_put_sync(&dev->dev);
+ pm_runtime_disable(&dev->dev);
+
if (pdata == &ohci_platform_defaults)
dev->dev.platform_data = NULL;
@@ -350,6 +362,7 @@ static int ohci_platform_resume(struct device *dev)
static const struct of_device_id ohci_platform_ids[] = {
{ .compatible = "generic-ohci", },
{ .compatible = "cavium,octeon-6335-ohci", },
+ { .compatible = "ti,ohci-omap3", },
{ }
};
MODULE_DEVICE_TABLE(of, ohci_platform_ids);
diff --git a/drivers/usb/host/ohci-pxa27x.c b/drivers/usb/host/ohci-pxa27x.c
index 79efde8f21e0..21c010ffb03c 100644
--- a/drivers/usb/host/ohci-pxa27x.c
+++ b/drivers/usb/host/ohci-pxa27x.c
@@ -274,14 +274,16 @@ extern void pxa27x_clear_otgph(void);
static int pxa27x_start_hc(struct pxa27x_ohci *pxa_ohci, struct device *dev)
{
- int retval = 0;
+ int retval;
struct pxaohci_platform_data *inf;
uint32_t uhchr;
struct usb_hcd *hcd = dev_get_drvdata(dev);
inf = dev_get_platdata(dev);
- clk_prepare_enable(pxa_ohci->clk);
+ retval = clk_prepare_enable(pxa_ohci->clk);
+ if (retval)
+ return retval;
pxa27x_reset_hc(pxa_ohci);
@@ -296,8 +298,10 @@ static int pxa27x_start_hc(struct pxa27x_ohci *pxa_ohci, struct device *dev)
if (inf->init)
retval = inf->init(dev);
- if (retval < 0)
+ if (retval < 0) {
+ clk_disable_unprepare(pxa_ohci->clk);
return retval;
+ }
if (cpu_is_pxa3xx())
pxa3xx_u2d_start_hc(&hcd->self);
diff --git a/drivers/usb/host/uhci-hcd.c b/drivers/usb/host/uhci-hcd.c
index 94b150196d4f..c3267a78c94e 100644
--- a/drivers/usb/host/uhci-hcd.c
+++ b/drivers/usb/host/uhci-hcd.c
@@ -265,9 +265,13 @@ static void configure_hc(struct uhci_hcd *uhci)
static int resume_detect_interrupts_are_broken(struct uhci_hcd *uhci)
{
- /* If we have to ignore overcurrent events then almost by definition
- * we can't depend on resume-detect interrupts. */
- if (ignore_oc)
+ /*
+ * If we have to ignore overcurrent events then almost by definition
+ * we can't depend on resume-detect interrupts.
+ *
+ * Those interrupts also don't seem to work on ASpeed SoCs.
+ */
+ if (ignore_oc || uhci_is_aspeed(uhci))
return 1;
return uhci->resume_detect_interrupts_are_broken ?
@@ -384,6 +388,13 @@ static void start_rh(struct uhci_hcd *uhci)
{
uhci->is_stopped = 0;
+ /*
+ * Clear stale status bits on Aspeed as we get a stale HCH
+ * which causes problems later on
+ */
+ if (uhci_is_aspeed(uhci))
+ uhci_writew(uhci, uhci_readw(uhci, USBSTS), USBSTS);
+
/* Mark it configured and running with a 64-byte max packet.
* All interrupts are enabled, even though RESUME won't do anything.
*/
diff --git a/drivers/usb/host/uhci-hcd.h b/drivers/usb/host/uhci-hcd.h
index 7fa318a3091d..91b22b2ea3aa 100644
--- a/drivers/usb/host/uhci-hcd.h
+++ b/drivers/usb/host/uhci-hcd.h
@@ -48,6 +48,8 @@
/* USB port status and control registers */
#define USBPORTSC1 16
#define USBPORTSC2 18
+#define USBPORTSC3 20
+#define USBPORTSC4 22
#define USBPORTSC_CCS 0x0001 /* Current Connect Status
* ("device present") */
#define USBPORTSC_CSC 0x0002 /* Connect Status Change */
@@ -427,6 +429,7 @@ struct uhci_hcd {
unsigned int wait_for_hp:1; /* Wait for HP port reset */
unsigned int big_endian_mmio:1; /* Big endian registers */
unsigned int big_endian_desc:1; /* Big endian descriptors */
+ unsigned int is_aspeed:1; /* Aspeed impl. workarounds */
/* Support for port suspend/resume/reset */
unsigned long port_c_suspend; /* Bit-arrays of ports */
@@ -490,6 +493,12 @@ struct urb_priv {
#define PCI_VENDOR_ID_GENESYS 0x17a0
#define PCI_DEVICE_ID_GL880S_UHCI 0x8083
+/* Aspeed SoC needs some quirks */
+static inline bool uhci_is_aspeed(const struct uhci_hcd *uhci)
+{
+ return IS_ENABLED(CONFIG_USB_UHCI_ASPEED) && uhci->is_aspeed;
+}
+
/*
* Functions used to access controller registers. The UCHI spec says that host
* controller I/O registers are mapped into PCI I/O space. For non-PCI hosts
@@ -545,10 +554,42 @@ static inline void uhci_writeb(const struct uhci_hcd *uhci, u8 val, int reg)
#define uhci_big_endian_mmio(u) 0
#endif
+static inline int uhci_aspeed_reg(unsigned int reg)
+{
+ switch (reg) {
+ case USBCMD:
+ return 00;
+ case USBSTS:
+ return 0x04;
+ case USBINTR:
+ return 0x08;
+ case USBFRNUM:
+ return 0x80;
+ case USBFLBASEADD:
+ return 0x0c;
+ case USBSOF:
+ return 0x84;
+ case USBPORTSC1:
+ return 0x88;
+ case USBPORTSC2:
+ return 0x8c;
+ case USBPORTSC3:
+ return 0x90;
+ case USBPORTSC4:
+ return 0x94;
+ default:
+ pr_warn("UHCI: Unsupported register 0x%02x on Aspeed\n", reg);
+ /* Return an unimplemented register */
+ return 0x10;
+ }
+}
+
static inline u32 uhci_readl(const struct uhci_hcd *uhci, int reg)
{
if (uhci_has_pci_registers(uhci))
return inl(uhci->io_addr + reg);
+ else if (uhci_is_aspeed(uhci))
+ return readl(uhci->regs + uhci_aspeed_reg(reg));
#ifdef CONFIG_USB_UHCI_BIG_ENDIAN_MMIO
else if (uhci_big_endian_mmio(uhci))
return readl_be(uhci->regs + reg);
@@ -561,6 +602,8 @@ static inline void uhci_writel(const struct uhci_hcd *uhci, u32 val, int reg)
{
if (uhci_has_pci_registers(uhci))
outl(val, uhci->io_addr + reg);
+ else if (uhci_is_aspeed(uhci))
+ writel(val, uhci->regs + uhci_aspeed_reg(reg));
#ifdef CONFIG_USB_UHCI_BIG_ENDIAN_MMIO
else if (uhci_big_endian_mmio(uhci))
writel_be(val, uhci->regs + reg);
@@ -573,6 +616,8 @@ static inline u16 uhci_readw(const struct uhci_hcd *uhci, int reg)
{
if (uhci_has_pci_registers(uhci))
return inw(uhci->io_addr + reg);
+ else if (uhci_is_aspeed(uhci))
+ return readl(uhci->regs + uhci_aspeed_reg(reg));
#ifdef CONFIG_USB_UHCI_BIG_ENDIAN_MMIO
else if (uhci_big_endian_mmio(uhci))
return readw_be(uhci->regs + reg);
@@ -585,6 +630,8 @@ static inline void uhci_writew(const struct uhci_hcd *uhci, u16 val, int reg)
{
if (uhci_has_pci_registers(uhci))
outw(val, uhci->io_addr + reg);
+ else if (uhci_is_aspeed(uhci))
+ writel(val, uhci->regs + uhci_aspeed_reg(reg));
#ifdef CONFIG_USB_UHCI_BIG_ENDIAN_MMIO
else if (uhci_big_endian_mmio(uhci))
writew_be(val, uhci->regs + reg);
@@ -597,6 +644,8 @@ static inline u8 uhci_readb(const struct uhci_hcd *uhci, int reg)
{
if (uhci_has_pci_registers(uhci))
return inb(uhci->io_addr + reg);
+ else if (uhci_is_aspeed(uhci))
+ return readl(uhci->regs + uhci_aspeed_reg(reg));
#ifdef CONFIG_USB_UHCI_BIG_ENDIAN_MMIO
else if (uhci_big_endian_mmio(uhci))
return readb_be(uhci->regs + reg);
@@ -609,6 +658,8 @@ static inline void uhci_writeb(const struct uhci_hcd *uhci, u8 val, int reg)
{
if (uhci_has_pci_registers(uhci))
outb(val, uhci->io_addr + reg);
+ else if (uhci_is_aspeed(uhci))
+ writel(val, uhci->regs + uhci_aspeed_reg(reg));
#ifdef CONFIG_USB_UHCI_BIG_ENDIAN_MMIO
else if (uhci_big_endian_mmio(uhci))
writeb_be(val, uhci->regs + reg);
diff --git a/drivers/usb/host/uhci-platform.c b/drivers/usb/host/uhci-platform.c
index 32a6f3d8deec..1b4e086c33a0 100644
--- a/drivers/usb/host/uhci-platform.c
+++ b/drivers/usb/host/uhci-platform.c
@@ -15,7 +15,9 @@ static int uhci_platform_init(struct usb_hcd *hcd)
{
struct uhci_hcd *uhci = hcd_to_uhci(hcd);
- uhci->rh_numports = uhci_count_ports(hcd);
+ /* Probe number of ports if not already provided by DT */
+ if (!uhci->rh_numports)
+ uhci->rh_numports = uhci_count_ports(hcd);
/* Set up pointers to to generic functions */
uhci->reset_hc = uhci_generic_reset_hc;
@@ -63,6 +65,7 @@ static const struct hc_driver uhci_platform_hc_driver = {
static int uhci_hcd_platform_probe(struct platform_device *pdev)
{
+ struct device_node *np = pdev->dev.of_node;
struct usb_hcd *hcd;
struct uhci_hcd *uhci;
struct resource *res;
@@ -98,6 +101,23 @@ static int uhci_hcd_platform_probe(struct platform_device *pdev)
uhci->regs = hcd->regs;
+ /* Grab some things from the device-tree */
+ if (np) {
+ u32 num_ports;
+
+ if (of_property_read_u32(np, "#ports", &num_ports) == 0) {
+ uhci->rh_numports = num_ports;
+ dev_info(&pdev->dev,
+ "Detected %d ports from device-tree\n",
+ num_ports);
+ }
+ if (of_device_is_compatible(np, "aspeed,ast2400-uhci") ||
+ of_device_is_compatible(np, "aspeed,ast2500-uhci")) {
+ uhci->is_aspeed = 1;
+ dev_info(&pdev->dev,
+ "Enabled Aspeed implementation workarounds\n");
+ }
+ }
ret = usb_add_hcd(hcd, pdev->resource[1].start, IRQF_SHARED);
if (ret)
goto err_rmr;
diff --git a/drivers/usb/host/xhci-mem.c b/drivers/usb/host/xhci-mem.c
index 1f1687e888d6..2a82c927ded2 100644
--- a/drivers/usb/host/xhci-mem.c
+++ b/drivers/usb/host/xhci-mem.c
@@ -407,64 +407,17 @@ fail:
return NULL;
}
-void xhci_free_or_cache_endpoint_ring(struct xhci_hcd *xhci,
+void xhci_free_endpoint_ring(struct xhci_hcd *xhci,
struct xhci_virt_device *virt_dev,
unsigned int ep_index)
{
- int rings_cached;
-
- rings_cached = virt_dev->num_rings_cached;
- if (rings_cached < XHCI_MAX_RINGS_CACHED) {
- virt_dev->ring_cache[rings_cached] =
- virt_dev->eps[ep_index].ring;
- virt_dev->num_rings_cached++;
- xhci_dbg(xhci, "Cached old ring, "
- "%d ring%s cached\n",
- virt_dev->num_rings_cached,
- (virt_dev->num_rings_cached > 1) ? "s" : "");
- } else {
- xhci_ring_free(xhci, virt_dev->eps[ep_index].ring);
- xhci_dbg(xhci, "Ring cache full (%d rings), "
- "freeing ring\n",
- virt_dev->num_rings_cached);
- }
+ xhci_ring_free(xhci, virt_dev->eps[ep_index].ring);
virt_dev->eps[ep_index].ring = NULL;
}
-/* Zero an endpoint ring (except for link TRBs) and move the enqueue and dequeue
- * pointers to the beginning of the ring.
- */
-static void xhci_reinit_cached_ring(struct xhci_hcd *xhci,
- struct xhci_ring *ring, unsigned int cycle_state,
- enum xhci_ring_type type)
-{
- struct xhci_segment *seg = ring->first_seg;
- int i;
-
- do {
- memset(seg->trbs, 0,
- sizeof(union xhci_trb)*TRBS_PER_SEGMENT);
- if (cycle_state == 0) {
- for (i = 0; i < TRBS_PER_SEGMENT; i++)
- seg->trbs[i].link.control |=
- cpu_to_le32(TRB_CYCLE);
- }
- /* All endpoint rings have link TRBs */
- xhci_link_segments(xhci, seg, seg->next, type);
- seg = seg->next;
- } while (seg != ring->first_seg);
- ring->type = type;
- xhci_initialize_ring_info(ring, cycle_state);
- /* td list should be empty since all URBs have been cancelled,
- * but just in case...
- */
- INIT_LIST_HEAD(&ring->td_list);
-}
-
/*
* Expand an existing ring.
- * Look for a cached ring or allocate a new ring which has same segment numbers
- * and link the two rings.
+ * Allocate a new ring which has same segment numbers and link the two rings.
*/
int xhci_ring_expansion(struct xhci_hcd *xhci, struct xhci_ring *ring,
unsigned int num_trbs, gfp_t flags)
@@ -968,12 +921,6 @@ void xhci_free_virt_device(struct xhci_hcd *xhci, int slot_id)
/* If necessary, update the number of active TTs on this root port */
xhci_update_tt_active_eps(xhci, dev, old_active_eps);
- if (dev->ring_cache) {
- for (i = 0; i < dev->num_rings_cached; i++)
- xhci_ring_free(xhci, dev->ring_cache[i]);
- kfree(dev->ring_cache);
- }
-
if (dev->in_ctx)
xhci_free_container_ctx(xhci, dev->in_ctx);
if (dev->out_ctx)
@@ -1062,14 +1009,6 @@ int xhci_alloc_virt_device(struct xhci_hcd *xhci, int slot_id,
if (!dev->eps[0].ring)
goto fail;
- /* Allocate pointers to the ring cache */
- dev->ring_cache = kzalloc(
- sizeof(struct xhci_ring *)*XHCI_MAX_RINGS_CACHED,
- flags);
- if (!dev->ring_cache)
- goto fail;
- dev->num_rings_cached = 0;
-
dev->udev = udev;
/* Point to output device context in dcbaa. */
@@ -1537,17 +1476,9 @@ int xhci_endpoint_init(struct xhci_hcd *xhci,
/* Set up the endpoint ring */
virt_dev->eps[ep_index].new_ring =
xhci_ring_alloc(xhci, 2, 1, ring_type, max_packet, mem_flags);
- if (!virt_dev->eps[ep_index].new_ring) {
- /* Attempt to use the ring cache */
- if (virt_dev->num_rings_cached == 0)
- return -ENOMEM;
- virt_dev->num_rings_cached--;
- virt_dev->eps[ep_index].new_ring =
- virt_dev->ring_cache[virt_dev->num_rings_cached];
- virt_dev->ring_cache[virt_dev->num_rings_cached] = NULL;
- xhci_reinit_cached_ring(xhci, virt_dev->eps[ep_index].new_ring,
- 1, ring_type);
- }
+ if (!virt_dev->eps[ep_index].new_ring)
+ return -ENOMEM;
+
virt_dev->eps[ep_index].skip = false;
ep_ring = virt_dev->eps[ep_index].new_ring;
@@ -2119,11 +2050,12 @@ static void xhci_add_in_port(struct xhci_hcd *xhci, unsigned int num_ports,
{
u32 temp, port_offset, port_count;
int i;
- u8 major_revision;
+ u8 major_revision, minor_revision;
struct xhci_hub *rhub;
temp = readl(addr);
major_revision = XHCI_EXT_PORT_MAJOR(temp);
+ minor_revision = XHCI_EXT_PORT_MINOR(temp);
if (major_revision == 0x03) {
rhub = &xhci->usb3_rhub;
@@ -2137,7 +2069,9 @@ static void xhci_add_in_port(struct xhci_hcd *xhci, unsigned int num_ports,
return;
}
rhub->maj_rev = XHCI_EXT_PORT_MAJOR(temp);
- rhub->min_rev = XHCI_EXT_PORT_MINOR(temp);
+
+ if (rhub->min_rev < minor_revision)
+ rhub->min_rev = minor_revision;
/* Port offset and count in the third dword, see section 7.2 */
temp = readl(addr + 2);
diff --git a/drivers/usb/host/xhci-pci.c b/drivers/usb/host/xhci-pci.c
index fcf1f3f63e7a..783e6687bf4a 100644
--- a/drivers/usb/host/xhci-pci.c
+++ b/drivers/usb/host/xhci-pci.c
@@ -201,6 +201,9 @@ static void xhci_pci_quirks(struct device *dev, struct xhci_hcd *xhci)
if (pdev->vendor == PCI_VENDOR_ID_ASMEDIA &&
pdev->device == 0x1042)
xhci->quirks |= XHCI_BROKEN_STREAMS;
+ if (pdev->vendor == PCI_VENDOR_ID_ASMEDIA &&
+ pdev->device == 0x1142)
+ xhci->quirks |= XHCI_TRUST_TX_LENGTH;
if (pdev->vendor == PCI_VENDOR_ID_TI && pdev->device == 0x8241)
xhci->quirks |= XHCI_LIMIT_ENDPOINT_INTERVAL_7;
@@ -213,13 +216,12 @@ static void xhci_pci_quirks(struct device *dev, struct xhci_hcd *xhci)
#ifdef CONFIG_ACPI
static void xhci_pme_acpi_rtd3_enable(struct pci_dev *dev)
{
- static const u8 intel_dsm_uuid[] = {
- 0xb7, 0x0c, 0x34, 0xac, 0x01, 0xe9, 0xbf, 0x45,
- 0xb7, 0xe6, 0x2b, 0x34, 0xec, 0x93, 0x1e, 0x23,
- };
+ static const guid_t intel_dsm_guid =
+ GUID_INIT(0xac340cb7, 0xe901, 0x45bf,
+ 0xb7, 0xe6, 0x2b, 0x34, 0xec, 0x93, 0x1e, 0x23);
union acpi_object *obj;
- obj = acpi_evaluate_dsm(ACPI_HANDLE(&dev->dev), intel_dsm_uuid, 3, 1,
+ obj = acpi_evaluate_dsm(ACPI_HANDLE(&dev->dev), &intel_dsm_guid, 3, 1,
NULL);
ACPI_FREE(obj);
}
diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c
index 03f63f50afb6..c50c902d009e 100644
--- a/drivers/usb/host/xhci-ring.c
+++ b/drivers/usb/host/xhci-ring.c
@@ -480,10 +480,34 @@ struct xhci_ring *xhci_triad_to_transfer_ring(struct xhci_hcd *xhci,
return NULL;
}
+
+/*
+ * Get the hw dequeue pointer xHC stopped on, either directly from the
+ * endpoint context, or if streams are in use from the stream context.
+ * The returned hw_dequeue contains the lowest four bits with cycle state
+ * and possbile stream context type.
+ */
+static u64 xhci_get_hw_deq(struct xhci_hcd *xhci, struct xhci_virt_device *vdev,
+ unsigned int ep_index, unsigned int stream_id)
+{
+ struct xhci_ep_ctx *ep_ctx;
+ struct xhci_stream_ctx *st_ctx;
+ struct xhci_virt_ep *ep;
+
+ ep = &vdev->eps[ep_index];
+
+ if (ep->ep_state & EP_HAS_STREAMS) {
+ st_ctx = &ep->stream_info->stream_ctx_array[stream_id];
+ return le64_to_cpu(st_ctx->stream_ring);
+ }
+ ep_ctx = xhci_get_ep_ctx(xhci, vdev->out_ctx, ep_index);
+ return le64_to_cpu(ep_ctx->deq);
+}
+
/*
* Move the xHC's endpoint ring dequeue pointer past cur_td.
* Record the new state of the xHC's endpoint ring dequeue segment,
- * dequeue pointer, and new consumer cycle state in state.
+ * dequeue pointer, stream id, and new consumer cycle state in state.
* Update our internal representation of the ring's dequeue pointer.
*
* We do this in three jumps:
@@ -521,24 +545,15 @@ void xhci_find_new_dequeue_state(struct xhci_hcd *xhci,
stream_id);
return;
}
-
/* Dig out the cycle state saved by the xHC during the stop ep cmd */
xhci_dbg_trace(xhci, trace_xhci_dbg_cancel_urb,
"Finding endpoint context");
- /* 4.6.9 the css flag is written to the stream context for streams */
- if (ep->ep_state & EP_HAS_STREAMS) {
- struct xhci_stream_ctx *ctx =
- &ep->stream_info->stream_ctx_array[stream_id];
- hw_dequeue = le64_to_cpu(ctx->stream_ring);
- } else {
- struct xhci_ep_ctx *ep_ctx
- = xhci_get_ep_ctx(xhci, dev->out_ctx, ep_index);
- hw_dequeue = le64_to_cpu(ep_ctx->deq);
- }
+ hw_dequeue = xhci_get_hw_deq(xhci, dev, ep_index, stream_id);
new_seg = ep_ring->deq_seg;
new_deq = ep_ring->dequeue;
state->new_cycle_state = hw_dequeue & 0x1;
+ state->stream_id = stream_id;
/*
* We want to find the pointer, segment and cycle state of the new trb
@@ -691,7 +706,7 @@ static void xhci_handle_cmd_stop_ep(struct xhci_hcd *xhci, int slot_id,
struct xhci_td *last_unlinked_td;
struct xhci_ep_ctx *ep_ctx;
struct xhci_virt_device *vdev;
-
+ u64 hw_deq;
struct xhci_dequeue_state deq_state;
if (unlikely(TRB_TO_SUSPEND_PORT(le32_to_cpu(trb->generic.field[3])))) {
@@ -715,7 +730,6 @@ static void xhci_handle_cmd_stop_ep(struct xhci_hcd *xhci, int slot_id,
if (list_empty(&ep->cancelled_td_list)) {
xhci_stop_watchdog_timer_in_irq(xhci, ep);
- ep->stopped_td = NULL;
ring_doorbell_for_active_rings(xhci, slot_id, ep_index);
return;
}
@@ -753,12 +767,19 @@ static void xhci_handle_cmd_stop_ep(struct xhci_hcd *xhci, int slot_id,
* If we stopped on the TD we need to cancel, then we have to
* move the xHC endpoint ring dequeue pointer past this TD.
*/
- if (cur_td == ep->stopped_td)
+ hw_deq = xhci_get_hw_deq(xhci, vdev, ep_index,
+ cur_td->urb->stream_id);
+ hw_deq &= ~0xf;
+
+ if (trb_in_td(xhci, cur_td->start_seg, cur_td->first_trb,
+ cur_td->last_trb, hw_deq, false)) {
xhci_find_new_dequeue_state(xhci, slot_id, ep_index,
- cur_td->urb->stream_id,
- cur_td, &deq_state);
- else
+ cur_td->urb->stream_id,
+ cur_td, &deq_state);
+ } else {
td_to_noop(xhci, ep_ring, cur_td, false);
+ }
+
remove_finished_td:
/*
* The event handler won't see a completion for this TD anymore,
@@ -773,15 +794,13 @@ remove_finished_td:
/* If necessary, queue a Set Transfer Ring Dequeue Pointer command */
if (deq_state.new_deq_ptr && deq_state.new_deq_seg) {
xhci_queue_new_dequeue_state(xhci, slot_id, ep_index,
- ep->stopped_td->urb->stream_id, &deq_state);
+ &deq_state);
xhci_ring_cmd_db(xhci);
} else {
/* Otherwise ring the doorbell(s) to restart queued transfers */
ring_doorbell_for_active_rings(xhci, slot_id, ep_index);
}
- ep->stopped_td = NULL;
-
/*
* Drop the lock and complete the URBs in the cancelled TD list.
* New TDs to be cancelled might be added to the end of the list before
@@ -1800,7 +1819,8 @@ struct xhci_segment *trb_in_td(struct xhci_hcd *xhci,
static void xhci_cleanup_halted_endpoint(struct xhci_hcd *xhci,
unsigned int slot_id, unsigned int ep_index,
unsigned int stream_id,
- struct xhci_td *td, union xhci_trb *ep_trb)
+ struct xhci_td *td, union xhci_trb *ep_trb,
+ enum xhci_ep_reset_type reset_type)
{
struct xhci_virt_ep *ep = &xhci->devs[slot_id]->eps[ep_index];
struct xhci_command *command;
@@ -1809,12 +1829,11 @@ static void xhci_cleanup_halted_endpoint(struct xhci_hcd *xhci,
return;
ep->ep_state |= EP_HALTED;
- ep->stopped_stream = stream_id;
- xhci_queue_reset_ep(xhci, command, slot_id, ep_index);
- xhci_cleanup_stalled_ring(xhci, ep_index, td);
+ xhci_queue_reset_ep(xhci, command, slot_id, ep_index, reset_type);
- ep->stopped_stream = 0;
+ if (reset_type == EP_HARD_RESET)
+ xhci_cleanup_stalled_ring(xhci, ep_index, stream_id, td);
xhci_ring_cmd_db(xhci);
}
@@ -1909,7 +1928,7 @@ static int xhci_td_cleanup(struct xhci_hcd *xhci, struct xhci_td *td,
static int finish_td(struct xhci_hcd *xhci, struct xhci_td *td,
union xhci_trb *ep_trb, struct xhci_transfer_event *event,
- struct xhci_virt_ep *ep, int *status, bool skip)
+ struct xhci_virt_ep *ep, int *status)
{
struct xhci_virt_device *xdev;
struct xhci_ep_ctx *ep_ctx;
@@ -1925,9 +1944,6 @@ static int finish_td(struct xhci_hcd *xhci, struct xhci_td *td,
ep_ctx = xhci_get_ep_ctx(xhci, xdev->out_ctx, ep_index);
trb_comp_code = GET_COMP_CODE(le32_to_cpu(event->transfer_len));
- if (skip)
- goto td_cleanup;
-
if (trb_comp_code == COMP_STOPPED_LENGTH_INVALID ||
trb_comp_code == COMP_STOPPED ||
trb_comp_code == COMP_STOPPED_SHORT_PACKET) {
@@ -1935,7 +1951,6 @@ static int finish_td(struct xhci_hcd *xhci, struct xhci_td *td,
* stopped TDs. A stopped TD may be restarted, so don't update
* the ring dequeue pointer or take this TD off any lists yet.
*/
- ep->stopped_td = td;
return 0;
}
if (trb_comp_code == COMP_STALL_ERROR ||
@@ -1947,7 +1962,8 @@ static int finish_td(struct xhci_hcd *xhci, struct xhci_td *td,
* The class driver clears the device side halt later.
*/
xhci_cleanup_halted_endpoint(xhci, slot_id, ep_index,
- ep_ring->stream_id, td, ep_trb);
+ ep_ring->stream_id, td, ep_trb,
+ EP_HARD_RESET);
} else {
/* Update ring dequeue pointer */
while (ep_ring->dequeue != td->last_trb)
@@ -1955,7 +1971,6 @@ static int finish_td(struct xhci_hcd *xhci, struct xhci_td *td,
inc_deq(xhci, ep_ring);
}
-td_cleanup:
return xhci_td_cleanup(xhci, td, ep_ring, status);
}
@@ -2075,7 +2090,7 @@ static int process_ctrl_td(struct xhci_hcd *xhci, struct xhci_td *td,
td->urb->actual_length = requested;
finish_td:
- return finish_td(xhci, td, ep_trb, event, ep, status, false);
+ return finish_td(xhci, td, ep_trb, event, ep, status);
}
/*
@@ -2162,7 +2177,7 @@ static int process_isoc_td(struct xhci_hcd *xhci, struct xhci_td *td,
td->urb->actual_length += frame->actual_length;
- return finish_td(xhci, td, ep_trb, event, ep, status, false);
+ return finish_td(xhci, td, ep_trb, event, ep, status);
}
static int skip_isoc_td(struct xhci_hcd *xhci, struct xhci_td *td,
@@ -2190,7 +2205,7 @@ static int skip_isoc_td(struct xhci_hcd *xhci, struct xhci_td *td,
inc_deq(xhci, ep_ring);
inc_deq(xhci, ep_ring);
- return finish_td(xhci, td, NULL, event, ep, status, true);
+ return xhci_td_cleanup(xhci, td, ep_ring, status);
}
/*
@@ -2252,7 +2267,7 @@ finish_td:
remaining);
td->urb->actual_length = 0;
}
- return finish_td(xhci, td, ep_trb, event, ep, status, false);
+ return finish_td(xhci, td, ep_trb, event, ep, status);
}
/*
@@ -2280,39 +2295,46 @@ static int handle_tx_event(struct xhci_hcd *xhci,
bool handling_skipped_tds = false;
slot_id = TRB_TO_SLOT_ID(le32_to_cpu(event->flags));
+ ep_index = TRB_TO_EP_ID(le32_to_cpu(event->flags)) - 1;
+ trb_comp_code = GET_COMP_CODE(le32_to_cpu(event->transfer_len));
+ ep_trb_dma = le64_to_cpu(event->buffer);
+
xdev = xhci->devs[slot_id];
if (!xdev) {
xhci_err(xhci, "ERROR Transfer event pointed to bad slot %u\n",
slot_id);
- xhci_err(xhci, "@%016llx %08x %08x %08x %08x\n",
- (unsigned long long) xhci_trb_virt_to_dma(
- xhci->event_ring->deq_seg,
- xhci->event_ring->dequeue),
- lower_32_bits(le64_to_cpu(event->buffer)),
- upper_32_bits(le64_to_cpu(event->buffer)),
- le32_to_cpu(event->transfer_len),
- le32_to_cpu(event->flags));
- return -ENODEV;
- }
-
- /* Endpoint ID is 1 based, our index is zero based */
- ep_index = TRB_TO_EP_ID(le32_to_cpu(event->flags)) - 1;
+ goto err_out;
+ }
+
ep = &xdev->eps[ep_index];
- ep_ring = xhci_dma_to_transfer_ring(ep, le64_to_cpu(event->buffer));
+ ep_ring = xhci_dma_to_transfer_ring(ep, ep_trb_dma);
ep_ctx = xhci_get_ep_ctx(xhci, xdev->out_ctx, ep_index);
- if (!ep_ring || GET_EP_CTX_STATE(ep_ctx) == EP_STATE_DISABLED) {
+
+ if (GET_EP_CTX_STATE(ep_ctx) == EP_STATE_DISABLED) {
xhci_err(xhci,
- "ERROR Transfer event for disabled endpoint slot %u ep %u or incorrect stream ring\n",
+ "ERROR Transfer event for disabled endpoint slot %u ep %u\n",
slot_id, ep_index);
- xhci_err(xhci, "@%016llx %08x %08x %08x %08x\n",
- (unsigned long long) xhci_trb_virt_to_dma(
- xhci->event_ring->deq_seg,
- xhci->event_ring->dequeue),
- lower_32_bits(le64_to_cpu(event->buffer)),
- upper_32_bits(le64_to_cpu(event->buffer)),
- le32_to_cpu(event->transfer_len),
- le32_to_cpu(event->flags));
- return -ENODEV;
+ goto err_out;
+ }
+
+ /* Some transfer events don't always point to a trb, see xhci 4.17.4 */
+ if (!ep_ring) {
+ switch (trb_comp_code) {
+ case COMP_STALL_ERROR:
+ case COMP_USB_TRANSACTION_ERROR:
+ case COMP_INVALID_STREAM_TYPE_ERROR:
+ case COMP_INVALID_STREAM_ID_ERROR:
+ xhci_cleanup_halted_endpoint(xhci, slot_id, ep_index, 0,
+ NULL, NULL, EP_SOFT_RESET);
+ goto cleanup;
+ case COMP_RING_UNDERRUN:
+ case COMP_RING_OVERRUN:
+ goto cleanup;
+ default:
+ xhci_err(xhci, "ERROR Transfer event for unknown stream ring slot %u ep %u\n",
+ slot_id, ep_index);
+ goto err_out;
+ }
}
/* Count current td numbers if ep->skip is set */
@@ -2321,8 +2343,6 @@ static int handle_tx_event(struct xhci_hcd *xhci,
td_num++;
}
- ep_trb_dma = le64_to_cpu(event->buffer);
- trb_comp_code = GET_COMP_CODE(le32_to_cpu(event->transfer_len));
/* Look for common error cases */
switch (trb_comp_code) {
/* Skip codes that require special handling depending on
@@ -2339,6 +2359,7 @@ static int handle_tx_event(struct xhci_hcd *xhci,
slot_id, ep_index);
case COMP_SHORT_PACKET:
break;
+ /* Completion codes for endpoint stopped state */
case COMP_STOPPED:
xhci_dbg(xhci, "Stopped on Transfer TRB for slot %u ep %u\n",
slot_id, ep_index);
@@ -2353,18 +2374,13 @@ static int handle_tx_event(struct xhci_hcd *xhci,
"Stopped with short packet transfer detected for slot %u ep %u\n",
slot_id, ep_index);
break;
+ /* Completion codes for endpoint halted state */
case COMP_STALL_ERROR:
xhci_dbg(xhci, "Stalled endpoint for slot %u ep %u\n", slot_id,
ep_index);
ep->ep_state |= EP_HALTED;
status = -EPIPE;
break;
- case COMP_TRB_ERROR:
- xhci_warn(xhci,
- "WARN: TRB error for slot %u ep %u on endpoint\n",
- slot_id, ep_index);
- status = -EILSEQ;
- break;
case COMP_SPLIT_TRANSACTION_ERROR:
case COMP_USB_TRANSACTION_ERROR:
xhci_dbg(xhci, "Transfer error for slot %u ep %u on endpoint\n",
@@ -2376,6 +2392,14 @@ static int handle_tx_event(struct xhci_hcd *xhci,
slot_id, ep_index);
status = -EOVERFLOW;
break;
+ /* Completion codes for endpoint error state */
+ case COMP_TRB_ERROR:
+ xhci_warn(xhci,
+ "WARN: TRB error for slot %u ep %u on endpoint\n",
+ slot_id, ep_index);
+ status = -EILSEQ;
+ break;
+ /* completion codes not indicating endpoint state change */
case COMP_DATA_BUFFER_ERROR:
xhci_warn(xhci,
"WARN: HC couldn't access mem fast enough for slot %u ep %u\n",
@@ -2413,12 +2437,6 @@ static int handle_tx_event(struct xhci_hcd *xhci,
TRB_TO_SLOT_ID(le32_to_cpu(event->flags)),
ep_index);
goto cleanup;
- case COMP_INCOMPATIBLE_DEVICE_ERROR:
- xhci_warn(xhci,
- "WARN: detect an incompatible device for slot %u ep %u",
- slot_id, ep_index);
- status = -EPROTO;
- break;
case COMP_MISSED_SERVICE_ERROR:
/*
* When encounter missed service error, one or more isoc tds
@@ -2437,6 +2455,14 @@ static int handle_tx_event(struct xhci_hcd *xhci,
"No Ping response error for slot %u ep %u, Skip one Isoc TD\n",
slot_id, ep_index);
goto cleanup;
+
+ case COMP_INCOMPATIBLE_DEVICE_ERROR:
+ /* needs disable slot command to recover */
+ xhci_warn(xhci,
+ "WARN: detect an incompatible device for slot %u ep %u",
+ slot_id, ep_index);
+ status = -EPROTO;
+ break;
default:
if (xhci_is_vendor_info_code(xhci, trb_comp_code)) {
status = 0;
@@ -2589,6 +2615,17 @@ cleanup:
} while (handling_skipped_tds);
return 0;
+
+err_out:
+ xhci_err(xhci, "@%016llx %08x %08x %08x %08x\n",
+ (unsigned long long) xhci_trb_virt_to_dma(
+ xhci->event_ring->deq_seg,
+ xhci->event_ring->dequeue),
+ lower_32_bits(le64_to_cpu(event->buffer)),
+ upper_32_bits(le64_to_cpu(event->buffer)),
+ le32_to_cpu(event->transfer_len),
+ le32_to_cpu(event->flags));
+ return -ENODEV;
}
/*
@@ -3963,13 +4000,12 @@ int xhci_queue_stop_endpoint(struct xhci_hcd *xhci, struct xhci_command *cmd,
/* Set Transfer Ring Dequeue Pointer command */
void xhci_queue_new_dequeue_state(struct xhci_hcd *xhci,
unsigned int slot_id, unsigned int ep_index,
- unsigned int stream_id,
struct xhci_dequeue_state *deq_state)
{
dma_addr_t addr;
u32 trb_slot_id = SLOT_ID_FOR_TRB(slot_id);
u32 trb_ep_index = EP_ID_FOR_TRB(ep_index);
- u32 trb_stream_id = STREAM_ID_FOR_TRB(stream_id);
+ u32 trb_stream_id = STREAM_ID_FOR_TRB(deq_state->stream_id);
u32 trb_sct = 0;
u32 type = TRB_TYPE(TRB_SET_DEQ);
struct xhci_virt_ep *ep;
@@ -4007,7 +4043,7 @@ void xhci_queue_new_dequeue_state(struct xhci_hcd *xhci,
ep->queued_deq_seg = deq_state->new_deq_seg;
ep->queued_deq_ptr = deq_state->new_deq_ptr;
- if (stream_id)
+ if (deq_state->stream_id)
trb_sct = SCT_FOR_TRB(SCT_PRI_TR);
ret = queue_command(xhci, cmd,
lower_32_bits(addr) | trb_sct | deq_state->new_cycle_state,
@@ -4027,12 +4063,16 @@ void xhci_queue_new_dequeue_state(struct xhci_hcd *xhci,
}
int xhci_queue_reset_ep(struct xhci_hcd *xhci, struct xhci_command *cmd,
- int slot_id, unsigned int ep_index)
+ int slot_id, unsigned int ep_index,
+ enum xhci_ep_reset_type reset_type)
{
u32 trb_slot_id = SLOT_ID_FOR_TRB(slot_id);
u32 trb_ep_index = EP_ID_FOR_TRB(ep_index);
u32 type = TRB_TYPE(TRB_RESET_EP);
+ if (reset_type == EP_SOFT_RESET)
+ type |= TRB_TSP;
+
return queue_command(xhci, cmd, 0, 0, 0,
trb_slot_id | trb_ep_index | type, false);
}
diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c
index 30f47d92a610..56f85df013db 100644
--- a/drivers/usb/host/xhci.c
+++ b/drivers/usb/host/xhci.c
@@ -1695,8 +1695,7 @@ static int xhci_add_endpoint(struct usb_hcd *hcd, struct usb_device *udev,
if (xhci->quirks & XHCI_MTK_HOST) {
ret = xhci_mtk_add_ep_quirk(hcd, udev, ep);
if (ret < 0) {
- xhci_free_or_cache_endpoint_ring(xhci,
- virt_dev, ep_index);
+ xhci_free_endpoint_ring(xhci, virt_dev, ep_index);
return ret;
}
}
@@ -2720,23 +2719,23 @@ static int xhci_check_bandwidth(struct usb_hcd *hcd, struct usb_device *udev)
for (i = 1; i < 31; i++) {
if ((le32_to_cpu(ctrl_ctx->drop_flags) & (1 << (i + 1))) &&
!(le32_to_cpu(ctrl_ctx->add_flags) & (1 << (i + 1)))) {
- xhci_free_or_cache_endpoint_ring(xhci, virt_dev, i);
+ xhci_free_endpoint_ring(xhci, virt_dev, i);
xhci_check_bw_drop_ep_streams(xhci, virt_dev, i);
}
}
xhci_zero_in_ctx(xhci, virt_dev);
/*
* Install any rings for completely new endpoints or changed endpoints,
- * and free or cache any old rings from changed endpoints.
+ * and free any old rings from changed endpoints.
*/
for (i = 1; i < 31; i++) {
if (!virt_dev->eps[i].new_ring)
continue;
- /* Only cache or free the old ring if it exists.
+ /* Only free the old ring if it exists.
* It may not if this is the first add of an endpoint.
*/
if (virt_dev->eps[i].ring) {
- xhci_free_or_cache_endpoint_ring(xhci, virt_dev, i);
+ xhci_free_endpoint_ring(xhci, virt_dev, i);
}
xhci_check_bw_drop_ep_streams(xhci, virt_dev, i);
virt_dev->eps[i].ring = virt_dev->eps[i].new_ring;
@@ -2823,8 +2822,8 @@ static void xhci_setup_input_ctx_for_quirk(struct xhci_hcd *xhci,
added_ctxs, added_ctxs);
}
-void xhci_cleanup_stalled_ring(struct xhci_hcd *xhci,
- unsigned int ep_index, struct xhci_td *td)
+void xhci_cleanup_stalled_ring(struct xhci_hcd *xhci, unsigned int ep_index,
+ unsigned int stream_id, struct xhci_td *td)
{
struct xhci_dequeue_state deq_state;
struct xhci_virt_ep *ep;
@@ -2837,7 +2836,7 @@ void xhci_cleanup_stalled_ring(struct xhci_hcd *xhci,
* or it will attempt to resend it on the next doorbell ring.
*/
xhci_find_new_dequeue_state(xhci, udev->slot_id,
- ep_index, ep->stopped_stream, td, &deq_state);
+ ep_index, stream_id, td, &deq_state);
if (!deq_state.new_deq_ptr || !deq_state.new_deq_seg)
return;
@@ -2849,7 +2848,7 @@ void xhci_cleanup_stalled_ring(struct xhci_hcd *xhci,
xhci_dbg_trace(xhci, trace_xhci_dbg_reset_ep,
"Queueing new dequeue state");
xhci_queue_new_dequeue_state(xhci, udev->slot_id,
- ep_index, ep->stopped_stream, &deq_state);
+ ep_index, &deq_state);
} else {
/* Better hope no one uses the input context between now and the
* reset endpoint completion!
@@ -3336,7 +3335,7 @@ void xhci_free_device_endpoint_resources(struct xhci_hcd *xhci,
*
* Wait for the Reset Device command to finish. Remove all structures
* associated with the endpoints that were disabled. Clear the input device
- * structure? Cache the rings? Reset the control endpoint 0 max packet size?
+ * structure? Reset the control endpoint 0 max packet size?
*
* If the virt_dev to be reset does not exist or does not match the udev,
* it means the device is lost, possibly due to the xHC restore error and
@@ -3466,7 +3465,7 @@ static int xhci_discover_or_reset_device(struct usb_hcd *hcd,
spin_unlock_irqrestore(&xhci->lock, flags);
}
- /* Everything but endpoint 0 is disabled, so free or cache the rings. */
+ /* Everything but endpoint 0 is disabled, so free the rings. */
last_freed_endpoint = 1;
for (i = 1; i < 31; i++) {
struct xhci_virt_ep *ep = &virt_dev->eps[i];
@@ -3480,7 +3479,7 @@ static int xhci_discover_or_reset_device(struct usb_hcd *hcd,
}
if (ep->ring) {
- xhci_free_or_cache_endpoint_ring(xhci, virt_dev, i);
+ xhci_free_endpoint_ring(xhci, virt_dev, i);
last_freed_endpoint = i;
}
if (!list_empty(&virt_dev->eps[i].bw_endpoint_list))
diff --git a/drivers/usb/host/xhci.h b/drivers/usb/host/xhci.h
index 73a28a986d5e..650a2d9d4aec 100644
--- a/drivers/usb/host/xhci.h
+++ b/drivers/usb/host/xhci.h
@@ -924,8 +924,6 @@ struct xhci_virt_ep {
#define EP_GETTING_NO_STREAMS (1 << 5)
/* ---- Related to URB cancellation ---- */
struct list_head cancelled_td_list;
- struct xhci_td *stopped_td;
- unsigned int stopped_stream;
/* Watchdog timer for stop endpoint command to cancel URBs */
struct timer_list stop_cmd_timer;
struct xhci_hcd *xhci;
@@ -993,10 +991,6 @@ struct xhci_virt_device {
struct xhci_container_ctx *out_ctx;
/* Used for addressing devices and configuration changes */
struct xhci_container_ctx *in_ctx;
- /* Rings saved to ensure old alt settings can be re-instated */
- struct xhci_ring **ring_cache;
- int num_rings_cached;
-#define XHCI_MAX_RINGS_CACHED 31
struct xhci_virt_ep eps[31];
u8 fake_port;
u8 real_port;
@@ -1210,6 +1204,11 @@ struct xhci_event_cmd {
/* Stop Ring - Transfer State Preserve */
#define TRB_TSP (1<<9)
+enum xhci_ep_reset_type {
+ EP_HARD_RESET,
+ EP_SOFT_RESET,
+};
+
/* Force Event */
#define TRB_TO_VF_INTR_TARGET(p) (((p) & (0x3ff << 22)) >> 22)
#define TRB_TO_VF_ID(p) (((p) & (0xff << 16)) >> 16)
@@ -1527,6 +1526,7 @@ struct xhci_dequeue_state {
struct xhci_segment *new_deq_seg;
union xhci_trb *new_deq_ptr;
int new_cycle_state;
+ unsigned int stream_id;
};
enum xhci_ring_type {
@@ -1960,7 +1960,7 @@ int xhci_endpoint_init(struct xhci_hcd *xhci, struct xhci_virt_device *virt_dev,
void xhci_ring_free(struct xhci_hcd *xhci, struct xhci_ring *ring);
int xhci_ring_expansion(struct xhci_hcd *xhci, struct xhci_ring *ring,
unsigned int num_trbs, gfp_t flags);
-void xhci_free_or_cache_endpoint_ring(struct xhci_hcd *xhci,
+void xhci_free_endpoint_ring(struct xhci_hcd *xhci,
struct xhci_virt_device *virt_dev,
unsigned int ep_index);
struct xhci_stream_info *xhci_alloc_stream_info(struct xhci_hcd *xhci,
@@ -2044,7 +2044,8 @@ int xhci_queue_configure_endpoint(struct xhci_hcd *xhci,
int xhci_queue_evaluate_context(struct xhci_hcd *xhci, struct xhci_command *cmd,
dma_addr_t in_ctx_ptr, u32 slot_id, bool command_must_succeed);
int xhci_queue_reset_ep(struct xhci_hcd *xhci, struct xhci_command *cmd,
- int slot_id, unsigned int ep_index);
+ int slot_id, unsigned int ep_index,
+ enum xhci_ep_reset_type reset_type);
int xhci_queue_reset_device(struct xhci_hcd *xhci, struct xhci_command *cmd,
u32 slot_id);
void xhci_find_new_dequeue_state(struct xhci_hcd *xhci,
@@ -2053,10 +2054,9 @@ void xhci_find_new_dequeue_state(struct xhci_hcd *xhci,
struct xhci_dequeue_state *state);
void xhci_queue_new_dequeue_state(struct xhci_hcd *xhci,
unsigned int slot_id, unsigned int ep_index,
- unsigned int stream_id,
struct xhci_dequeue_state *deq_state);
-void xhci_cleanup_stalled_ring(struct xhci_hcd *xhci,
- unsigned int ep_index, struct xhci_td *td);
+void xhci_cleanup_stalled_ring(struct xhci_hcd *xhci, unsigned int ep_index,
+ unsigned int stream_id, struct xhci_td *td);
void xhci_stop_endpoint_command_watchdog(unsigned long arg);
void xhci_handle_command_timeout(struct work_struct *work);
diff --git a/drivers/usb/misc/Kconfig b/drivers/usb/misc/Kconfig
index 1d1d70d62a19..0f9f25db9163 100644
--- a/drivers/usb/misc/Kconfig
+++ b/drivers/usb/misc/Kconfig
@@ -275,29 +275,3 @@ config USB_CHAOSKEY
To compile this driver as a module, choose M here: the
module will be called chaoskey.
-
-config UCSI
- tristate "USB Type-C Connector System Software Interface driver"
- depends on ACPI
- help
- UCSI driver is meant to be used as a convenience tool for desktop and
- server systems that are not equipped to handle USB in device mode. It
- will always select USB host role for the USB Type-C ports on systems
- that provide UCSI interface.
-
- USB Type-C Connector System Software Interface (UCSI) is a
- specification for an interface that allows the Operating System to
- control the USB Type-C ports on a system. Things the need controlling
- include the USB Data Role (host or device), and when USB Power
- Delivery is supported, the Power Role (source or sink). With USB
- Type-C connectors, when two dual role capable devices are attached
- together, the data role is selected randomly. Therefore it is
- important to give the OS a way to select the role. Otherwise the user
- would have to unplug and replug in order in order to attempt to swap
- the data and power roles.
-
- The UCSI specification can be downloaded from:
- http://www.intel.com/content/www/us/en/io/universal-serial-bus/usb-type-c-ucsi-spec.html
-
- To compile the driver as a module, choose M here: the module will be
- called ucsi.
diff --git a/drivers/usb/misc/Makefile b/drivers/usb/misc/Makefile
index f6ac6c99a6e6..7fdb45fc976f 100644
--- a/drivers/usb/misc/Makefile
+++ b/drivers/usb/misc/Makefile
@@ -27,7 +27,6 @@ obj-$(CONFIG_USB_HUB_USB251XB) += usb251xb.o
obj-$(CONFIG_USB_HSIC_USB3503) += usb3503.o
obj-$(CONFIG_USB_HSIC_USB4604) += usb4604.o
obj-$(CONFIG_USB_CHAOSKEY) += chaoskey.o
-obj-$(CONFIG_UCSI) += ucsi.o
obj-$(CONFIG_USB_SISUSBVGA) += sisusbvga/
obj-$(CONFIG_USB_LINK_LAYER_TEST) += lvstest.o
diff --git a/drivers/usb/misc/iowarrior.c b/drivers/usb/misc/iowarrior.c
index 83b05a287b0c..7ca4c7e0ea0d 100644
--- a/drivers/usb/misc/iowarrior.c
+++ b/drivers/usb/misc/iowarrior.c
@@ -368,14 +368,9 @@ static ssize_t iowarrior_write(struct file *file,
case USB_DEVICE_ID_CODEMERCS_IOWPV2:
case USB_DEVICE_ID_CODEMERCS_IOW40:
/* IOW24 and IOW40 use a synchronous call */
- buf = kmalloc(count, GFP_KERNEL);
- if (!buf) {
- retval = -ENOMEM;
- goto exit;
- }
- if (copy_from_user(buf, user_buffer, count)) {
- retval = -EFAULT;
- kfree(buf);
+ buf = memdup_user(user_buffer, count);
+ if (IS_ERR(buf)) {
+ retval = PTR_ERR(buf);
goto exit;
}
retval = usb_set_report(dev->interface, 2, 0, buf, count);
diff --git a/drivers/usb/misc/ucsi.c b/drivers/usb/misc/ucsi.c
deleted file mode 100644
index 07397bddefa3..000000000000
--- a/drivers/usb/misc/ucsi.c
+++ /dev/null
@@ -1,478 +0,0 @@
-/*
- * USB Type-C Connector System Software Interface driver
- *
- * Copyright (C) 2016, Intel Corporation
- * Author: Heikki Krogerus <heikki.krogerus@linux.intel.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-#include <linux/platform_device.h>
-#include <linux/module.h>
-#include <linux/delay.h>
-#include <linux/acpi.h>
-
-#include "ucsi.h"
-
-/* Double the time defined by MIN_TIME_TO_RESPOND_WITH_BUSY */
-#define UCSI_TIMEOUT_MS 20
-
-enum ucsi_status {
- UCSI_IDLE = 0,
- UCSI_BUSY,
- UCSI_ERROR,
-};
-
-struct ucsi_connector {
- int num;
- struct ucsi *ucsi;
- struct work_struct work;
- struct ucsi_connector_capability cap;
-};
-
-struct ucsi {
- struct device *dev;
- struct ucsi_data __iomem *data;
-
- enum ucsi_status status;
- struct completion complete;
- struct ucsi_capability cap;
- struct ucsi_connector *connector;
-
- /* device lock */
- spinlock_t dev_lock;
-
- /* PPM Communication lock */
- struct mutex ppm_lock;
-
- /* PPM communication flags */
- unsigned long flags;
-#define EVENT_PENDING 0
-#define COMMAND_PENDING 1
-};
-
-static int ucsi_acpi_cmd(struct ucsi *ucsi, struct ucsi_control *ctrl)
-{
- uuid_le uuid = UUID_LE(0x6f8398c2, 0x7ca4, 0x11e4,
- 0xad, 0x36, 0x63, 0x10, 0x42, 0xb5, 0x00, 0x8f);
- union acpi_object *obj;
-
- ucsi->data->ctrl.raw_cmd = ctrl->raw_cmd;
-
- obj = acpi_evaluate_dsm(ACPI_HANDLE(ucsi->dev), uuid.b, 1, 1, NULL);
- if (!obj) {
- dev_err(ucsi->dev, "%s: failed to evaluate _DSM\n", __func__);
- return -EIO;
- }
-
- ACPI_FREE(obj);
- return 0;
-}
-
-static void ucsi_acpi_notify(acpi_handle handle, u32 event, void *data)
-{
- struct ucsi *ucsi = data;
- struct ucsi_cci *cci;
-
- spin_lock(&ucsi->dev_lock);
-
- ucsi->status = UCSI_IDLE;
- cci = &ucsi->data->cci;
-
- /*
- * REVISIT: This is not documented behavior, but all known PPMs ACK
- * asynchronous events by sending notification with cleared CCI.
- */
- if (!ucsi->data->raw_cci) {
- if (test_bit(EVENT_PENDING, &ucsi->flags))
- complete(&ucsi->complete);
- else
- dev_WARN(ucsi->dev, "spurious notification\n");
- goto out_unlock;
- }
-
- if (test_bit(COMMAND_PENDING, &ucsi->flags)) {
- if (cci->busy) {
- ucsi->status = UCSI_BUSY;
- complete(&ucsi->complete);
-
- goto out_unlock;
- } else if (cci->ack_complete || cci->cmd_complete) {
- /* Error Indication is only valid with commands */
- if (cci->error && cci->cmd_complete)
- ucsi->status = UCSI_ERROR;
-
- ucsi->data->ctrl.raw_cmd = 0;
- complete(&ucsi->complete);
- }
- }
-
- if (cci->connector_change) {
- struct ucsi_connector *con;
-
- /*
- * This is workaround for buggy PPMs that create asynchronous
- * event notifications before OPM has enabled them.
- */
- if (!ucsi->connector)
- goto out_unlock;
-
- con = ucsi->connector + (cci->connector_change - 1);
-
- /*
- * PPM will not clear the connector specific bit in Connector
- * Change Indication field of CCI until the driver has ACK it,
- * and the driver can not ACK it before it has been processed.
- * The PPM will not generate new events before the first has
- * been acknowledged, even if they are for an other connector.
- * So only one event at a time.
- */
- if (!test_and_set_bit(EVENT_PENDING, &ucsi->flags))
- schedule_work(&con->work);
- }
-out_unlock:
- spin_unlock(&ucsi->dev_lock);
-}
-
-static int ucsi_ack(struct ucsi *ucsi, u8 cmd)
-{
- struct ucsi_control ctrl;
- int ret;
-
- ctrl.cmd.cmd = UCSI_ACK_CC_CI;
- ctrl.cmd.length = 0;
- ctrl.cmd.data = cmd;
- ret = ucsi_acpi_cmd(ucsi, &ctrl);
- if (ret)
- return ret;
-
- /* Waiting for ACK also with ACK CMD for now */
- ret = wait_for_completion_timeout(&ucsi->complete,
- msecs_to_jiffies(UCSI_TIMEOUT_MS));
- if (!ret)
- return -ETIMEDOUT;
- return 0;
-}
-
-static int ucsi_run_cmd(struct ucsi *ucsi, struct ucsi_control *ctrl,
- void *data, size_t size)
-{
- u16 err_value = 0;
- int ret;
-
- set_bit(COMMAND_PENDING, &ucsi->flags);
-
- ret = ucsi_acpi_cmd(ucsi, ctrl);
- if (ret)
- goto err_clear_flag;
-
- ret = wait_for_completion_timeout(&ucsi->complete,
- msecs_to_jiffies(UCSI_TIMEOUT_MS));
- if (!ret) {
- ret = -ETIMEDOUT;
- goto err_clear_flag;
- }
-
- switch (ucsi->status) {
- case UCSI_IDLE:
- if (data)
- memcpy(data, ucsi->data->message_in, size);
-
- ret = ucsi_ack(ucsi, UCSI_ACK_CMD);
- break;
- case UCSI_BUSY:
- /* The caller decides whether to cancel or not */
- ret = -EBUSY;
- goto err_clear_flag;
- case UCSI_ERROR:
- ret = ucsi_ack(ucsi, UCSI_ACK_CMD);
- if (ret)
- goto err_clear_flag;
-
- ctrl->cmd.cmd = UCSI_GET_ERROR_STATUS;
- ctrl->cmd.length = 0;
- ctrl->cmd.data = 0;
- ret = ucsi_acpi_cmd(ucsi, ctrl);
- if (ret)
- goto err_clear_flag;
-
- ret = wait_for_completion_timeout(&ucsi->complete,
- msecs_to_jiffies(UCSI_TIMEOUT_MS));
- if (!ret) {
- ret = -ETIMEDOUT;
- goto err_clear_flag;
- }
-
- memcpy(&err_value, ucsi->data->message_in, sizeof(err_value));
-
- /* Something has really gone wrong */
- if (WARN_ON(ucsi->status == UCSI_ERROR)) {
- ret = -ENODEV;
- goto err_clear_flag;
- }
-
- ret = ucsi_ack(ucsi, UCSI_ACK_CMD);
- if (ret)
- goto err_clear_flag;
-
- switch (err_value) {
- case UCSI_ERROR_INCOMPATIBLE_PARTNER:
- ret = -EOPNOTSUPP;
- break;
- case UCSI_ERROR_CC_COMMUNICATION_ERR:
- ret = -ECOMM;
- break;
- case UCSI_ERROR_CONTRACT_NEGOTIATION_FAIL:
- ret = -EIO;
- break;
- case UCSI_ERROR_DEAD_BATTERY:
- dev_warn(ucsi->dev, "Dead battery condition!\n");
- ret = -EPERM;
- break;
- /* The following mean a bug in this driver */
- case UCSI_ERROR_INVALID_CON_NUM:
- case UCSI_ERROR_UNREGONIZED_CMD:
- case UCSI_ERROR_INVALID_CMD_ARGUMENT:
- default:
- dev_warn(ucsi->dev,
- "%s: possible UCSI driver bug - error %hu\n",
- __func__, err_value);
- ret = -EINVAL;
- break;
- }
- break;
- }
- ctrl->raw_cmd = 0;
-err_clear_flag:
- clear_bit(COMMAND_PENDING, &ucsi->flags);
- return ret;
-}
-
-static void ucsi_connector_change(struct work_struct *work)
-{
- struct ucsi_connector *con = container_of(work, struct ucsi_connector,
- work);
- struct ucsi_connector_status constat;
- struct ucsi *ucsi = con->ucsi;
- struct ucsi_control ctrl;
- int ret;
-
- mutex_lock(&ucsi->ppm_lock);
-
- ctrl.cmd.cmd = UCSI_GET_CONNECTOR_STATUS;
- ctrl.cmd.length = 0;
- ctrl.cmd.data = con->num;
- ret = ucsi_run_cmd(con->ucsi, &ctrl, &constat, sizeof(constat));
- if (ret) {
- dev_err(ucsi->dev, "%s: failed to read connector status (%d)\n",
- __func__, ret);
- goto out_ack_event;
- }
-
- /* Ignoring disconnections and Alternate Modes */
- if (!constat.connected || !(constat.change &
- (UCSI_CONSTAT_PARTNER_CHANGE | UCSI_CONSTAT_CONNECT_CHANGE)) ||
- constat.partner_flags & UCSI_CONSTAT_PARTNER_FLAG_ALT_MODE)
- goto out_ack_event;
-
- /* If the partner got USB Host role, attempting swap */
- if (constat.partner_type & UCSI_CONSTAT_PARTNER_TYPE_DFP) {
- ctrl.uor.cmd = UCSI_SET_UOR;
- ctrl.uor.con_num = con->num;
- ctrl.uor.role = UCSI_UOR_ROLE_DFP;
-
- ret = ucsi_run_cmd(con->ucsi, &ctrl, NULL, 0);
- if (ret)
- dev_err(ucsi->dev, "%s: failed to swap role (%d)\n",
- __func__, ret);
- }
-out_ack_event:
- ucsi_ack(ucsi, UCSI_ACK_EVENT);
- clear_bit(EVENT_PENDING, &ucsi->flags);
- mutex_unlock(&ucsi->ppm_lock);
-}
-
-static int ucsi_reset_ppm(struct ucsi *ucsi)
-{
- int timeout = UCSI_TIMEOUT_MS;
- struct ucsi_control ctrl;
- int ret;
-
- memset(&ctrl, 0, sizeof(ctrl));
- ctrl.cmd.cmd = UCSI_PPM_RESET;
- ret = ucsi_acpi_cmd(ucsi, &ctrl);
- if (ret)
- return ret;
-
- /* There is no quarantee the PPM will ever set the RESET_COMPLETE bit */
- while (!ucsi->data->cci.reset_complete && timeout--)
- usleep_range(1000, 2000);
- return 0;
-}
-
-static int ucsi_init(struct ucsi *ucsi)
-{
- struct ucsi_connector *con;
- struct ucsi_control ctrl;
- int ret;
- int i;
-
- init_completion(&ucsi->complete);
- spin_lock_init(&ucsi->dev_lock);
- mutex_init(&ucsi->ppm_lock);
-
- /* Reset the PPM */
- ret = ucsi_reset_ppm(ucsi);
- if (ret)
- return ret;
-
- /*
- * REVISIT: Executing second reset to WA an issue seen on some of the
- * Broxton based platforms, where the first reset puts the PPM into a
- * state where it's unable to recognise some of the commands.
- */
- ret = ucsi_reset_ppm(ucsi);
- if (ret)
- return ret;
-
- mutex_lock(&ucsi->ppm_lock);
-
- /* Enable basic notifications */
- ctrl.cmd.cmd = UCSI_SET_NOTIFICATION_ENABLE;
- ctrl.cmd.length = 0;
- ctrl.cmd.data = UCSI_ENABLE_NTFY_CMD_COMPLETE | UCSI_ENABLE_NTFY_ERROR;
- ret = ucsi_run_cmd(ucsi, &ctrl, NULL, 0);
- if (ret)
- goto err_reset;
-
- /* Get PPM capabilities */
- ctrl.cmd.cmd = UCSI_GET_CAPABILITY;
- ret = ucsi_run_cmd(ucsi, &ctrl, &ucsi->cap, sizeof(ucsi->cap));
- if (ret)
- goto err_reset;
-
- if (!ucsi->cap.num_connectors) {
- ret = -ENODEV;
- goto err_reset;
- }
-
- ucsi->connector = devm_kcalloc(ucsi->dev, ucsi->cap.num_connectors,
- sizeof(*ucsi->connector), GFP_KERNEL);
- if (!ucsi->connector) {
- ret = -ENOMEM;
- goto err_reset;
- }
-
- for (i = 1, con = ucsi->connector; i < ucsi->cap.num_connectors + 1;
- i++, con++) {
- /* Get connector capability */
- ctrl.cmd.cmd = UCSI_GET_CONNECTOR_CAPABILITY;
- ctrl.cmd.data = i;
- ret = ucsi_run_cmd(ucsi, &ctrl, &con->cap, sizeof(con->cap));
- if (ret)
- goto err_reset;
-
- con->num = i;
- con->ucsi = ucsi;
- INIT_WORK(&con->work, ucsi_connector_change);
- }
-
- /* Enable all notifications */
- ctrl.cmd.cmd = UCSI_SET_NOTIFICATION_ENABLE;
- ctrl.cmd.data = UCSI_ENABLE_NTFY_ALL;
- ret = ucsi_run_cmd(ucsi, &ctrl, NULL, 0);
- if (ret < 0)
- goto err_reset;
-
- mutex_unlock(&ucsi->ppm_lock);
- return 0;
-err_reset:
- ucsi_reset_ppm(ucsi);
- mutex_unlock(&ucsi->ppm_lock);
- return ret;
-}
-
-static int ucsi_acpi_probe(struct platform_device *pdev)
-{
- struct resource *res;
- acpi_status status;
- struct ucsi *ucsi;
- int ret;
-
- ucsi = devm_kzalloc(&pdev->dev, sizeof(*ucsi), GFP_KERNEL);
- if (!ucsi)
- return -ENOMEM;
-
- res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- if (!res) {
- dev_err(&pdev->dev, "missing memory resource\n");
- return -ENODEV;
- }
-
- /*
- * NOTE: ACPI has claimed the memory region as it's also an Operation
- * Region. It's not possible to request it in the driver.
- */
- ucsi->data = devm_ioremap(&pdev->dev, res->start, resource_size(res));
- if (!ucsi->data)
- return -ENOMEM;
-
- ucsi->dev = &pdev->dev;
-
- status = acpi_install_notify_handler(ACPI_HANDLE(&pdev->dev),
- ACPI_ALL_NOTIFY,
- ucsi_acpi_notify, ucsi);
- if (ACPI_FAILURE(status))
- return -ENODEV;
-
- ret = ucsi_init(ucsi);
- if (ret) {
- acpi_remove_notify_handler(ACPI_HANDLE(&pdev->dev),
- ACPI_ALL_NOTIFY,
- ucsi_acpi_notify);
- return ret;
- }
-
- platform_set_drvdata(pdev, ucsi);
- return 0;
-}
-
-static int ucsi_acpi_remove(struct platform_device *pdev)
-{
- struct ucsi *ucsi = platform_get_drvdata(pdev);
-
- acpi_remove_notify_handler(ACPI_HANDLE(&pdev->dev),
- ACPI_ALL_NOTIFY, ucsi_acpi_notify);
-
- /* Make sure there are no events in the middle of being processed */
- if (wait_on_bit_timeout(&ucsi->flags, EVENT_PENDING,
- TASK_UNINTERRUPTIBLE,
- msecs_to_jiffies(UCSI_TIMEOUT_MS)))
- dev_WARN(ucsi->dev, "%s: Events still pending\n", __func__);
-
- ucsi_reset_ppm(ucsi);
- return 0;
-}
-
-static const struct acpi_device_id ucsi_acpi_match[] = {
- { "PNP0CA0", 0 },
- { },
-};
-MODULE_DEVICE_TABLE(acpi, ucsi_acpi_match);
-
-static struct platform_driver ucsi_acpi_platform_driver = {
- .driver = {
- .name = "ucsi_acpi",
- .acpi_match_table = ACPI_PTR(ucsi_acpi_match),
- },
- .probe = ucsi_acpi_probe,
- .remove = ucsi_acpi_remove,
-};
-
-module_platform_driver(ucsi_acpi_platform_driver);
-
-MODULE_AUTHOR("Heikki Krogerus <heikki.krogerus@linux.intel.com>");
-MODULE_LICENSE("GPL v2");
-MODULE_DESCRIPTION("USB Type-C System Software Interface (UCSI) driver");
diff --git a/drivers/usb/misc/usbsevseg.c b/drivers/usb/misc/usbsevseg.c
index a0ba5298160c..388fae6373db 100644
--- a/drivers/usb/misc/usbsevseg.c
+++ b/drivers/usb/misc/usbsevseg.c
@@ -33,7 +33,7 @@ static const struct usb_device_id id_table[] = {
MODULE_DEVICE_TABLE(usb, id_table);
/* the different text display modes the device is capable of */
-static char *display_textmodes[] = {"raw", "hex", "ascii", NULL};
+static const char *display_textmodes[] = {"raw", "hex", "ascii"};
struct usb_sevsegdev {
struct usb_device *udev;
@@ -280,7 +280,7 @@ static ssize_t show_attr_textmode(struct device *dev,
buf[0] = 0;
- for (i = 0; display_textmodes[i]; i++) {
+ for (i = 0; i < ARRAY_SIZE(display_textmodes); i++) {
if (mydev->textmode == i) {
strcat(buf, " [");
strcat(buf, display_textmodes[i]);
@@ -304,15 +304,13 @@ static ssize_t set_attr_textmode(struct device *dev,
struct usb_sevsegdev *mydev = usb_get_intfdata(intf);
int i;
- for (i = 0; display_textmodes[i]; i++) {
- if (sysfs_streq(display_textmodes[i], buf)) {
- mydev->textmode = i;
- update_display_visual(mydev, GFP_KERNEL);
- return count;
- }
- }
+ i = sysfs_match_string(display_textmodes, buf);
+ if (i < 0)
+ return i;
- return -EINVAL;
+ mydev->textmode = i;
+ update_display_visual(mydev, GFP_KERNEL);
+ return count;
}
static DEVICE_ATTR(textmode, S_IRUGO | S_IWUSR, show_attr_textmode, set_attr_textmode);
diff --git a/drivers/usb/mtu3/mtu3.h b/drivers/usb/mtu3/mtu3.h
index aa6fd6a51221..7b6dc23d77e9 100644
--- a/drivers/usb/mtu3/mtu3.h
+++ b/drivers/usb/mtu3/mtu3.h
@@ -356,12 +356,8 @@ static inline struct mtu3_ep *to_mtu3_ep(struct usb_ep *ep)
static inline struct mtu3_request *next_request(struct mtu3_ep *mep)
{
- struct list_head *queue = &mep->req_list;
-
- if (list_empty(queue))
- return NULL;
-
- return list_first_entry(queue, struct mtu3_request, list);
+ return list_first_entry_or_null(&mep->req_list, struct mtu3_request,
+ list);
}
static inline void mtu3_writel(void __iomem *base, u32 offset, u32 data)
diff --git a/drivers/usb/mtu3/mtu3_plat.c b/drivers/usb/mtu3/mtu3_plat.c
index 42550c7db3e7..0d3ebb353e08 100644
--- a/drivers/usb/mtu3/mtu3_plat.c
+++ b/drivers/usb/mtu3/mtu3_plat.c
@@ -458,6 +458,7 @@ static int __maybe_unused mtu3_resume(struct device *dev)
{
struct platform_device *pdev = to_platform_device(dev);
struct ssusb_mtk *ssusb = platform_get_drvdata(pdev);
+ int ret;
dev_dbg(dev, "%s\n", __func__);
@@ -465,12 +466,28 @@ static int __maybe_unused mtu3_resume(struct device *dev)
return 0;
ssusb_wakeup_disable(ssusb);
- clk_prepare_enable(ssusb->sys_clk);
- clk_prepare_enable(ssusb->ref_clk);
- ssusb_phy_power_on(ssusb);
+ ret = clk_prepare_enable(ssusb->sys_clk);
+ if (ret)
+ goto err_sys_clk;
+
+ ret = clk_prepare_enable(ssusb->ref_clk);
+ if (ret)
+ goto err_ref_clk;
+
+ ret = ssusb_phy_power_on(ssusb);
+ if (ret)
+ goto err_power_on;
+
ssusb_host_enable(ssusb);
return 0;
+
+err_power_on:
+ clk_disable_unprepare(ssusb->ref_clk);
+err_ref_clk:
+ clk_disable_unprepare(ssusb->sys_clk);
+err_sys_clk:
+ return ret;
}
static const struct dev_pm_ops mtu3_pm_ops = {
diff --git a/drivers/usb/musb/musb_core.c b/drivers/usb/musb/musb_core.c
index 870da18f5077..87cbd56cc761 100644
--- a/drivers/usb/musb/musb_core.c
+++ b/drivers/usb/musb/musb_core.c
@@ -2224,6 +2224,9 @@ musb_init_controller(struct device *dev, int nIrq, void __iomem *ctrl)
musb->io.ep_select = musb_flat_ep_select;
}
+ if (musb->io.quirks & MUSB_G_NO_SKB_RESERVE)
+ musb->g.quirk_avoids_skb_reserve = 1;
+
/* At least tusb6010 has its own offsets */
if (musb->ops->ep_offset)
musb->io.ep_offset = musb->ops->ep_offset;
diff --git a/drivers/usb/musb/musb_core.h b/drivers/usb/musb/musb_core.h
index 3e98d4268a64..9f22c5b8ce37 100644
--- a/drivers/usb/musb/musb_core.h
+++ b/drivers/usb/musb/musb_core.h
@@ -172,6 +172,7 @@ struct musb_io;
*/
struct musb_platform_ops {
+#define MUSB_G_NO_SKB_RESERVE BIT(9)
#define MUSB_DA8XX BIT(8)
#define MUSB_PRESERVE_SESSION BIT(7)
#define MUSB_DMA_UX500 BIT(6)
diff --git a/drivers/usb/musb/musb_cppi41.c b/drivers/usb/musb/musb_cppi41.c
index e7c8b1b8bf22..ba255280a624 100644
--- a/drivers/usb/musb/musb_cppi41.c
+++ b/drivers/usb/musb/musb_cppi41.c
@@ -673,12 +673,15 @@ static int cppi41_dma_controller_start(struct cppi41_dma_controller *controller)
musb_dma->status = MUSB_DMA_STATUS_FREE;
musb_dma->max_len = SZ_4M;
- dc = dma_request_slave_channel(dev->parent, str);
- if (!dc) {
- dev_err(dev, "Failed to request %s.\n", str);
- ret = -EPROBE_DEFER;
+ dc = dma_request_chan(dev->parent, str);
+ if (IS_ERR(dc)) {
+ ret = PTR_ERR(dc);
+ if (ret != -EPROBE_DEFER)
+ dev_err(dev, "Failed to request %s: %d.\n",
+ str, ret);
goto err;
}
+
cppi41_channel->dc = dc;
}
return 0;
diff --git a/drivers/usb/musb/musb_dsps.c b/drivers/usb/musb/musb_dsps.c
index 9c7ee26ef388..bc6a9be2ccc5 100644
--- a/drivers/usb/musb/musb_dsps.c
+++ b/drivers/usb/musb/musb_dsps.c
@@ -245,6 +245,11 @@ static int dsps_check_status(struct musb *musb, void *unused)
dsps_mod_timer_optional(glue);
break;
case OTG_STATE_A_WAIT_BCON:
+ /* keep VBUS on for host-only mode */
+ if (musb->port_mode == MUSB_PORT_MODE_HOST) {
+ dsps_mod_timer_optional(glue);
+ break;
+ }
musb_writeb(musb->mregs, MUSB_DEVCTL, 0);
skip_session = 1;
/* fall */
diff --git a/drivers/usb/musb/musb_host.c b/drivers/usb/musb/musb_host.c
index dbe617a735d8..76decb8011eb 100644
--- a/drivers/usb/musb/musb_host.c
+++ b/drivers/usb/musb/musb_host.c
@@ -1540,7 +1540,7 @@ static int musb_rx_dma_iso_cppi41(struct dma_controller *dma,
struct dma_channel *channel = hw_ep->rx_channel;
void __iomem *epio = hw_ep->regs;
dma_addr_t *buf;
- u32 length, res;
+ u32 length;
u16 val;
buf = (void *)urb->iso_frame_desc[qh->iso_idx].offset +
@@ -1552,10 +1552,8 @@ static int musb_rx_dma_iso_cppi41(struct dma_controller *dma,
val |= MUSB_RXCSR_DMAENAB;
musb_writew(hw_ep->regs, MUSB_RXCSR, val);
- res = dma->channel_program(channel, qh->maxpacket, 0,
+ return dma->channel_program(channel, qh->maxpacket, 0,
(u32)buf, length);
-
- return res;
}
#else
static inline int musb_rx_dma_iso_cppi41(struct dma_controller *dma,
diff --git a/drivers/usb/musb/tusb6010.c b/drivers/usb/musb/tusb6010.c
index e85cc8e4e7a9..4eb640c54f2c 100644
--- a/drivers/usb/musb/tusb6010.c
+++ b/drivers/usb/musb/tusb6010.c
@@ -881,26 +881,14 @@ static irqreturn_t tusb_musb_interrupt(int irq, void *__hci)
| TUSB_INT_SRC_ID_STATUS_CHNG))
idle_timeout = tusb_otg_ints(musb, int_src, tbase);
- /* TX dma callback must be handled here, RX dma callback is
- * handled in tusb_omap_dma_cb.
+ /*
+ * Just clear the DMA interrupt if it comes as the completion for both
+ * TX and RX is handled by the DMA callback in tusb6010_omap
*/
if ((int_src & TUSB_INT_SRC_TXRX_DMA_DONE)) {
u32 dma_src = musb_readl(tbase, TUSB_DMA_INT_SRC);
- u32 real_dma_src = musb_readl(tbase, TUSB_DMA_INT_MASK);
dev_dbg(musb->controller, "DMA IRQ %08x\n", dma_src);
- real_dma_src = ~real_dma_src & dma_src;
- if (tusb_dma_omap(musb) && real_dma_src) {
- int tx_source = (real_dma_src & 0xffff);
- int i;
-
- for (i = 1; i <= 15; i++) {
- if (tx_source & (1 << i)) {
- dev_dbg(musb->controller, "completing ep%i %s\n", i, "tx");
- musb_dma_completion(musb, i, 1);
- }
- }
- }
musb_writel(tbase, TUSB_DMA_INT_CLEAR, dma_src);
}
@@ -1181,7 +1169,8 @@ static int tusb_musb_exit(struct musb *musb)
}
static const struct musb_platform_ops tusb_ops = {
- .quirks = MUSB_DMA_TUSB_OMAP | MUSB_IN_TUSB,
+ .quirks = MUSB_DMA_TUSB_OMAP | MUSB_IN_TUSB |
+ MUSB_G_NO_SKB_RESERVE,
.init = tusb_musb_init,
.exit = tusb_musb_exit,
diff --git a/drivers/usb/musb/tusb6010_omap.c b/drivers/usb/musb/tusb6010_omap.c
index 7870b37e0ea5..e8060e49b0f4 100644
--- a/drivers/usb/musb/tusb6010_omap.c
+++ b/drivers/usb/musb/tusb6010_omap.c
@@ -15,7 +15,7 @@
#include <linux/platform_device.h>
#include <linux/dma-mapping.h>
#include <linux/slab.h>
-#include <linux/omap-dma.h>
+#include <linux/dmaengine.h>
#include "musb_core.h"
#include "tusb6010.h"
@@ -24,12 +24,10 @@
#define MAX_DMAREQ 5 /* REVISIT: Really 6, but req5 not OK */
-#define OMAP24XX_DMA_EXT_DMAREQ0 2
-#define OMAP24XX_DMA_EXT_DMAREQ1 3
-#define OMAP242X_DMA_EXT_DMAREQ2 14
-#define OMAP242X_DMA_EXT_DMAREQ3 15
-#define OMAP242X_DMA_EXT_DMAREQ4 16
-#define OMAP242X_DMA_EXT_DMAREQ5 64
+struct tusb_dma_data {
+ s8 dmareq;
+ struct dma_chan *chan;
+};
struct tusb_omap_dma_ch {
struct musb *musb;
@@ -39,9 +37,7 @@ struct tusb_omap_dma_ch {
u8 tx;
struct musb_hw_ep *hw_ep;
- int ch;
- s8 dmareq;
- s8 sync_dev;
+ struct tusb_dma_data *dma_data;
struct tusb_omap_dma *tusb_dma;
@@ -58,9 +54,7 @@ struct tusb_omap_dma {
struct dma_controller controller;
void __iomem *tbase;
- int ch;
- s8 dmareq;
- s8 sync_dev;
+ struct tusb_dma_data dma_pool[MAX_DMAREQ];
unsigned multichannel:1;
};
@@ -103,7 +97,7 @@ static inline void tusb_omap_free_shared_dmareq(struct tusb_omap_dma_ch *chdat)
* See also musb_dma_completion in plat_uds.c and musb_g_[tx|rx]() in
* musb_gadget.c.
*/
-static void tusb_omap_dma_cb(int lch, u16 ch_status, void *data)
+static void tusb_omap_dma_cb(void *data)
{
struct dma_channel *channel = (struct dma_channel *)data;
struct tusb_omap_dma_ch *chdat = to_chdat(channel);
@@ -114,21 +108,11 @@ static void tusb_omap_dma_cb(int lch, u16 ch_status, void *data)
void __iomem *ep_conf = hw_ep->conf;
void __iomem *mbase = musb->mregs;
unsigned long remaining, flags, pio;
- int ch;
spin_lock_irqsave(&musb->lock, flags);
- if (tusb_dma->multichannel)
- ch = chdat->ch;
- else
- ch = tusb_dma->ch;
-
- if (ch_status != OMAP_DMA_BLOCK_IRQ)
- printk(KERN_ERR "TUSB DMA error status: %i\n", ch_status);
-
- dev_dbg(musb->controller, "ep%i %s dma callback ch: %i status: %x\n",
- chdat->epnum, chdat->tx ? "tx" : "rx",
- ch, ch_status);
+ dev_dbg(musb->controller, "ep%i %s dma callback\n",
+ chdat->epnum, chdat->tx ? "tx" : "rx");
if (chdat->tx)
remaining = musb_readl(ep_conf, TUSB_EP_TX_OFFSET);
@@ -139,9 +123,8 @@ static void tusb_omap_dma_cb(int lch, u16 ch_status, void *data)
/* HW issue #10: XFR_SIZE may get corrupt on DMA (both async & sync) */
if (unlikely(remaining > chdat->transfer_len)) {
- dev_dbg(musb->controller, "Corrupt %s dma ch%i XFR_SIZE: 0x%08lx\n",
- chdat->tx ? "tx" : "rx", chdat->ch,
- remaining);
+ dev_dbg(musb->controller, "Corrupt %s XFR_SIZE: 0x%08lx\n",
+ chdat->tx ? "tx" : "rx", remaining);
remaining = 0;
}
@@ -175,13 +158,7 @@ static void tusb_omap_dma_cb(int lch, u16 ch_status, void *data)
channel->status = MUSB_DMA_STATUS_FREE;
- /* Handle only RX callbacks here. TX callbacks must be handled based
- * on the TUSB DMA status interrupt.
- * REVISIT: Use both TUSB DMA status interrupt and OMAP DMA callback
- * interrupt for RX and TX.
- */
- if (!chdat->tx)
- musb_dma_completion(musb, chdat->epnum, chdat->tx);
+ musb_dma_completion(musb, chdat->epnum, chdat->tx);
/* We must terminate short tx transfers manually by setting TXPKTRDY.
* REVISIT: This same problem may occur with other MUSB dma as well.
@@ -214,15 +191,16 @@ static int tusb_omap_dma_program(struct dma_channel *channel, u16 packet_sz,
struct musb_hw_ep *hw_ep = chdat->hw_ep;
void __iomem *mbase = musb->mregs;
void __iomem *ep_conf = hw_ep->conf;
- dma_addr_t fifo = hw_ep->fifo_sync;
- struct omap_dma_channel_params dma_params;
+ dma_addr_t fifo_addr = hw_ep->fifo_sync;
u32 dma_remaining;
- int src_burst, dst_burst;
u16 csr;
u32 psize;
- int ch;
- s8 dmareq;
- s8 sync_dev;
+ struct tusb_dma_data *dma_data;
+ struct dma_async_tx_descriptor *dma_desc;
+ struct dma_slave_config dma_cfg;
+ enum dma_transfer_direction dma_dir;
+ u32 port_window;
+ int ret;
if (unlikely(dma_addr & 0x1) || (len < 32) || (len > packet_sz))
return false;
@@ -248,9 +226,8 @@ static int tusb_omap_dma_program(struct dma_channel *channel, u16 packet_sz,
dma_remaining = TUSB_EP_CONFIG_XFR_SIZE(dma_remaining);
if (dma_remaining) {
- dev_dbg(musb->controller, "Busy %s dma ch%i, not using: %08x\n",
- chdat->tx ? "tx" : "rx", chdat->ch,
- dma_remaining);
+ dev_dbg(musb->controller, "Busy %s dma, not using: %08x\n",
+ chdat->tx ? "tx" : "rx", dma_remaining);
return false;
}
@@ -261,27 +238,19 @@ static int tusb_omap_dma_program(struct dma_channel *channel, u16 packet_sz,
else
chdat->transfer_packet_sz = packet_sz;
- if (tusb_dma->multichannel) {
- ch = chdat->ch;
- dmareq = chdat->dmareq;
- sync_dev = chdat->sync_dev;
- } else {
+ dma_data = chdat->dma_data;
+ if (!tusb_dma->multichannel) {
if (tusb_omap_use_shared_dmareq(chdat) != 0) {
dev_dbg(musb->controller, "could not get dma for ep%i\n", chdat->epnum);
return false;
}
- if (tusb_dma->ch < 0) {
+ if (dma_data->dmareq < 0) {
/* REVISIT: This should get blocked earlier, happens
* with MSC ErrorRecoveryTest
*/
WARN_ON(1);
return false;
}
-
- ch = tusb_dma->ch;
- dmareq = tusb_dma->dmareq;
- sync_dev = tusb_dma->sync_dev;
- omap_set_dma_callback(ch, tusb_omap_dma_cb, channel);
}
chdat->packet_sz = packet_sz;
@@ -291,92 +260,80 @@ static int tusb_omap_dma_program(struct dma_channel *channel, u16 packet_sz,
channel->status = MUSB_DMA_STATUS_BUSY;
/* Since we're recycling dma areas, we need to clean or invalidate */
- if (chdat->tx)
+ if (chdat->tx) {
+ dma_dir = DMA_MEM_TO_DEV;
dma_map_single(dev, phys_to_virt(dma_addr), len,
DMA_TO_DEVICE);
- else
+ } else {
+ dma_dir = DMA_DEV_TO_MEM;
dma_map_single(dev, phys_to_virt(dma_addr), len,
DMA_FROM_DEVICE);
+ }
+
+ memset(&dma_cfg, 0, sizeof(dma_cfg));
/* Use 16-bit transfer if dma_addr is not 32-bit aligned */
if ((dma_addr & 0x3) == 0) {
- dma_params.data_type = OMAP_DMA_DATA_TYPE_S32;
- dma_params.elem_count = 8; /* Elements in frame */
+ dma_cfg.src_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
+ dma_cfg.dst_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
+ port_window = 8;
} else {
- dma_params.data_type = OMAP_DMA_DATA_TYPE_S16;
- dma_params.elem_count = 16; /* Elements in frame */
- fifo = hw_ep->fifo_async;
- }
+ dma_cfg.src_addr_width = DMA_SLAVE_BUSWIDTH_2_BYTES;
+ dma_cfg.dst_addr_width = DMA_SLAVE_BUSWIDTH_2_BYTES;
+ port_window = 16;
- dma_params.frame_count = chdat->transfer_len / 32; /* Burst sz frame */
+ fifo_addr = hw_ep->fifo_async;
+ }
- dev_dbg(musb->controller, "ep%i %s dma ch%i dma: %pad len: %u(%u) packet_sz: %i(%i)\n",
- chdat->epnum, chdat->tx ? "tx" : "rx",
- ch, &dma_addr, chdat->transfer_len, len,
- chdat->transfer_packet_sz, packet_sz);
+ dev_dbg(musb->controller,
+ "ep%i %s dma: %pad len: %u(%u) packet_sz: %i(%i)\n",
+ chdat->epnum, chdat->tx ? "tx" : "rx", &dma_addr,
+ chdat->transfer_len, len, chdat->transfer_packet_sz, packet_sz);
+
+ dma_cfg.src_addr = fifo_addr;
+ dma_cfg.dst_addr = fifo_addr;
+ dma_cfg.src_port_window_size = port_window;
+ dma_cfg.src_maxburst = port_window;
+ dma_cfg.dst_port_window_size = port_window;
+ dma_cfg.dst_maxburst = port_window;
+
+ ret = dmaengine_slave_config(dma_data->chan, &dma_cfg);
+ if (ret) {
+ dev_err(musb->controller, "DMA slave config failed: %d\n", ret);
+ return false;
+ }
- /*
- * Prepare omap DMA for transfer
- */
- if (chdat->tx) {
- dma_params.src_amode = OMAP_DMA_AMODE_POST_INC;
- dma_params.src_start = (unsigned long)dma_addr;
- dma_params.src_ei = 0;
- dma_params.src_fi = 0;
-
- dma_params.dst_amode = OMAP_DMA_AMODE_DOUBLE_IDX;
- dma_params.dst_start = (unsigned long)fifo;
- dma_params.dst_ei = 1;
- dma_params.dst_fi = -31; /* Loop 32 byte window */
-
- dma_params.trigger = sync_dev;
- dma_params.sync_mode = OMAP_DMA_SYNC_FRAME;
- dma_params.src_or_dst_synch = 0; /* Dest sync */
-
- src_burst = OMAP_DMA_DATA_BURST_16; /* 16x32 read */
- dst_burst = OMAP_DMA_DATA_BURST_8; /* 8x32 write */
- } else {
- dma_params.src_amode = OMAP_DMA_AMODE_DOUBLE_IDX;
- dma_params.src_start = (unsigned long)fifo;
- dma_params.src_ei = 1;
- dma_params.src_fi = -31; /* Loop 32 byte window */
-
- dma_params.dst_amode = OMAP_DMA_AMODE_POST_INC;
- dma_params.dst_start = (unsigned long)dma_addr;
- dma_params.dst_ei = 0;
- dma_params.dst_fi = 0;
-
- dma_params.trigger = sync_dev;
- dma_params.sync_mode = OMAP_DMA_SYNC_FRAME;
- dma_params.src_or_dst_synch = 1; /* Source sync */
-
- src_burst = OMAP_DMA_DATA_BURST_8; /* 8x32 read */
- dst_burst = OMAP_DMA_DATA_BURST_16; /* 16x32 write */
+ dma_desc = dmaengine_prep_slave_single(dma_data->chan, dma_addr,
+ chdat->transfer_len, dma_dir,
+ DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
+ if (!dma_desc) {
+ dev_err(musb->controller, "DMA prep_slave_single failed\n");
+ return false;
}
- dev_dbg(musb->controller, "ep%i %s using %i-bit %s dma from 0x%08lx to 0x%08lx\n",
+ dma_desc->callback = tusb_omap_dma_cb;
+ dma_desc->callback_param = channel;
+ dmaengine_submit(dma_desc);
+
+ dev_dbg(musb->controller,
+ "ep%i %s using %i-bit %s dma from %pad to %pad\n",
chdat->epnum, chdat->tx ? "tx" : "rx",
- (dma_params.data_type == OMAP_DMA_DATA_TYPE_S32) ? 32 : 16,
+ dma_cfg.src_addr_width * 8,
((dma_addr & 0x3) == 0) ? "sync" : "async",
- dma_params.src_start, dma_params.dst_start);
-
- omap_set_dma_params(ch, &dma_params);
- omap_set_dma_src_burst_mode(ch, src_burst);
- omap_set_dma_dest_burst_mode(ch, dst_burst);
- omap_set_dma_write_mode(ch, OMAP_DMA_WRITE_LAST_NON_POSTED);
+ (dma_dir == DMA_MEM_TO_DEV) ? &dma_addr : &fifo_addr,
+ (dma_dir == DMA_MEM_TO_DEV) ? &fifo_addr : &dma_addr);
/*
* Prepare MUSB for DMA transfer
*/
+ musb_ep_select(mbase, chdat->epnum);
if (chdat->tx) {
- musb_ep_select(mbase, chdat->epnum);
csr = musb_readw(hw_ep->regs, MUSB_TXCSR);
csr |= (MUSB_TXCSR_AUTOSET | MUSB_TXCSR_DMAENAB
| MUSB_TXCSR_DMAMODE | MUSB_TXCSR_MODE);
csr &= ~MUSB_TXCSR_P_UNDERRUN;
musb_writew(hw_ep->regs, MUSB_TXCSR, csr);
} else {
- musb_ep_select(mbase, chdat->epnum);
csr = musb_readw(hw_ep->regs, MUSB_RXCSR);
csr |= MUSB_RXCSR_DMAENAB;
csr &= ~(MUSB_RXCSR_AUTOCLEAR | MUSB_RXCSR_DMAMODE);
@@ -384,10 +341,8 @@ static int tusb_omap_dma_program(struct dma_channel *channel, u16 packet_sz,
csr | MUSB_RXCSR_P_WZC_BITS);
}
- /*
- * Start DMA transfer
- */
- omap_start_dma(ch);
+ /* Start DMA transfer */
+ dma_async_issue_pending(dma_data->chan);
if (chdat->tx) {
/* Send transfer_packet_sz packets at a time */
@@ -415,18 +370,9 @@ static int tusb_omap_dma_program(struct dma_channel *channel, u16 packet_sz,
static int tusb_omap_dma_abort(struct dma_channel *channel)
{
struct tusb_omap_dma_ch *chdat = to_chdat(channel);
- struct tusb_omap_dma *tusb_dma = chdat->tusb_dma;
- if (!tusb_dma->multichannel) {
- if (tusb_dma->ch >= 0) {
- omap_stop_dma(tusb_dma->ch);
- omap_free_dma(tusb_dma->ch);
- tusb_dma->ch = -1;
- }
-
- tusb_dma->dmareq = -1;
- tusb_dma->sync_dev = -1;
- }
+ if (chdat->dma_data)
+ dmaengine_terminate_all(chdat->dma_data->chan);
channel->status = MUSB_DMA_STATUS_FREE;
@@ -438,15 +384,6 @@ static inline int tusb_omap_dma_allocate_dmareq(struct tusb_omap_dma_ch *chdat)
u32 reg = musb_readl(chdat->tbase, TUSB_DMA_EP_MAP);
int i, dmareq_nr = -1;
- const int sync_dev[6] = {
- OMAP24XX_DMA_EXT_DMAREQ0,
- OMAP24XX_DMA_EXT_DMAREQ1,
- OMAP242X_DMA_EXT_DMAREQ2,
- OMAP242X_DMA_EXT_DMAREQ3,
- OMAP242X_DMA_EXT_DMAREQ4,
- OMAP242X_DMA_EXT_DMAREQ5,
- };
-
for (i = 0; i < MAX_DMAREQ; i++) {
int cur = (reg & (0xf << (i * 5))) >> (i * 5);
if (cur == 0) {
@@ -463,8 +400,7 @@ static inline int tusb_omap_dma_allocate_dmareq(struct tusb_omap_dma_ch *chdat)
reg |= ((1 << 4) << (dmareq_nr * 5));
musb_writel(chdat->tbase, TUSB_DMA_EP_MAP, reg);
- chdat->dmareq = dmareq_nr;
- chdat->sync_dev = sync_dev[chdat->dmareq];
+ chdat->dma_data = &chdat->tusb_dma->dma_pool[dmareq_nr];
return 0;
}
@@ -473,15 +409,14 @@ static inline void tusb_omap_dma_free_dmareq(struct tusb_omap_dma_ch *chdat)
{
u32 reg;
- if (!chdat || chdat->dmareq < 0)
+ if (!chdat || !chdat->dma_data || chdat->dma_data->dmareq < 0)
return;
reg = musb_readl(chdat->tbase, TUSB_DMA_EP_MAP);
- reg &= ~(0x1f << (chdat->dmareq * 5));
+ reg &= ~(0x1f << (chdat->dma_data->dmareq * 5));
musb_writel(chdat->tbase, TUSB_DMA_EP_MAP, reg);
- chdat->dmareq = -1;
- chdat->sync_dev = -1;
+ chdat->dma_data = NULL;
}
static struct dma_channel *dma_channel_pool[MAX_DMAREQ];
@@ -492,24 +427,14 @@ tusb_omap_dma_allocate(struct dma_controller *c,
u8 tx)
{
int ret, i;
- const char *dev_name;
struct tusb_omap_dma *tusb_dma;
struct musb *musb;
- void __iomem *tbase;
struct dma_channel *channel = NULL;
struct tusb_omap_dma_ch *chdat = NULL;
- u32 reg;
+ struct tusb_dma_data *dma_data = NULL;
tusb_dma = container_of(c, struct tusb_omap_dma, controller);
musb = tusb_dma->controller.musb;
- tbase = musb->ctrl_base;
-
- reg = musb_readl(tbase, TUSB_DMA_INT_MASK);
- if (tx)
- reg &= ~(1 << hw_ep->epnum);
- else
- reg &= ~(1 << (hw_ep->epnum + 15));
- musb_writel(tbase, TUSB_DMA_INT_MASK, reg);
/* REVISIT: Why does dmareq5 not work? */
if (hw_ep->epnum == 0) {
@@ -530,56 +455,38 @@ tusb_omap_dma_allocate(struct dma_controller *c,
if (!channel)
return NULL;
- if (tx) {
- chdat->tx = 1;
- dev_name = "TUSB transmit";
- } else {
- chdat->tx = 0;
- dev_name = "TUSB receive";
- }
-
chdat->musb = tusb_dma->controller.musb;
chdat->tbase = tusb_dma->tbase;
chdat->hw_ep = hw_ep;
chdat->epnum = hw_ep->epnum;
- chdat->dmareq = -1;
chdat->completed_len = 0;
chdat->tusb_dma = tusb_dma;
+ if (tx)
+ chdat->tx = 1;
+ else
+ chdat->tx = 0;
channel->max_len = 0x7fffffff;
channel->desired_mode = 0;
channel->actual_len = 0;
- if (tusb_dma->multichannel) {
- ret = tusb_omap_dma_allocate_dmareq(chdat);
- if (ret != 0)
- goto free_dmareq;
-
- ret = omap_request_dma(chdat->sync_dev, dev_name,
- tusb_omap_dma_cb, channel, &chdat->ch);
- if (ret != 0)
- goto free_dmareq;
- } else if (tusb_dma->ch == -1) {
- tusb_dma->dmareq = 0;
- tusb_dma->sync_dev = OMAP24XX_DMA_EXT_DMAREQ0;
-
- /* Callback data gets set later in the shared dmareq case */
- ret = omap_request_dma(tusb_dma->sync_dev, "TUSB shared",
- tusb_omap_dma_cb, NULL, &tusb_dma->ch);
- if (ret != 0)
- goto free_dmareq;
-
- chdat->dmareq = -1;
- chdat->ch = -1;
+ if (!chdat->dma_data) {
+ if (tusb_dma->multichannel) {
+ ret = tusb_omap_dma_allocate_dmareq(chdat);
+ if (ret != 0)
+ goto free_dmareq;
+ } else {
+ chdat->dma_data = &tusb_dma->dma_pool[0];
+ }
}
- dev_dbg(musb->controller, "ep%i %s dma: %s dma%i dmareq%i sync%i\n",
+ dma_data = chdat->dma_data;
+
+ dev_dbg(musb->controller, "ep%i %s dma: %s dmareq%i\n",
chdat->epnum,
chdat->tx ? "tx" : "rx",
- chdat->ch >= 0 ? "dedicated" : "shared",
- chdat->ch >= 0 ? chdat->ch : tusb_dma->ch,
- chdat->dmareq >= 0 ? chdat->dmareq : tusb_dma->dmareq,
- chdat->sync_dev >= 0 ? chdat->sync_dev : tusb_dma->sync_dev);
+ tusb_dma->multichannel ? "shared" : "dedicated",
+ dma_data->dmareq);
return channel;
@@ -596,35 +503,13 @@ static void tusb_omap_dma_release(struct dma_channel *channel)
{
struct tusb_omap_dma_ch *chdat = to_chdat(channel);
struct musb *musb = chdat->musb;
- void __iomem *tbase = musb->ctrl_base;
- u32 reg;
-
- dev_dbg(musb->controller, "ep%i ch%i\n", chdat->epnum, chdat->ch);
-
- reg = musb_readl(tbase, TUSB_DMA_INT_MASK);
- if (chdat->tx)
- reg |= (1 << chdat->epnum);
- else
- reg |= (1 << (chdat->epnum + 15));
- musb_writel(tbase, TUSB_DMA_INT_MASK, reg);
- reg = musb_readl(tbase, TUSB_DMA_INT_CLEAR);
- if (chdat->tx)
- reg |= (1 << chdat->epnum);
- else
- reg |= (1 << (chdat->epnum + 15));
- musb_writel(tbase, TUSB_DMA_INT_CLEAR, reg);
+ dev_dbg(musb->controller, "Release for ep%i\n", chdat->epnum);
channel->status = MUSB_DMA_STATUS_UNKNOWN;
- if (chdat->ch >= 0) {
- omap_stop_dma(chdat->ch);
- omap_free_dma(chdat->ch);
- chdat->ch = -1;
- }
-
- if (chdat->dmareq >= 0)
- tusb_omap_dma_free_dmareq(chdat);
+ dmaengine_terminate_sync(chdat->dma_data->chan);
+ tusb_omap_dma_free_dmareq(chdat);
channel = NULL;
}
@@ -641,15 +526,62 @@ void tusb_dma_controller_destroy(struct dma_controller *c)
kfree(ch->private_data);
kfree(ch);
}
- }
- if (tusb_dma && !tusb_dma->multichannel && tusb_dma->ch >= 0)
- omap_free_dma(tusb_dma->ch);
+ /* Free up the DMA channels */
+ if (tusb_dma && tusb_dma->dma_pool[i].chan)
+ dma_release_channel(tusb_dma->dma_pool[i].chan);
+ }
kfree(tusb_dma);
}
EXPORT_SYMBOL_GPL(tusb_dma_controller_destroy);
+static int tusb_omap_allocate_dma_pool(struct tusb_omap_dma *tusb_dma)
+{
+ struct musb *musb = tusb_dma->controller.musb;
+ int i;
+ int ret = 0;
+
+ for (i = 0; i < MAX_DMAREQ; i++) {
+ struct tusb_dma_data *dma_data = &tusb_dma->dma_pool[i];
+
+ /*
+ * Request DMA channels:
+ * - one channel in case of non multichannel mode
+ * - MAX_DMAREQ number of channels in multichannel mode
+ */
+ if (i == 0 || tusb_dma->multichannel) {
+ char ch_name[8];
+
+ sprintf(ch_name, "dmareq%d", i);
+ dma_data->chan = dma_request_chan(musb->controller,
+ ch_name);
+ if (IS_ERR(dma_data->chan)) {
+ dev_err(musb->controller,
+ "Failed to request %s\n", ch_name);
+ ret = PTR_ERR(dma_data->chan);
+ goto dma_error;
+ }
+
+ dma_data->dmareq = i;
+ } else {
+ dma_data->dmareq = -1;
+ }
+ }
+
+ return 0;
+
+dma_error:
+ for (; i >= 0; i--) {
+ struct tusb_dma_data *dma_data = &tusb_dma->dma_pool[i];
+
+ if (dma_data->dmareq >= 0)
+ dma_release_channel(dma_data->chan);
+ }
+
+ return ret;
+}
+
struct dma_controller *
tusb_dma_controller_create(struct musb *musb, void __iomem *base)
{
@@ -674,10 +606,6 @@ tusb_dma_controller_create(struct musb *musb, void __iomem *base)
tusb_dma->controller.musb = musb;
tusb_dma->tbase = musb->ctrl_base;
- tusb_dma->ch = -1;
- tusb_dma->dmareq = -1;
- tusb_dma->sync_dev = -1;
-
tusb_dma->controller.channel_alloc = tusb_omap_dma_allocate;
tusb_dma->controller.channel_release = tusb_omap_dma_release;
tusb_dma->controller.channel_program = tusb_omap_dma_program;
@@ -704,6 +632,9 @@ tusb_dma_controller_create(struct musb *musb, void __iomem *base)
ch->private_data = chdat;
}
+ if (tusb_omap_allocate_dma_pool(tusb_dma))
+ goto cleanup;
+
return &tusb_dma->controller;
cleanup:
diff --git a/drivers/usb/phy/Kconfig b/drivers/usb/phy/Kconfig
index 3006f569c068..aff702c0eb9f 100644
--- a/drivers/usb/phy/Kconfig
+++ b/drivers/usb/phy/Kconfig
@@ -4,6 +4,7 @@
menu "USB Physical Layer drivers"
config USB_PHY
+ select EXTCON
def_bool n
#
@@ -109,7 +110,7 @@ config OMAP_OTG
config TAHVO_USB
tristate "Tahvo USB transceiver driver"
- depends on MFD_RETU && EXTCON
+ depends on MFD_RETU
depends on USB_GADGET || !USB_GADGET # if USB_GADGET=m, this can't be 'y'
select USB_PHY
help
@@ -141,7 +142,6 @@ config USB_MSM_OTG
depends on (USB || USB_GADGET) && (ARCH_QCOM || COMPILE_TEST)
depends on USB_GADGET || !USB_GADGET # if USB_GADGET=m, this can't be 'y'
depends on RESET_CONTROLLER
- depends on EXTCON
select USB_PHY
help
Enable this to support the USB OTG transceiver on Qualcomm chips. It
@@ -155,7 +155,7 @@ config USB_MSM_OTG
config USB_QCOM_8X16_PHY
tristate "Qualcomm APQ8016/MSM8916 on-chip USB PHY controller support"
depends on ARCH_QCOM || COMPILE_TEST
- depends on RESET_CONTROLLER && EXTCON
+ depends on RESET_CONTROLLER
select USB_PHY
select USB_ULPI_VIEWPORT
help
diff --git a/drivers/usb/phy/phy-msm-usb.c b/drivers/usb/phy/phy-msm-usb.c
index 93d9aaad2994..8fb86a5f458e 100644
--- a/drivers/usb/phy/phy-msm-usb.c
+++ b/drivers/usb/phy/phy-msm-usb.c
@@ -146,17 +146,6 @@ struct msm_otg_platform_data {
};
/**
- * struct msm_usb_cable - structure for exteternal connector cable
- * state tracking
- * @nb: hold event notification callback
- * @conn: used for notification registration
- */
-struct msm_usb_cable {
- struct notifier_block nb;
- struct extcon_dev *extcon;
-};
-
-/**
* struct msm_otg: OTG driver data. Shared by HCD and DCD.
* @otg: USB OTG Transceiver structure.
* @pdata: otg device platform data.
@@ -215,9 +204,6 @@ struct msm_otg {
bool manual_pullup;
- struct msm_usb_cable vbus;
- struct msm_usb_cable id;
-
struct gpio_desc *switch_gpio;
struct notifier_block reboot;
};
@@ -1612,8 +1598,8 @@ MODULE_DEVICE_TABLE(of, msm_otg_dt_match);
static int msm_otg_vbus_notifier(struct notifier_block *nb, unsigned long event,
void *ptr)
{
- struct msm_usb_cable *vbus = container_of(nb, struct msm_usb_cable, nb);
- struct msm_otg *motg = container_of(vbus, struct msm_otg, vbus);
+ struct usb_phy *usb_phy = container_of(nb, struct usb_phy, vbus_nb);
+ struct msm_otg *motg = container_of(usb_phy, struct msm_otg, phy);
if (event)
set_bit(B_SESS_VLD, &motg->inputs);
@@ -1636,8 +1622,8 @@ static int msm_otg_vbus_notifier(struct notifier_block *nb, unsigned long event,
static int msm_otg_id_notifier(struct notifier_block *nb, unsigned long event,
void *ptr)
{
- struct msm_usb_cable *id = container_of(nb, struct msm_usb_cable, nb);
- struct msm_otg *motg = container_of(id, struct msm_otg, id);
+ struct usb_phy *usb_phy = container_of(nb, struct usb_phy, id_nb);
+ struct msm_otg *motg = container_of(usb_phy, struct msm_otg, phy);
if (event)
clear_bit(ID, &motg->inputs);
@@ -1652,7 +1638,6 @@ static int msm_otg_id_notifier(struct notifier_block *nb, unsigned long event,
static int msm_otg_read_dt(struct platform_device *pdev, struct msm_otg *motg)
{
struct msm_otg_platform_data *pdata;
- struct extcon_dev *ext_id, *ext_vbus;
struct device_node *node = pdev->dev.of_node;
struct property *prop;
int len, ret, words;
@@ -1708,54 +1693,6 @@ static int msm_otg_read_dt(struct platform_device *pdev, struct msm_otg *motg)
if (IS_ERR(motg->switch_gpio))
return PTR_ERR(motg->switch_gpio);
- ext_id = ERR_PTR(-ENODEV);
- ext_vbus = ERR_PTR(-ENODEV);
- if (of_property_read_bool(node, "extcon")) {
-
- /* Each one of them is not mandatory */
- ext_vbus = extcon_get_edev_by_phandle(&pdev->dev, 0);
- if (IS_ERR(ext_vbus) && PTR_ERR(ext_vbus) != -ENODEV)
- return PTR_ERR(ext_vbus);
-
- ext_id = extcon_get_edev_by_phandle(&pdev->dev, 1);
- if (IS_ERR(ext_id) && PTR_ERR(ext_id) != -ENODEV)
- return PTR_ERR(ext_id);
- }
-
- if (!IS_ERR(ext_vbus)) {
- motg->vbus.extcon = ext_vbus;
- motg->vbus.nb.notifier_call = msm_otg_vbus_notifier;
- ret = devm_extcon_register_notifier(&pdev->dev, ext_vbus,
- EXTCON_USB, &motg->vbus.nb);
- if (ret < 0) {
- dev_err(&pdev->dev, "register VBUS notifier failed\n");
- return ret;
- }
-
- ret = extcon_get_state(ext_vbus, EXTCON_USB);
- if (ret)
- set_bit(B_SESS_VLD, &motg->inputs);
- else
- clear_bit(B_SESS_VLD, &motg->inputs);
- }
-
- if (!IS_ERR(ext_id)) {
- motg->id.extcon = ext_id;
- motg->id.nb.notifier_call = msm_otg_id_notifier;
- ret = devm_extcon_register_notifier(&pdev->dev, ext_id,
- EXTCON_USB_HOST, &motg->id.nb);
- if (ret < 0) {
- dev_err(&pdev->dev, "register ID notifier failed\n");
- return ret;
- }
-
- ret = extcon_get_state(ext_id, EXTCON_USB_HOST);
- if (ret)
- clear_bit(ID, &motg->inputs);
- else
- set_bit(ID, &motg->inputs);
- }
-
prop = of_find_property(node, "qcom,phy-init-sequence", &len);
if (!prop || !len)
return 0;
@@ -1932,6 +1869,8 @@ static int msm_otg_probe(struct platform_device *pdev)
phy->init = msm_phy_init;
phy->notify_disconnect = msm_phy_notify_disconnect;
phy->type = USB_PHY_TYPE_USB2;
+ phy->vbus_nb.notifier_call = msm_otg_vbus_notifier;
+ phy->id_nb.notifier_call = msm_otg_id_notifier;
phy->io_ops = &msm_otg_io_ops;
@@ -1947,6 +1886,18 @@ static int msm_otg_probe(struct platform_device *pdev)
goto disable_ldo;
}
+ ret = extcon_get_state(phy->edev, EXTCON_USB);
+ if (ret)
+ set_bit(B_SESS_VLD, &motg->inputs);
+ else
+ clear_bit(B_SESS_VLD, &motg->inputs);
+
+ ret = extcon_get_state(phy->id_edev, EXTCON_USB_HOST);
+ if (ret)
+ clear_bit(ID, &motg->inputs);
+ else
+ set_bit(ID, &motg->inputs);
+
platform_set_drvdata(pdev, motg);
device_init_wakeup(&pdev->dev, 1);
diff --git a/drivers/usb/phy/phy-qcom-8x16-usb.c b/drivers/usb/phy/phy-qcom-8x16-usb.c
index fdf686398772..b6a83a5cbad3 100644
--- a/drivers/usb/phy/phy-qcom-8x16-usb.c
+++ b/drivers/usb/phy/phy-qcom-8x16-usb.c
@@ -69,9 +69,6 @@ struct phy_8x16 {
struct reset_control *phy_reset;
- struct extcon_dev *vbus_edev;
- struct notifier_block vbus_notify;
-
struct gpio_desc *switch_gpio;
struct notifier_block reboot_notify;
};
@@ -131,7 +128,8 @@ static int phy_8x16_vbus_off(struct phy_8x16 *qphy)
static int phy_8x16_vbus_notify(struct notifier_block *nb, unsigned long event,
void *ptr)
{
- struct phy_8x16 *qphy = container_of(nb, struct phy_8x16, vbus_notify);
+ struct usb_phy *usb_phy = container_of(nb, struct usb_phy, vbus_nb);
+ struct phy_8x16 *qphy = container_of(usb_phy, struct phy_8x16, phy);
if (event)
phy_8x16_vbus_on(qphy);
@@ -187,7 +185,7 @@ static int phy_8x16_init(struct usb_phy *phy)
val = ULPI_PWR_OTG_COMP_DISABLE;
usb_phy_io_write(phy, val, ULPI_SET(ULPI_PWR_CLK_MNG_REG));
- state = extcon_get_state(qphy->vbus_edev, EXTCON_USB);
+ state = extcon_get_state(qphy->phy.edev, EXTCON_USB);
if (state)
phy_8x16_vbus_on(qphy);
else
@@ -289,15 +287,13 @@ static int phy_8x16_probe(struct platform_device *pdev)
phy->io_priv = qphy->regs + HSPHY_ULPI_VIEWPORT;
phy->io_ops = &ulpi_viewport_access_ops;
phy->type = USB_PHY_TYPE_USB2;
+ phy->vbus_nb.notifier_call = phy_8x16_vbus_notify;
+ phy->id_nb.notifier_call = NULL;
ret = phy_8x16_read_devicetree(qphy);
if (ret < 0)
return ret;
- qphy->vbus_edev = extcon_get_edev_by_phandle(phy->dev, 0);
- if (IS_ERR(qphy->vbus_edev))
- return PTR_ERR(qphy->vbus_edev);
-
ret = clk_set_rate(qphy->core_clk, INT_MAX);
if (ret < 0)
dev_dbg(phy->dev, "Can't boost core clock\n");
@@ -315,12 +311,6 @@ static int phy_8x16_probe(struct platform_device *pdev)
if (WARN_ON(ret))
goto off_clks;
- qphy->vbus_notify.notifier_call = phy_8x16_vbus_notify;
- ret = devm_extcon_register_notifier(&pdev->dev, qphy->vbus_edev,
- EXTCON_USB, &qphy->vbus_notify);
- if (ret < 0)
- goto off_power;
-
ret = usb_add_phy_dev(&qphy->phy);
if (ret)
goto off_power;
diff --git a/drivers/usb/phy/phy.c b/drivers/usb/phy/phy.c
index 98f75d2842b7..032f5afaad4b 100644
--- a/drivers/usb/phy/phy.c
+++ b/drivers/usb/phy/phy.c
@@ -100,6 +100,54 @@ static int devm_usb_phy_match(struct device *dev, void *res, void *match_data)
return *phy == match_data;
}
+static int usb_add_extcon(struct usb_phy *x)
+{
+ int ret;
+
+ if (of_property_read_bool(x->dev->of_node, "extcon")) {
+ x->edev = extcon_get_edev_by_phandle(x->dev, 0);
+ if (IS_ERR(x->edev))
+ return PTR_ERR(x->edev);
+
+ x->id_edev = extcon_get_edev_by_phandle(x->dev, 1);
+ if (IS_ERR(x->id_edev)) {
+ x->id_edev = NULL;
+ dev_info(x->dev, "No separate ID extcon device\n");
+ }
+
+ if (x->vbus_nb.notifier_call) {
+ ret = devm_extcon_register_notifier(x->dev, x->edev,
+ EXTCON_USB,
+ &x->vbus_nb);
+ if (ret < 0) {
+ dev_err(x->dev,
+ "register VBUS notifier failed\n");
+ return ret;
+ }
+ }
+
+ if (x->id_nb.notifier_call) {
+ struct extcon_dev *id_ext;
+
+ if (x->id_edev)
+ id_ext = x->id_edev;
+ else
+ id_ext = x->edev;
+
+ ret = devm_extcon_register_notifier(x->dev, id_ext,
+ EXTCON_USB_HOST,
+ &x->id_nb);
+ if (ret < 0) {
+ dev_err(x->dev,
+ "register ID notifier failed\n");
+ return ret;
+ }
+ }
+ }
+
+ return 0;
+}
+
/**
* devm_usb_get_phy - find the USB PHY
* @dev - device that requests this phy
@@ -388,6 +436,10 @@ int usb_add_phy(struct usb_phy *x, enum usb_phy_type type)
return -EINVAL;
}
+ ret = usb_add_extcon(x);
+ if (ret)
+ return ret;
+
ATOMIC_INIT_NOTIFIER_HEAD(&x->notifier);
spin_lock_irqsave(&phy_lock, flags);
@@ -422,12 +474,17 @@ int usb_add_phy_dev(struct usb_phy *x)
{
struct usb_phy_bind *phy_bind;
unsigned long flags;
+ int ret;
if (!x->dev) {
dev_err(x->dev, "no device provided for PHY\n");
return -EINVAL;
}
+ ret = usb_add_extcon(x);
+ if (ret)
+ return ret;
+
ATOMIC_INIT_NOTIFIER_HEAD(&x->notifier);
spin_lock_irqsave(&phy_lock, flags);
diff --git a/drivers/usb/serial/cp210x.c b/drivers/usb/serial/cp210x.c
index 0c55e7f64269..f64e914a8985 100644
--- a/drivers/usb/serial/cp210x.c
+++ b/drivers/usb/serial/cp210x.c
@@ -141,6 +141,7 @@ static const struct usb_device_id id_table[] = {
{ USB_DEVICE(0x10C4, 0x8977) }, /* CEL MeshWorks DevKit Device */
{ USB_DEVICE(0x10C4, 0x8998) }, /* KCF Technologies PRN */
{ USB_DEVICE(0x10C4, 0x8A2A) }, /* HubZ dual ZigBee and Z-Wave dongle */
+ { USB_DEVICE(0x10C4, 0x8A5E) }, /* CEL EM3588 ZigBee USB Stick Long Range */
{ USB_DEVICE(0x10C4, 0xEA60) }, /* Silicon Labs factory default */
{ USB_DEVICE(0x10C4, 0xEA61) }, /* Silicon Labs factory default */
{ USB_DEVICE(0x10C4, 0xEA70) }, /* Silicon Labs factory default */
diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c
index aba74f817dc6..1cec03799cdf 100644
--- a/drivers/usb/serial/ftdi_sio.c
+++ b/drivers/usb/serial/ftdi_sio.c
@@ -1244,42 +1244,13 @@ static __u32 get_ftdi_divisor(struct tty_struct *tty,
int div_okay = 1;
int baud;
- /*
- * The logic involved in setting the baudrate can be cleanly split into
- * 3 steps.
- * 1. Standard baud rates are set in tty->termios->c_cflag
- * 2. If these are not enough, you can set any speed using alt_speed as
- * follows:
- * - set tty->termios->c_cflag speed to B38400
- * - set your real speed in tty->alt_speed; it gets ignored when
- * alt_speed==0, (or)
- * - call TIOCSSERIAL ioctl with (struct serial_struct) set as
- * follows:
- * flags & ASYNC_SPD_MASK == ASYNC_SPD_[HI, VHI, SHI, WARP],
- * this just sets alt_speed to (HI: 57600, VHI: 115200,
- * SHI: 230400, WARP: 460800)
- * ** Steps 1, 2 are done courtesy of tty_get_baud_rate
- * 3. You can also set baud rate by setting custom divisor as follows
- * - set tty->termios->c_cflag speed to B38400
- * - call TIOCSSERIAL ioctl with (struct serial_struct) set as
- * follows:
- * o flags & ASYNC_SPD_MASK == ASYNC_SPD_CUST
- * o custom_divisor set to baud_base / your_new_baudrate
- * ** Step 3 is done courtesy of code borrowed from serial.c
- * I should really spend some time and separate + move this common
- * code to serial.c, it is replicated in nearly every serial driver
- * you see.
- */
-
- /* 1. Get the baud rate from the tty settings, this observes
- alt_speed hack */
-
baud = tty_get_baud_rate(tty);
dev_dbg(dev, "%s - tty_get_baud_rate reports speed %d\n", __func__, baud);
- /* 2. Observe async-compatible custom_divisor hack, update baudrate
- if needed */
-
+ /*
+ * Observe deprecated async-compatible custom_divisor hack, update
+ * baudrate if needed.
+ */
if (baud == 38400 &&
((priv->flags & ASYNC_SPD_MASK) == ASYNC_SPD_CUST) &&
(priv->custom_divisor)) {
@@ -1288,8 +1259,6 @@ static __u32 get_ftdi_divisor(struct tty_struct *tty,
__func__, priv->custom_divisor, baud);
}
- /* 3. Convert baudrate to device-specific divisor */
-
if (!baud)
baud = 9600;
switch (priv->chip_type) {
@@ -1505,8 +1474,7 @@ static int set_serial_info(struct tty_struct *tty,
/* Do error checking and permission checking */
if (!capable(CAP_SYS_ADMIN)) {
- if (((new_serial.flags & ~ASYNC_USR_MASK) !=
- (priv->flags & ~ASYNC_USR_MASK))) {
+ if ((new_serial.flags ^ priv->flags) & ~ASYNC_USR_MASK) {
mutex_unlock(&priv->cfg_lock);
return -EPERM;
}
@@ -1530,23 +1498,14 @@ static int set_serial_info(struct tty_struct *tty,
check_and_exit:
write_latency_timer(port);
- if ((old_priv.flags & ASYNC_SPD_MASK) !=
- (priv->flags & ASYNC_SPD_MASK)) {
- if ((priv->flags & ASYNC_SPD_MASK) == ASYNC_SPD_HI)
- tty->alt_speed = 57600;
- else if ((priv->flags & ASYNC_SPD_MASK) == ASYNC_SPD_VHI)
- tty->alt_speed = 115200;
- else if ((priv->flags & ASYNC_SPD_MASK) == ASYNC_SPD_SHI)
- tty->alt_speed = 230400;
- else if ((priv->flags & ASYNC_SPD_MASK) == ASYNC_SPD_WARP)
- tty->alt_speed = 460800;
- else
- tty->alt_speed = 0;
- }
- if (((old_priv.flags & ASYNC_SPD_MASK) !=
- (priv->flags & ASYNC_SPD_MASK)) ||
- (((priv->flags & ASYNC_SPD_MASK) == ASYNC_SPD_CUST) &&
- (old_priv.custom_divisor != priv->custom_divisor))) {
+ if ((priv->flags ^ old_priv.flags) & ASYNC_SPD_MASK ||
+ ((priv->flags & ASYNC_SPD_MASK) == ASYNC_SPD_CUST &&
+ priv->custom_divisor != old_priv.custom_divisor)) {
+
+ /* warn about deprecation unless clearing */
+ if (priv->flags & ASYNC_SPD_MASK)
+ dev_warn_ratelimited(&port->dev, "use of SPD flags is deprecated\n");
+
change_speed(tty, port);
mutex_unlock(&priv->cfg_lock);
}
diff --git a/drivers/usb/serial/qcserial.c b/drivers/usb/serial/qcserial.c
index fd509ed6cf70..4ac137d070fb 100644
--- a/drivers/usb/serial/qcserial.c
+++ b/drivers/usb/serial/qcserial.c
@@ -454,6 +454,8 @@ static struct usb_serial_driver qcdevice = {
.write = usb_wwan_write,
.write_room = usb_wwan_write_room,
.chars_in_buffer = usb_wwan_chars_in_buffer,
+ .tiocmget = usb_wwan_tiocmget,
+ .tiocmset = usb_wwan_tiocmset,
.attach = qc_attach,
.release = qc_release,
.port_probe = usb_wwan_port_probe,
diff --git a/drivers/usb/serial/upd78f0730.c b/drivers/usb/serial/upd78f0730.c
index a028dd2310c9..6819a3486e5d 100644
--- a/drivers/usb/serial/upd78f0730.c
+++ b/drivers/usb/serial/upd78f0730.c
@@ -288,7 +288,7 @@ static void upd78f0730_dtr_rts(struct usb_serial_port *port, int on)
static speed_t upd78f0730_get_baud_rate(struct tty_struct *tty)
{
const speed_t baud_rate = tty_get_baud_rate(tty);
- const speed_t supported[] = {
+ static const speed_t supported[] = {
0, 2400, 4800, 9600, 19200, 38400, 57600, 115200, 153600
};
int i;
@@ -384,7 +384,7 @@ static void upd78f0730_set_termios(struct tty_struct *tty,
static int upd78f0730_open(struct tty_struct *tty, struct usb_serial_port *port)
{
- struct upd78f0730_open_close request = {
+ static const struct upd78f0730_open_close request = {
.opcode = UPD78F0730_CMD_OPEN_CLOSE,
.state = UPD78F0730_PORT_OPEN
};
@@ -402,7 +402,7 @@ static int upd78f0730_open(struct tty_struct *tty, struct usb_serial_port *port)
static void upd78f0730_close(struct usb_serial_port *port)
{
- struct upd78f0730_open_close request = {
+ static const struct upd78f0730_open_close request = {
.opcode = UPD78F0730_CMD_OPEN_CLOSE,
.state = UPD78F0730_PORT_CLOSE
};
diff --git a/drivers/usb/serial/usb-serial.c b/drivers/usb/serial/usb-serial.c
index c7ca95f64edc..bb34f9f7eaf4 100644
--- a/drivers/usb/serial/usb-serial.c
+++ b/drivers/usb/serial/usb-serial.c
@@ -742,6 +742,124 @@ static void find_endpoints(struct usb_serial *serial,
}
}
+static int setup_port_bulk_in(struct usb_serial_port *port,
+ struct usb_endpoint_descriptor *epd)
+{
+ struct usb_serial_driver *type = port->serial->type;
+ struct usb_device *udev = port->serial->dev;
+ int buffer_size;
+ int i;
+
+ buffer_size = max_t(int, type->bulk_in_size, usb_endpoint_maxp(epd));
+ port->bulk_in_size = buffer_size;
+ port->bulk_in_endpointAddress = epd->bEndpointAddress;
+
+ for (i = 0; i < ARRAY_SIZE(port->read_urbs); ++i) {
+ set_bit(i, &port->read_urbs_free);
+ port->read_urbs[i] = usb_alloc_urb(0, GFP_KERNEL);
+ if (!port->read_urbs[i])
+ return -ENOMEM;
+ port->bulk_in_buffers[i] = kmalloc(buffer_size, GFP_KERNEL);
+ if (!port->bulk_in_buffers[i])
+ return -ENOMEM;
+ usb_fill_bulk_urb(port->read_urbs[i], udev,
+ usb_rcvbulkpipe(udev, epd->bEndpointAddress),
+ port->bulk_in_buffers[i], buffer_size,
+ type->read_bulk_callback, port);
+ }
+
+ port->read_urb = port->read_urbs[0];
+ port->bulk_in_buffer = port->bulk_in_buffers[0];
+
+ return 0;
+}
+
+static int setup_port_bulk_out(struct usb_serial_port *port,
+ struct usb_endpoint_descriptor *epd)
+{
+ struct usb_serial_driver *type = port->serial->type;
+ struct usb_device *udev = port->serial->dev;
+ int buffer_size;
+ int i;
+
+ if (kfifo_alloc(&port->write_fifo, PAGE_SIZE, GFP_KERNEL))
+ return -ENOMEM;
+ if (type->bulk_out_size)
+ buffer_size = type->bulk_out_size;
+ else
+ buffer_size = usb_endpoint_maxp(epd);
+ port->bulk_out_size = buffer_size;
+ port->bulk_out_endpointAddress = epd->bEndpointAddress;
+
+ for (i = 0; i < ARRAY_SIZE(port->write_urbs); ++i) {
+ set_bit(i, &port->write_urbs_free);
+ port->write_urbs[i] = usb_alloc_urb(0, GFP_KERNEL);
+ if (!port->write_urbs[i])
+ return -ENOMEM;
+ port->bulk_out_buffers[i] = kmalloc(buffer_size, GFP_KERNEL);
+ if (!port->bulk_out_buffers[i])
+ return -ENOMEM;
+ usb_fill_bulk_urb(port->write_urbs[i], udev,
+ usb_sndbulkpipe(udev, epd->bEndpointAddress),
+ port->bulk_out_buffers[i], buffer_size,
+ type->write_bulk_callback, port);
+ }
+
+ port->write_urb = port->write_urbs[0];
+ port->bulk_out_buffer = port->bulk_out_buffers[0];
+
+ return 0;
+}
+
+static int setup_port_interrupt_in(struct usb_serial_port *port,
+ struct usb_endpoint_descriptor *epd)
+{
+ struct usb_serial_driver *type = port->serial->type;
+ struct usb_device *udev = port->serial->dev;
+ int buffer_size;
+
+ port->interrupt_in_urb = usb_alloc_urb(0, GFP_KERNEL);
+ if (!port->interrupt_in_urb)
+ return -ENOMEM;
+ buffer_size = usb_endpoint_maxp(epd);
+ port->interrupt_in_endpointAddress = epd->bEndpointAddress;
+ port->interrupt_in_buffer = kmalloc(buffer_size, GFP_KERNEL);
+ if (!port->interrupt_in_buffer)
+ return -ENOMEM;
+ usb_fill_int_urb(port->interrupt_in_urb, udev,
+ usb_rcvintpipe(udev, epd->bEndpointAddress),
+ port->interrupt_in_buffer, buffer_size,
+ type->read_int_callback, port,
+ epd->bInterval);
+
+ return 0;
+}
+
+static int setup_port_interrupt_out(struct usb_serial_port *port,
+ struct usb_endpoint_descriptor *epd)
+{
+ struct usb_serial_driver *type = port->serial->type;
+ struct usb_device *udev = port->serial->dev;
+ int buffer_size;
+
+ port->interrupt_out_urb = usb_alloc_urb(0, GFP_KERNEL);
+ if (!port->interrupt_out_urb)
+ return -ENOMEM;
+ buffer_size = usb_endpoint_maxp(epd);
+ port->interrupt_out_size = buffer_size;
+ port->interrupt_out_endpointAddress = epd->bEndpointAddress;
+ port->interrupt_out_buffer = kmalloc(buffer_size, GFP_KERNEL);
+ if (!port->interrupt_out_buffer)
+ return -ENOMEM;
+ usb_fill_int_urb(port->interrupt_out_urb, udev,
+ usb_sndintpipe(udev, epd->bEndpointAddress),
+ port->interrupt_out_buffer, buffer_size,
+ type->write_int_callback, port,
+ epd->bInterval);
+
+ return 0;
+}
+
static int usb_serial_probe(struct usb_interface *interface,
const struct usb_device_id *id)
{
@@ -749,13 +867,10 @@ static int usb_serial_probe(struct usb_interface *interface,
struct usb_device *dev = interface_to_usbdev(interface);
struct usb_serial *serial = NULL;
struct usb_serial_port *port;
- struct usb_endpoint_descriptor *endpoint;
struct usb_serial_endpoints *epds;
struct usb_serial_driver *type = NULL;
int retval;
- int buffer_size;
int i;
- int j;
int num_ports = 0;
unsigned char max_endpoints;
@@ -847,8 +962,10 @@ static int usb_serial_probe(struct usb_interface *interface,
dev_dbg(ddev, "setting up %d port structure(s)\n", max_endpoints);
for (i = 0; i < max_endpoints; ++i) {
port = kzalloc(sizeof(struct usb_serial_port), GFP_KERNEL);
- if (!port)
- goto probe_error;
+ if (!port) {
+ retval = -ENOMEM;
+ goto err_free_epds;
+ }
tty_port_init(&port->port);
port->port.ops = &serial_port_ops;
port->serial = serial;
@@ -867,86 +984,24 @@ static int usb_serial_probe(struct usb_interface *interface,
/* set up the endpoint information */
for (i = 0; i < epds->num_bulk_in; ++i) {
- endpoint = epds->bulk_in[i];
- port = serial->port[i];
- buffer_size = max_t(int, serial->type->bulk_in_size,
- usb_endpoint_maxp(endpoint));
- port->bulk_in_size = buffer_size;
- port->bulk_in_endpointAddress = endpoint->bEndpointAddress;
-
- for (j = 0; j < ARRAY_SIZE(port->read_urbs); ++j) {
- set_bit(j, &port->read_urbs_free);
- port->read_urbs[j] = usb_alloc_urb(0, GFP_KERNEL);
- if (!port->read_urbs[j])
- goto probe_error;
- port->bulk_in_buffers[j] = kmalloc(buffer_size,
- GFP_KERNEL);
- if (!port->bulk_in_buffers[j])
- goto probe_error;
- usb_fill_bulk_urb(port->read_urbs[j], dev,
- usb_rcvbulkpipe(dev,
- endpoint->bEndpointAddress),
- port->bulk_in_buffers[j], buffer_size,
- serial->type->read_bulk_callback,
- port);
- }
-
- port->read_urb = port->read_urbs[0];
- port->bulk_in_buffer = port->bulk_in_buffers[0];
+ retval = setup_port_bulk_in(serial->port[i], epds->bulk_in[i]);
+ if (retval)
+ goto err_free_epds;
}
for (i = 0; i < epds->num_bulk_out; ++i) {
- endpoint = epds->bulk_out[i];
- port = serial->port[i];
- if (kfifo_alloc(&port->write_fifo, PAGE_SIZE, GFP_KERNEL))
- goto probe_error;
- buffer_size = serial->type->bulk_out_size;
- if (!buffer_size)
- buffer_size = usb_endpoint_maxp(endpoint);
- port->bulk_out_size = buffer_size;
- port->bulk_out_endpointAddress = endpoint->bEndpointAddress;
-
- for (j = 0; j < ARRAY_SIZE(port->write_urbs); ++j) {
- set_bit(j, &port->write_urbs_free);
- port->write_urbs[j] = usb_alloc_urb(0, GFP_KERNEL);
- if (!port->write_urbs[j])
- goto probe_error;
- port->bulk_out_buffers[j] = kmalloc(buffer_size,
- GFP_KERNEL);
- if (!port->bulk_out_buffers[j])
- goto probe_error;
- usb_fill_bulk_urb(port->write_urbs[j], dev,
- usb_sndbulkpipe(dev,
- endpoint->bEndpointAddress),
- port->bulk_out_buffers[j], buffer_size,
- serial->type->write_bulk_callback,
- port);
- }
-
- port->write_urb = port->write_urbs[0];
- port->bulk_out_buffer = port->bulk_out_buffers[0];
+ retval = setup_port_bulk_out(serial->port[i],
+ epds->bulk_out[i]);
+ if (retval)
+ goto err_free_epds;
}
if (serial->type->read_int_callback) {
for (i = 0; i < epds->num_interrupt_in; ++i) {
- endpoint = epds->interrupt_in[i];
- port = serial->port[i];
- port->interrupt_in_urb = usb_alloc_urb(0, GFP_KERNEL);
- if (!port->interrupt_in_urb)
- goto probe_error;
- buffer_size = usb_endpoint_maxp(endpoint);
- port->interrupt_in_endpointAddress =
- endpoint->bEndpointAddress;
- port->interrupt_in_buffer = kmalloc(buffer_size,
- GFP_KERNEL);
- if (!port->interrupt_in_buffer)
- goto probe_error;
- usb_fill_int_urb(port->interrupt_in_urb, dev,
- usb_rcvintpipe(dev,
- endpoint->bEndpointAddress),
- port->interrupt_in_buffer, buffer_size,
- serial->type->read_int_callback, port,
- endpoint->bInterval);
+ retval = setup_port_interrupt_in(serial->port[i],
+ epds->interrupt_in[i]);
+ if (retval)
+ goto err_free_epds;
}
} else if (epds->num_interrupt_in) {
dev_dbg(ddev, "The device claims to support interrupt in transfers, but read_int_callback is not defined\n");
@@ -954,25 +1009,10 @@ static int usb_serial_probe(struct usb_interface *interface,
if (serial->type->write_int_callback) {
for (i = 0; i < epds->num_interrupt_out; ++i) {
- endpoint = epds->interrupt_out[i];
- port = serial->port[i];
- port->interrupt_out_urb = usb_alloc_urb(0, GFP_KERNEL);
- if (!port->interrupt_out_urb)
- goto probe_error;
- buffer_size = usb_endpoint_maxp(endpoint);
- port->interrupt_out_size = buffer_size;
- port->interrupt_out_endpointAddress =
- endpoint->bEndpointAddress;
- port->interrupt_out_buffer = kmalloc(buffer_size,
- GFP_KERNEL);
- if (!port->interrupt_out_buffer)
- goto probe_error;
- usb_fill_int_urb(port->interrupt_out_urb, dev,
- usb_sndintpipe(dev,
- endpoint->bEndpointAddress),
- port->interrupt_out_buffer, buffer_size,
- serial->type->write_int_callback, port,
- endpoint->bInterval);
+ retval = setup_port_interrupt_out(serial->port[i],
+ epds->interrupt_out[i]);
+ if (retval)
+ goto err_free_epds;
}
} else if (epds->num_interrupt_out) {
dev_dbg(ddev, "The device claims to support interrupt out transfers, but write_int_callback is not defined\n");
@@ -984,7 +1024,7 @@ static int usb_serial_probe(struct usb_interface *interface,
if (type->attach) {
retval = type->attach(serial);
if (retval < 0)
- goto probe_error;
+ goto err_free_epds;
serial->attached = 1;
if (retval > 0) {
/* quietly accept this device, but don't bind to a
@@ -996,9 +1036,10 @@ static int usb_serial_probe(struct usb_interface *interface,
serial->attached = 1;
}
- if (allocate_minors(serial, num_ports)) {
+ retval = allocate_minors(serial, num_ports);
+ if (retval) {
dev_err(ddev, "No more free serial minor numbers\n");
- goto probe_error;
+ goto err_free_epds;
}
/* register all of the individual ports with the driver core */
@@ -1020,8 +1061,6 @@ exit:
module_put(type->driver.owner);
return 0;
-probe_error:
- retval = -EIO;
err_free_epds:
kfree(epds);
err_put_serial:
diff --git a/drivers/usb/storage/ene_ub6250.c b/drivers/usb/storage/ene_ub6250.c
index 44af719194b2..28100374f7bd 100644
--- a/drivers/usb/storage/ene_ub6250.c
+++ b/drivers/usb/storage/ene_ub6250.c
@@ -95,12 +95,12 @@ static struct us_unusual_dev ene_ub6250_unusual_dev_list[] = {
#define REG_HW_TRAP1 0xFF89
/* SRB Status */
-#define SS_SUCCESS 0x00 /* No Sense */
-#define SS_NOT_READY 0x02
-#define SS_MEDIUM_ERR 0x03
-#define SS_HW_ERR 0x04
-#define SS_ILLEGAL_REQUEST 0x05
-#define SS_UNIT_ATTENTION 0x06
+#define SS_SUCCESS 0x000000 /* No Sense */
+#define SS_NOT_READY 0x023A00 /* Medium not present */
+#define SS_MEDIUM_ERR 0x031100 /* Unrecovered read error */
+#define SS_HW_ERR 0x040800 /* Communication failure */
+#define SS_ILLEGAL_REQUEST 0x052000 /* Invalid command */
+#define SS_UNIT_ATTENTION 0x062900 /* Reset occurred */
/* ENE Load FW Pattern */
#define SD_INIT1_PATTERN 1
@@ -584,24 +584,26 @@ static int ene_send_scsi_cmd(struct us_data *us, u8 fDir, void *buf, int use_sg)
return USB_STOR_TRANSPORT_GOOD;
}
-static int sd_scsi_test_unit_ready(struct us_data *us, struct scsi_cmnd *srb)
+static int do_scsi_request_sense(struct us_data *us, struct scsi_cmnd *srb)
{
struct ene_ub6250_info *info = (struct ene_ub6250_info *) us->extra;
+ unsigned char buf[18];
- if (info->SD_Status.Insert && info->SD_Status.Ready)
- return USB_STOR_TRANSPORT_GOOD;
- else {
- ene_sd_init(us);
- return USB_STOR_TRANSPORT_GOOD;
- }
+ memset(buf, 0, 18);
+ buf[0] = 0x70; /* Current error */
+ buf[2] = info->SrbStatus >> 16; /* Sense key */
+ buf[7] = 10; /* Additional length */
+ buf[12] = info->SrbStatus >> 8; /* ASC */
+ buf[13] = info->SrbStatus; /* ASCQ */
+ usb_stor_set_xfer_buf(buf, sizeof(buf), srb);
return USB_STOR_TRANSPORT_GOOD;
}
-static int sd_scsi_inquiry(struct us_data *us, struct scsi_cmnd *srb)
+static int do_scsi_inquiry(struct us_data *us, struct scsi_cmnd *srb)
{
unsigned char data_ptr[36] = {
- 0x00, 0x80, 0x02, 0x00, 0x1F, 0x00, 0x00, 0x00, 0x55,
+ 0x00, 0x00, 0x02, 0x00, 0x1F, 0x00, 0x00, 0x00, 0x55,
0x53, 0x42, 0x32, 0x2E, 0x30, 0x20, 0x20, 0x43, 0x61,
0x72, 0x64, 0x52, 0x65, 0x61, 0x64, 0x65, 0x72, 0x20,
0x20, 0x20, 0x20, 0x20, 0x20, 0x30, 0x31, 0x30, 0x30 };
@@ -610,6 +612,20 @@ static int sd_scsi_inquiry(struct us_data *us, struct scsi_cmnd *srb)
return USB_STOR_TRANSPORT_GOOD;
}
+static int sd_scsi_test_unit_ready(struct us_data *us, struct scsi_cmnd *srb)
+{
+ struct ene_ub6250_info *info = (struct ene_ub6250_info *) us->extra;
+
+ if (info->SD_Status.Insert && info->SD_Status.Ready)
+ return USB_STOR_TRANSPORT_GOOD;
+ else {
+ ene_sd_init(us);
+ return USB_STOR_TRANSPORT_GOOD;
+ }
+
+ return USB_STOR_TRANSPORT_GOOD;
+}
+
static int sd_scsi_mode_sense(struct us_data *us, struct scsi_cmnd *srb)
{
struct ene_ub6250_info *info = (struct ene_ub6250_info *) us->extra;
@@ -1455,19 +1471,6 @@ static int ms_scsi_test_unit_ready(struct us_data *us, struct scsi_cmnd *srb)
return USB_STOR_TRANSPORT_GOOD;
}
-static int ms_scsi_inquiry(struct us_data *us, struct scsi_cmnd *srb)
-{
- /* pr_info("MS_SCSI_Inquiry\n"); */
- unsigned char data_ptr[36] = {
- 0x00, 0x80, 0x02, 0x00, 0x1F, 0x00, 0x00, 0x00, 0x55,
- 0x53, 0x42, 0x32, 0x2E, 0x30, 0x20, 0x20, 0x43, 0x61,
- 0x72, 0x64, 0x52, 0x65, 0x61, 0x64, 0x65, 0x72, 0x20,
- 0x20, 0x20, 0x20, 0x20, 0x20, 0x30, 0x31, 0x30, 0x30};
-
- usb_stor_set_xfer_buf(data_ptr, 36, srb);
- return USB_STOR_TRANSPORT_GOOD;
-}
-
static int ms_scsi_mode_sense(struct us_data *us, struct scsi_cmnd *srb)
{
struct ene_ub6250_info *info = (struct ene_ub6250_info *) us->extra;
@@ -1940,6 +1943,8 @@ static int ene_load_bincode(struct us_data *us, unsigned char flag)
bcb->CDB[0] = 0xEF;
result = ene_send_scsi_cmd(us, FDIR_WRITE, buf, 0);
+ if (us->srb != NULL)
+ scsi_set_resid(us->srb, 0);
info->BIN_FLAG = flag;
kfree(buf);
@@ -2223,13 +2228,15 @@ static int sd_scsi_irp(struct us_data *us, struct scsi_cmnd *srb)
int result;
struct ene_ub6250_info *info = (struct ene_ub6250_info *)us->extra;
- info->SrbStatus = SS_SUCCESS;
switch (srb->cmnd[0]) {
case TEST_UNIT_READY:
result = sd_scsi_test_unit_ready(us, srb);
break; /* 0x00 */
+ case REQUEST_SENSE:
+ result = do_scsi_request_sense(us, srb);
+ break; /* 0x03 */
case INQUIRY:
- result = sd_scsi_inquiry(us, srb);
+ result = do_scsi_inquiry(us, srb);
break; /* 0x12 */
case MODE_SENSE:
result = sd_scsi_mode_sense(us, srb);
@@ -2253,6 +2260,8 @@ static int sd_scsi_irp(struct us_data *us, struct scsi_cmnd *srb)
result = USB_STOR_TRANSPORT_FAILED;
break;
}
+ if (result == USB_STOR_TRANSPORT_GOOD)
+ info->SrbStatus = SS_SUCCESS;
return result;
}
@@ -2263,13 +2272,16 @@ static int ms_scsi_irp(struct us_data *us, struct scsi_cmnd *srb)
{
int result;
struct ene_ub6250_info *info = (struct ene_ub6250_info *)us->extra;
- info->SrbStatus = SS_SUCCESS;
+
switch (srb->cmnd[0]) {
case TEST_UNIT_READY:
result = ms_scsi_test_unit_ready(us, srb);
break; /* 0x00 */
+ case REQUEST_SENSE:
+ result = do_scsi_request_sense(us, srb);
+ break; /* 0x03 */
case INQUIRY:
- result = ms_scsi_inquiry(us, srb);
+ result = do_scsi_inquiry(us, srb);
break; /* 0x12 */
case MODE_SENSE:
result = ms_scsi_mode_sense(us, srb);
@@ -2288,26 +2300,29 @@ static int ms_scsi_irp(struct us_data *us, struct scsi_cmnd *srb)
result = USB_STOR_TRANSPORT_FAILED;
break;
}
+ if (result == USB_STOR_TRANSPORT_GOOD)
+ info->SrbStatus = SS_SUCCESS;
return result;
}
static int ene_transport(struct scsi_cmnd *srb, struct us_data *us)
{
- int result = 0;
+ int result = USB_STOR_XFER_GOOD;
struct ene_ub6250_info *info = (struct ene_ub6250_info *)(us->extra);
/*US_DEBUG(usb_stor_show_command(us, srb)); */
scsi_set_resid(srb, 0);
- if (unlikely(!(info->SD_Status.Ready || info->MS_Status.Ready))) {
+ if (unlikely(!(info->SD_Status.Ready || info->MS_Status.Ready)))
result = ene_init(us);
- } else {
+ if (result == USB_STOR_XFER_GOOD) {
+ result = USB_STOR_TRANSPORT_ERROR;
if (info->SD_Status.Ready)
result = sd_scsi_irp(us, srb);
if (info->MS_Status.Ready)
result = ms_scsi_irp(us, srb);
}
- return 0;
+ return result;
}
static struct scsi_host_template ene_ub6250_host_template;
diff --git a/drivers/usb/typec/Kconfig b/drivers/usb/typec/Kconfig
index dfcfe459b7cf..bc1b7745f1d4 100644
--- a/drivers/usb/typec/Kconfig
+++ b/drivers/usb/typec/Kconfig
@@ -19,4 +19,6 @@ config TYPEC_WCOVE
To compile this driver as module, choose M here: the module will be
called typec_wcove
+source "drivers/usb/typec/ucsi/Kconfig"
+
endmenu
diff --git a/drivers/usb/typec/Makefile b/drivers/usb/typec/Makefile
index b9cb862221af..bc214f15f1b5 100644
--- a/drivers/usb/typec/Makefile
+++ b/drivers/usb/typec/Makefile
@@ -1,2 +1,3 @@
obj-$(CONFIG_TYPEC) += typec.o
obj-$(CONFIG_TYPEC_WCOVE) += typec_wcove.o
+obj-$(CONFIG_TYPEC_UCSI) += ucsi/
diff --git a/drivers/usb/typec/typec.c b/drivers/usb/typec/typec.c
index 89e540bb7ff3..24e355ba109d 100644
--- a/drivers/usb/typec/typec.c
+++ b/drivers/usb/typec/typec.c
@@ -11,6 +11,7 @@
#include <linux/device.h>
#include <linux/module.h>
+#include <linux/mutex.h>
#include <linux/slab.h>
#include <linux/usb/typec.h>
@@ -69,6 +70,8 @@ struct typec_port {
enum typec_role pwr_role;
enum typec_role vconn_role;
enum typec_pwr_opmode pwr_opmode;
+ enum typec_port_type port_type;
+ struct mutex port_type_lock;
const struct typec_capability *cap;
};
@@ -291,7 +294,7 @@ typec_altmode_roles_show(struct device *dev, struct device_attribute *attr,
}
static void typec_init_modes(struct typec_altmode *alt,
- struct typec_mode_desc *desc, bool is_port)
+ const struct typec_mode_desc *desc, bool is_port)
{
int i;
@@ -378,7 +381,8 @@ static const struct device_type typec_altmode_dev_type = {
};
static struct typec_altmode *
-typec_register_altmode(struct device *parent, struct typec_altmode_desc *desc)
+typec_register_altmode(struct device *parent,
+ const struct typec_altmode_desc *desc)
{
struct typec_altmode *alt;
int ret;
@@ -495,7 +499,7 @@ EXPORT_SYMBOL_GPL(typec_partner_set_identity);
*/
struct typec_altmode *
typec_partner_register_altmode(struct typec_partner *partner,
- struct typec_altmode_desc *desc)
+ const struct typec_altmode_desc *desc)
{
return typec_register_altmode(&partner->dev, desc);
}
@@ -590,7 +594,7 @@ static const struct device_type typec_plug_dev_type = {
*/
struct typec_altmode *
typec_plug_register_altmode(struct typec_plug *plug,
- struct typec_altmode_desc *desc)
+ const struct typec_altmode_desc *desc)
{
return typec_register_altmode(&plug->dev, desc);
}
@@ -789,6 +793,18 @@ static const char * const typec_data_roles[] = {
[TYPEC_HOST] = "host",
};
+static const char * const typec_port_types[] = {
+ [TYPEC_PORT_DFP] = "source",
+ [TYPEC_PORT_UFP] = "sink",
+ [TYPEC_PORT_DRP] = "dual",
+};
+
+static const char * const typec_port_types_drp[] = {
+ [TYPEC_PORT_DFP] = "dual [source] sink",
+ [TYPEC_PORT_UFP] = "dual source [sink]",
+ [TYPEC_PORT_DRP] = "[dual] source sink",
+};
+
static ssize_t
preferred_role_store(struct device *dev, struct device_attribute *attr,
const char *buf, size_t size)
@@ -846,11 +862,6 @@ static ssize_t data_role_store(struct device *dev,
struct typec_port *port = to_typec_port(dev);
int ret;
- if (port->cap->type != TYPEC_PORT_DRP) {
- dev_dbg(dev, "data role swap only supported with DRP ports\n");
- return -EOPNOTSUPP;
- }
-
if (!port->cap->dr_set) {
dev_dbg(dev, "data role swapping not supported\n");
return -EOPNOTSUPP;
@@ -860,11 +871,22 @@ static ssize_t data_role_store(struct device *dev,
if (ret < 0)
return ret;
+ mutex_lock(&port->port_type_lock);
+ if (port->port_type != TYPEC_PORT_DRP) {
+ dev_dbg(dev, "port type fixed at \"%s\"",
+ typec_port_types[port->port_type]);
+ ret = -EOPNOTSUPP;
+ goto unlock_and_ret;
+ }
+
ret = port->cap->dr_set(port->cap, ret);
if (ret)
- return ret;
+ goto unlock_and_ret;
- return size;
+ ret = size;
+unlock_and_ret:
+ mutex_unlock(&port->port_type_lock);
+ return ret;
}
static ssize_t data_role_show(struct device *dev,
@@ -885,7 +907,7 @@ static ssize_t power_role_store(struct device *dev,
const char *buf, size_t size)
{
struct typec_port *port = to_typec_port(dev);
- int ret = size;
+ int ret;
if (!port->cap->pd_revision) {
dev_dbg(dev, "USB Power Delivery not supported\n");
@@ -906,11 +928,22 @@ static ssize_t power_role_store(struct device *dev,
if (ret < 0)
return ret;
+ mutex_lock(&port->port_type_lock);
+ if (port->port_type != TYPEC_PORT_DRP) {
+ dev_dbg(dev, "port type fixed at \"%s\"",
+ typec_port_types[port->port_type]);
+ ret = -EOPNOTSUPP;
+ goto unlock_and_ret;
+ }
+
ret = port->cap->pr_set(port->cap, ret);
if (ret)
- return ret;
+ goto unlock_and_ret;
- return size;
+ ret = size;
+unlock_and_ret:
+ mutex_unlock(&port->port_type_lock);
+ return ret;
}
static ssize_t power_role_show(struct device *dev,
@@ -926,6 +959,57 @@ static ssize_t power_role_show(struct device *dev,
}
static DEVICE_ATTR_RW(power_role);
+static ssize_t
+port_type_store(struct device *dev, struct device_attribute *attr,
+ const char *buf, size_t size)
+{
+ struct typec_port *port = to_typec_port(dev);
+ int ret;
+ enum typec_port_type type;
+
+ if (!port->cap->port_type_set || port->cap->type != TYPEC_PORT_DRP) {
+ dev_dbg(dev, "changing port type not supported\n");
+ return -EOPNOTSUPP;
+ }
+
+ ret = sysfs_match_string(typec_port_types, buf);
+ if (ret < 0)
+ return ret;
+
+ type = ret;
+ mutex_lock(&port->port_type_lock);
+
+ if (port->port_type == type) {
+ ret = size;
+ goto unlock_and_ret;
+ }
+
+ ret = port->cap->port_type_set(port->cap, type);
+ if (ret)
+ goto unlock_and_ret;
+
+ port->port_type = type;
+ ret = size;
+
+unlock_and_ret:
+ mutex_unlock(&port->port_type_lock);
+ return ret;
+}
+
+static ssize_t
+port_type_show(struct device *dev, struct device_attribute *attr,
+ char *buf)
+{
+ struct typec_port *port = to_typec_port(dev);
+
+ if (port->cap->type == TYPEC_PORT_DRP)
+ return sprintf(buf, "%s\n",
+ typec_port_types_drp[port->port_type]);
+
+ return sprintf(buf, "[%s]\n", typec_port_types[port->cap->type]);
+}
+static DEVICE_ATTR_RW(port_type);
+
static const char * const typec_pwr_opmodes[] = {
[TYPEC_PWR_MODE_USB] = "default",
[TYPEC_PWR_MODE_1_5A] = "1.5A",
@@ -1035,6 +1119,7 @@ static struct attribute *typec_attrs[] = {
&dev_attr_usb_power_delivery_revision.attr,
&dev_attr_usb_typec_revision.attr,
&dev_attr_vconn_source.attr,
+ &dev_attr_port_type.attr,
NULL,
};
ATTRIBUTE_GROUPS(typec);
@@ -1123,6 +1208,11 @@ void typec_set_vconn_role(struct typec_port *port, enum typec_role role)
}
EXPORT_SYMBOL_GPL(typec_set_vconn_role);
+static int partner_match(struct device *dev, void *data)
+{
+ return is_typec_partner(dev);
+}
+
/**
* typec_set_pwr_opmode - Report changed power operation mode
* @port: The USB Type-C Port where the mode was changed
@@ -1136,12 +1226,26 @@ EXPORT_SYMBOL_GPL(typec_set_vconn_role);
void typec_set_pwr_opmode(struct typec_port *port,
enum typec_pwr_opmode opmode)
{
+ struct device *partner_dev;
+
if (port->pwr_opmode == opmode)
return;
port->pwr_opmode = opmode;
sysfs_notify(&port->dev.kobj, NULL, "power_operation_mode");
kobject_uevent(&port->dev.kobj, KOBJ_CHANGE);
+
+ partner_dev = device_find_child(&port->dev, NULL, partner_match);
+ if (partner_dev) {
+ struct typec_partner *partner = to_typec_partner(partner_dev);
+
+ if (opmode == TYPEC_PWR_MODE_PD && !partner->usb_pd) {
+ partner->usb_pd = 1;
+ sysfs_notify(&partner_dev->kobj, NULL,
+ "supports_usb_power_delivery");
+ }
+ put_device(partner_dev);
+ }
}
EXPORT_SYMBOL_GPL(typec_set_pwr_opmode);
@@ -1159,7 +1263,7 @@ EXPORT_SYMBOL_GPL(typec_set_pwr_opmode);
*/
struct typec_altmode *
typec_port_register_altmode(struct typec_port *port,
- struct typec_altmode_desc *desc)
+ const struct typec_altmode_desc *desc)
{
return typec_register_altmode(&port->dev, desc);
}
@@ -1211,6 +1315,8 @@ struct typec_port *typec_register_port(struct device *parent,
port->id = id;
port->cap = cap;
+ port->port_type = cap->type;
+ mutex_init(&port->port_type_lock);
port->prefer_role = cap->prefer_role;
port->dev.class = typec_class;
diff --git a/drivers/usb/typec/typec_wcove.c b/drivers/usb/typec/typec_wcove.c
index d5a7b21fa3f1..c2ce25289027 100644
--- a/drivers/usb/typec/typec_wcove.c
+++ b/drivers/usb/typec/typec_wcove.c
@@ -105,8 +105,8 @@ enum wcove_typec_role {
WCOVE_ROLE_DEVICE,
};
-static uuid_le uuid = UUID_LE(0x482383f0, 0x2876, 0x4e49,
- 0x86, 0x85, 0xdb, 0x66, 0x21, 0x1a, 0xf0, 0x37);
+static guid_t guid = GUID_INIT(0x482383f0, 0x2876, 0x4e49,
+ 0x86, 0x85, 0xdb, 0x66, 0x21, 0x1a, 0xf0, 0x37);
static int wcove_typec_func(struct wcove_typec *wcove,
enum wcove_typec_func func, int param)
@@ -118,7 +118,7 @@ static int wcove_typec_func(struct wcove_typec *wcove,
tmp.type = ACPI_TYPE_INTEGER;
tmp.integer.value = param;
- obj = acpi_evaluate_dsm(ACPI_HANDLE(wcove->dev), uuid.b, 1, func,
+ obj = acpi_evaluate_dsm(ACPI_HANDLE(wcove->dev), &guid, 1, func,
&argv4);
if (!obj) {
dev_err(wcove->dev, "%s: failed to evaluate _DSM\n", __func__);
@@ -314,7 +314,7 @@ static int wcove_typec_probe(struct platform_device *pdev)
if (ret)
return ret;
- if (!acpi_check_dsm(ACPI_HANDLE(&pdev->dev), uuid.b, 0, 0x1f)) {
+ if (!acpi_check_dsm(ACPI_HANDLE(&pdev->dev), &guid, 0, 0x1f)) {
dev_err(&pdev->dev, "Missing _DSM functions\n");
return -ENODEV;
}
diff --git a/drivers/usb/typec/ucsi/Kconfig b/drivers/usb/typec/ucsi/Kconfig
new file mode 100644
index 000000000000..d0c31cee4720
--- /dev/null
+++ b/drivers/usb/typec/ucsi/Kconfig
@@ -0,0 +1,39 @@
+config TYPEC_UCSI
+ tristate "USB Type-C Connector System Software Interface driver"
+ depends on !CPU_BIG_ENDIAN
+ select TYPEC
+ help
+ USB Type-C Connector System Software Interface (UCSI) is a
+ specification for an interface that allows the operating system to
+ control the USB Type-C ports. On UCSI system the USB Type-C ports
+ function autonomously by default, but in order to get the status of
+ the ports and support basic operations like role swapping, the driver
+ is required. UCSI is available on most of the new Intel based systems
+ that are equipped with Embedded Controller and USB Type-C ports.
+
+ UCSI specification does not define the interface method, so depending
+ on the platform, ACPI, PCI, I2C, etc. may be used. Therefore this
+ driver only provides the core part, and separate drivers are needed
+ for every supported interface method.
+
+ The UCSI specification can be downloaded from:
+ http://www.intel.com/content/www/us/en/io/universal-serial-bus/usb-type-c-ucsi-spec.html
+
+ To compile the driver as a module, choose M here: the module will be
+ called typec_ucsi.
+
+if TYPEC_UCSI
+
+config UCSI_ACPI
+ tristate "UCSI ACPI Interface Driver"
+ depends on ACPI
+ help
+ This driver enables UCSI support on platforms that expose UCSI
+ interface as ACPI device. On new Intel Atom based platforms starting
+ from Broxton SoCs and Core platforms stating from Skylake, UCSI is an
+ ACPI enumerated device.
+
+ To compile the driver as a module, choose M here: the module will be
+ called ucsi_acpi
+
+endif
diff --git a/drivers/usb/typec/ucsi/Makefile b/drivers/usb/typec/ucsi/Makefile
new file mode 100644
index 000000000000..8372fc22f9b3
--- /dev/null
+++ b/drivers/usb/typec/ucsi/Makefile
@@ -0,0 +1,9 @@
+CFLAGS_trace.o := -I$(src)
+
+obj-$(CONFIG_TYPEC_UCSI) += typec_ucsi.o
+
+typec_ucsi-y := ucsi.o
+
+typec_ucsi-$(CONFIG_FTRACE) += trace.o
+
+obj-$(CONFIG_UCSI_ACPI) += ucsi_acpi.o
diff --git a/drivers/usb/typec/ucsi/debug.h b/drivers/usb/typec/ucsi/debug.h
new file mode 100644
index 000000000000..e4d8fc763e6c
--- /dev/null
+++ b/drivers/usb/typec/ucsi/debug.h
@@ -0,0 +1,64 @@
+#ifndef __UCSI_DEBUG_H
+#define __UCSI_DEBUG_H
+
+#include "ucsi.h"
+
+static const char * const ucsi_cmd_strs[] = {
+ [0] = "Unknown command",
+ [UCSI_PPM_RESET] = "PPM_RESET",
+ [UCSI_CANCEL] = "CANCEL",
+ [UCSI_CONNECTOR_RESET] = "CONNECTOR_RESET",
+ [UCSI_ACK_CC_CI] = "ACK_CC_CI",
+ [UCSI_SET_NOTIFICATION_ENABLE] = "SET_NOTIFICATION_ENABLE",
+ [UCSI_GET_CAPABILITY] = "GET_CAPABILITY",
+ [UCSI_GET_CONNECTOR_CAPABILITY] = "GET_CONNECTOR_CAPABILITY",
+ [UCSI_SET_UOM] = "SET_UOM",
+ [UCSI_SET_UOR] = "SET_UOR",
+ [UCSI_SET_PDM] = "SET_PDM",
+ [UCSI_SET_PDR] = "SET_PDR",
+ [UCSI_GET_ALTERNATE_MODES] = "GET_ALTERNATE_MODES",
+ [UCSI_GET_CAM_SUPPORTED] = "GET_CAM_SUPPORTED",
+ [UCSI_GET_CURRENT_CAM] = "GET_CURRENT_CAM",
+ [UCSI_SET_NEW_CAM] = "SET_NEW_CAM",
+ [UCSI_GET_PDOS] = "GET_PDOS",
+ [UCSI_GET_CABLE_PROPERTY] = "GET_CABLE_PROPERTY",
+ [UCSI_GET_CONNECTOR_STATUS] = "GET_CONNECTOR_STATUS",
+ [UCSI_GET_ERROR_STATUS] = "GET_ERROR_STATUS",
+};
+
+static inline const char *ucsi_cmd_str(u64 raw_cmd)
+{
+ u8 cmd = raw_cmd & GENMASK(7, 0);
+
+ return ucsi_cmd_strs[(cmd >= ARRAY_SIZE(ucsi_cmd_strs)) ? 0 : cmd];
+}
+
+static const char * const ucsi_ack_strs[] = {
+ [0] = "",
+ [UCSI_ACK_EVENT] = "event",
+ [UCSI_ACK_CMD] = "command",
+};
+
+static inline const char *ucsi_ack_str(u8 ack)
+{
+ return ucsi_ack_strs[(ack >= ARRAY_SIZE(ucsi_ack_strs)) ? 0 : ack];
+}
+
+static inline const char *ucsi_cci_str(u32 cci)
+{
+ if (cci & GENMASK(7, 0)) {
+ if (cci & BIT(29))
+ return "Event pending (ACK completed)";
+ if (cci & BIT(31))
+ return "Event pending (command completed)";
+ return "Connector Change";
+ }
+ if (cci & BIT(29))
+ return "ACK completed";
+ if (cci & BIT(31))
+ return "Command completed";
+
+ return "";
+}
+
+#endif /* __UCSI_DEBUG_H */
diff --git a/drivers/usb/typec/ucsi/trace.c b/drivers/usb/typec/ucsi/trace.c
new file mode 100644
index 000000000000..006f65c72a34
--- /dev/null
+++ b/drivers/usb/typec/ucsi/trace.c
@@ -0,0 +1,2 @@
+#define CREATE_TRACE_POINTS
+#include "trace.h"
diff --git a/drivers/usb/typec/ucsi/trace.h b/drivers/usb/typec/ucsi/trace.h
new file mode 100644
index 000000000000..98b404404834
--- /dev/null
+++ b/drivers/usb/typec/ucsi/trace.h
@@ -0,0 +1,143 @@
+
+#undef TRACE_SYSTEM
+#define TRACE_SYSTEM ucsi
+
+#if !defined(__UCSI_TRACE_H) || defined(TRACE_HEADER_MULTI_READ)
+#define __UCSI_TRACE_H
+
+#include <linux/tracepoint.h>
+#include "ucsi.h"
+#include "debug.h"
+
+DECLARE_EVENT_CLASS(ucsi_log_ack,
+ TP_PROTO(u8 ack),
+ TP_ARGS(ack),
+ TP_STRUCT__entry(
+ __field(u8, ack)
+ ),
+ TP_fast_assign(
+ __entry->ack = ack;
+ ),
+ TP_printk("ACK %s", ucsi_ack_str(__entry->ack))
+);
+
+DEFINE_EVENT(ucsi_log_ack, ucsi_ack,
+ TP_PROTO(u8 ack),
+ TP_ARGS(ack)
+);
+
+DECLARE_EVENT_CLASS(ucsi_log_control,
+ TP_PROTO(struct ucsi_control *ctrl),
+ TP_ARGS(ctrl),
+ TP_STRUCT__entry(
+ __field(u64, ctrl)
+ ),
+ TP_fast_assign(
+ __entry->ctrl = ctrl->raw_cmd;
+ ),
+ TP_printk("control=%08llx (%s)", __entry->ctrl,
+ ucsi_cmd_str(__entry->ctrl))
+);
+
+DEFINE_EVENT(ucsi_log_control, ucsi_command,
+ TP_PROTO(struct ucsi_control *ctrl),
+ TP_ARGS(ctrl)
+);
+
+DECLARE_EVENT_CLASS(ucsi_log_command,
+ TP_PROTO(struct ucsi_control *ctrl, int ret),
+ TP_ARGS(ctrl, ret),
+ TP_STRUCT__entry(
+ __field(u64, ctrl)
+ __field(int, ret)
+ ),
+ TP_fast_assign(
+ __entry->ctrl = ctrl->raw_cmd;
+ __entry->ret = ret;
+ ),
+ TP_printk("%s -> %s (err=%d)", ucsi_cmd_str(__entry->ctrl),
+ __entry->ret < 0 ? "FAIL" : "OK",
+ __entry->ret < 0 ? __entry->ret : 0)
+);
+
+DEFINE_EVENT(ucsi_log_command, ucsi_run_command,
+ TP_PROTO(struct ucsi_control *ctrl, int ret),
+ TP_ARGS(ctrl, ret)
+);
+
+DEFINE_EVENT(ucsi_log_command, ucsi_reset_ppm,
+ TP_PROTO(struct ucsi_control *ctrl, int ret),
+ TP_ARGS(ctrl, ret)
+);
+
+DECLARE_EVENT_CLASS(ucsi_log_cci,
+ TP_PROTO(u32 cci),
+ TP_ARGS(cci),
+ TP_STRUCT__entry(
+ __field(u32, cci)
+ ),
+ TP_fast_assign(
+ __entry->cci = cci;
+ ),
+ TP_printk("CCI=%08x %s", __entry->cci, ucsi_cci_str(__entry->cci))
+);
+
+DEFINE_EVENT(ucsi_log_cci, ucsi_notify,
+ TP_PROTO(u32 cci),
+ TP_ARGS(cci)
+);
+
+DECLARE_EVENT_CLASS(ucsi_log_connector_status,
+ TP_PROTO(int port, struct ucsi_connector_status *status),
+ TP_ARGS(port, status),
+ TP_STRUCT__entry(
+ __field(int, port)
+ __field(u16, change)
+ __field(u8, opmode)
+ __field(u8, connected)
+ __field(u8, pwr_dir)
+ __field(u8, partner_flags)
+ __field(u8, partner_type)
+ __field(u32, request_data_obj)
+ __field(u8, bc_status)
+ ),
+ TP_fast_assign(
+ __entry->port = port - 1;
+ __entry->change = status->change;
+ __entry->opmode = status->pwr_op_mode;
+ __entry->connected = status->connected;
+ __entry->pwr_dir = status->pwr_dir;
+ __entry->partner_flags = status->partner_flags;
+ __entry->partner_type = status->partner_type;
+ __entry->request_data_obj = status->request_data_obj;
+ __entry->bc_status = status->bc_status;
+ ),
+ TP_printk("port%d status: change=%04x, opmode=%x, connected=%d, "
+ "sourcing=%d, partner_flags=%x, partner_type=%x, "
+ "request_data_obj=%08x, BC status=%x", __entry->port,
+ __entry->change, __entry->opmode, __entry->connected,
+ __entry->pwr_dir, __entry->partner_flags, __entry->partner_type,
+ __entry->request_data_obj, __entry->bc_status)
+);
+
+DEFINE_EVENT(ucsi_log_connector_status, ucsi_connector_change,
+ TP_PROTO(int port, struct ucsi_connector_status *status),
+ TP_ARGS(port, status)
+);
+
+DEFINE_EVENT(ucsi_log_connector_status, ucsi_register_port,
+ TP_PROTO(int port, struct ucsi_connector_status *status),
+ TP_ARGS(port, status)
+);
+
+#endif /* __UCSI_TRACE_H */
+
+/* This part must be outside protection */
+
+#undef TRACE_INCLUDE_PATH
+#define TRACE_INCLUDE_PATH .
+
+#undef TRACE_INCLUDE_FILE
+#define TRACE_INCLUDE_FILE trace
+
+#include <trace/define_trace.h>
diff --git a/drivers/usb/typec/ucsi/ucsi.c b/drivers/usb/typec/ucsi/ucsi.c
new file mode 100644
index 000000000000..714c5bcedf2b
--- /dev/null
+++ b/drivers/usb/typec/ucsi/ucsi.c
@@ -0,0 +1,790 @@
+/*
+ * USB Type-C Connector System Software Interface driver
+ *
+ * Copyright (C) 2017, Intel Corporation
+ * Author: Heikki Krogerus <heikki.krogerus@linux.intel.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/completion.h>
+#include <linux/property.h>
+#include <linux/device.h>
+#include <linux/module.h>
+#include <linux/delay.h>
+#include <linux/slab.h>
+#include <linux/usb/typec.h>
+
+#include "ucsi.h"
+#include "trace.h"
+
+#define to_ucsi_connector(_cap_) container_of(_cap_, struct ucsi_connector, \
+ typec_cap)
+
+/*
+ * UCSI_TIMEOUT_MS - PPM communication timeout
+ *
+ * Ideally we could use MIN_TIME_TO_RESPOND_WITH_BUSY (which is defined in UCSI
+ * specification) here as reference, but unfortunately we can't. It is very
+ * difficult to estimate the time it takes for the system to process the command
+ * before it is actually passed to the PPM.
+ */
+#define UCSI_TIMEOUT_MS 1000
+
+/*
+ * UCSI_SWAP_TIMEOUT_MS - Timeout for role swap requests
+ *
+ * 5 seconds is close to the time it takes for CapsCounter to reach 0, so even
+ * if the PPM does not generate Connector Change events before that with
+ * partners that do not support USB Power Delivery, this should still work.
+ */
+#define UCSI_SWAP_TIMEOUT_MS 5000
+
+enum ucsi_status {
+ UCSI_IDLE = 0,
+ UCSI_BUSY,
+ UCSI_ERROR,
+};
+
+struct ucsi_connector {
+ int num;
+
+ struct ucsi *ucsi;
+ struct work_struct work;
+ struct completion complete;
+
+ struct typec_port *port;
+ struct typec_partner *partner;
+
+ struct typec_capability typec_cap;
+
+ struct ucsi_connector_status status;
+ struct ucsi_connector_capability cap;
+};
+
+struct ucsi {
+ struct device *dev;
+ struct ucsi_ppm *ppm;
+
+ enum ucsi_status status;
+ struct completion complete;
+ struct ucsi_capability cap;
+ struct ucsi_connector *connector;
+
+ struct work_struct work;
+
+ /* PPM Communication lock */
+ struct mutex ppm_lock;
+
+ /* PPM communication flags */
+ unsigned long flags;
+#define EVENT_PENDING 0
+#define COMMAND_PENDING 1
+#define ACK_PENDING 2
+};
+
+static inline int ucsi_sync(struct ucsi *ucsi)
+{
+ if (ucsi->ppm && ucsi->ppm->sync)
+ return ucsi->ppm->sync(ucsi->ppm);
+ return 0;
+}
+
+static int ucsi_command(struct ucsi *ucsi, struct ucsi_control *ctrl)
+{
+ int ret;
+
+ trace_ucsi_command(ctrl);
+
+ set_bit(COMMAND_PENDING, &ucsi->flags);
+
+ ret = ucsi->ppm->cmd(ucsi->ppm, ctrl);
+ if (ret)
+ goto err_clear_flag;
+
+ if (!wait_for_completion_timeout(&ucsi->complete,
+ msecs_to_jiffies(UCSI_TIMEOUT_MS))) {
+ dev_warn(ucsi->dev, "PPM NOT RESPONDING\n");
+ ret = -ETIMEDOUT;
+ }
+
+err_clear_flag:
+ clear_bit(COMMAND_PENDING, &ucsi->flags);
+
+ return ret;
+}
+
+static int ucsi_ack(struct ucsi *ucsi, u8 ack)
+{
+ struct ucsi_control ctrl;
+ int ret;
+
+ trace_ucsi_ack(ack);
+
+ set_bit(ACK_PENDING, &ucsi->flags);
+
+ UCSI_CMD_ACK(ctrl, ack);
+ ret = ucsi->ppm->cmd(ucsi->ppm, &ctrl);
+ if (ret)
+ goto out_clear_bit;
+
+ /* Waiting for ACK with ACK CMD, but not with EVENT for now */
+ if (ack == UCSI_ACK_EVENT)
+ goto out_clear_bit;
+
+ if (!wait_for_completion_timeout(&ucsi->complete,
+ msecs_to_jiffies(UCSI_TIMEOUT_MS)))
+ ret = -ETIMEDOUT;
+
+out_clear_bit:
+ clear_bit(ACK_PENDING, &ucsi->flags);
+
+ if (ret)
+ dev_err(ucsi->dev, "%s: failed\n", __func__);
+
+ return ret;
+}
+
+static int ucsi_run_command(struct ucsi *ucsi, struct ucsi_control *ctrl,
+ void *data, size_t size)
+{
+ struct ucsi_control _ctrl;
+ u8 data_length;
+ u16 error;
+ int ret;
+
+ ret = ucsi_command(ucsi, ctrl);
+ if (ret)
+ goto err;
+
+ switch (ucsi->status) {
+ case UCSI_IDLE:
+ ret = ucsi_sync(ucsi);
+ if (ret)
+ dev_warn(ucsi->dev, "%s: sync failed\n", __func__);
+
+ if (data)
+ memcpy(data, ucsi->ppm->data->message_in, size);
+
+ data_length = ucsi->ppm->data->cci.data_length;
+
+ ret = ucsi_ack(ucsi, UCSI_ACK_CMD);
+ if (!ret)
+ ret = data_length;
+ break;
+ case UCSI_BUSY:
+ /* The caller decides whether to cancel or not */
+ ret = -EBUSY;
+ break;
+ case UCSI_ERROR:
+ ret = ucsi_ack(ucsi, UCSI_ACK_CMD);
+ if (ret)
+ break;
+
+ _ctrl.raw_cmd = 0;
+ _ctrl.cmd.cmd = UCSI_GET_ERROR_STATUS;
+ ret = ucsi_command(ucsi, &_ctrl);
+ if (ret) {
+ dev_err(ucsi->dev, "reading error failed!\n");
+ break;
+ }
+
+ memcpy(&error, ucsi->ppm->data->message_in, sizeof(error));
+
+ /* Something has really gone wrong */
+ if (WARN_ON(ucsi->status == UCSI_ERROR)) {
+ ret = -ENODEV;
+ break;
+ }
+
+ ret = ucsi_ack(ucsi, UCSI_ACK_CMD);
+ if (ret)
+ break;
+
+ switch (error) {
+ case UCSI_ERROR_INCOMPATIBLE_PARTNER:
+ ret = -EOPNOTSUPP;
+ break;
+ case UCSI_ERROR_CC_COMMUNICATION_ERR:
+ ret = -ECOMM;
+ break;
+ case UCSI_ERROR_CONTRACT_NEGOTIATION_FAIL:
+ ret = -EPROTO;
+ break;
+ case UCSI_ERROR_DEAD_BATTERY:
+ dev_warn(ucsi->dev, "Dead battery condition!\n");
+ ret = -EPERM;
+ break;
+ /* The following mean a bug in this driver */
+ case UCSI_ERROR_INVALID_CON_NUM:
+ case UCSI_ERROR_UNREGONIZED_CMD:
+ case UCSI_ERROR_INVALID_CMD_ARGUMENT:
+ dev_warn(ucsi->dev,
+ "%s: possible UCSI driver bug - error 0x%x\n",
+ __func__, error);
+ ret = -EINVAL;
+ break;
+ default:
+ dev_warn(ucsi->dev,
+ "%s: error without status\n", __func__);
+ ret = -EIO;
+ break;
+ }
+ break;
+ }
+
+err:
+ trace_ucsi_run_command(ctrl, ret);
+
+ return ret;
+}
+
+/* -------------------------------------------------------------------------- */
+
+static void ucsi_pwr_opmode_change(struct ucsi_connector *con)
+{
+ switch (con->status.pwr_op_mode) {
+ case UCSI_CONSTAT_PWR_OPMODE_PD:
+ typec_set_pwr_opmode(con->port, TYPEC_PWR_MODE_PD);
+ break;
+ case UCSI_CONSTAT_PWR_OPMODE_TYPEC1_5:
+ typec_set_pwr_opmode(con->port, TYPEC_PWR_MODE_1_5A);
+ break;
+ case UCSI_CONSTAT_PWR_OPMODE_TYPEC3_0:
+ typec_set_pwr_opmode(con->port, TYPEC_PWR_MODE_3_0A);
+ break;
+ default:
+ typec_set_pwr_opmode(con->port, TYPEC_PWR_MODE_USB);
+ break;
+ }
+}
+
+static int ucsi_register_partner(struct ucsi_connector *con)
+{
+ struct typec_partner_desc partner;
+
+ if (con->partner)
+ return 0;
+
+ memset(&partner, 0, sizeof(partner));
+
+ switch (con->status.partner_type) {
+ case UCSI_CONSTAT_PARTNER_TYPE_DEBUG:
+ partner.accessory = TYPEC_ACCESSORY_DEBUG;
+ break;
+ case UCSI_CONSTAT_PARTNER_TYPE_AUDIO:
+ partner.accessory = TYPEC_ACCESSORY_AUDIO;
+ break;
+ default:
+ break;
+ }
+
+ partner.usb_pd = con->status.pwr_op_mode == UCSI_CONSTAT_PWR_OPMODE_PD;
+
+ con->partner = typec_register_partner(con->port, &partner);
+ if (!con->partner) {
+ dev_err(con->ucsi->dev, "con%d: failed to register partner\n",
+ con->num);
+ return -ENODEV;
+ }
+
+ return 0;
+}
+
+static void ucsi_unregister_partner(struct ucsi_connector *con)
+{
+ typec_unregister_partner(con->partner);
+ con->partner = NULL;
+}
+
+static void ucsi_connector_change(struct work_struct *work)
+{
+ struct ucsi_connector *con = container_of(work, struct ucsi_connector,
+ work);
+ struct ucsi *ucsi = con->ucsi;
+ struct ucsi_control ctrl;
+ int ret;
+
+ mutex_lock(&ucsi->ppm_lock);
+
+ UCSI_CMD_GET_CONNECTOR_STATUS(ctrl, con->num);
+ ret = ucsi_run_command(ucsi, &ctrl, &con->status, sizeof(con->status));
+ if (ret < 0) {
+ dev_err(ucsi->dev, "%s: GET_CONNECTOR_STATUS failed (%d)\n",
+ __func__, ret);
+ goto out_unlock;
+ }
+
+ if (con->status.change & UCSI_CONSTAT_POWER_OPMODE_CHANGE)
+ ucsi_pwr_opmode_change(con);
+
+ if (con->status.change & UCSI_CONSTAT_POWER_DIR_CHANGE) {
+ typec_set_pwr_role(con->port, con->status.pwr_dir);
+
+ /* Complete pending power role swap */
+ if (!completion_done(&con->complete))
+ complete(&con->complete);
+ }
+
+ if (con->status.change & UCSI_CONSTAT_PARTNER_CHANGE) {
+ switch (con->status.partner_type) {
+ case UCSI_CONSTAT_PARTNER_TYPE_UFP:
+ typec_set_data_role(con->port, TYPEC_HOST);
+ break;
+ case UCSI_CONSTAT_PARTNER_TYPE_DFP:
+ typec_set_data_role(con->port, TYPEC_DEVICE);
+ break;
+ default:
+ break;
+ }
+
+ /* Complete pending data role swap */
+ if (!completion_done(&con->complete))
+ complete(&con->complete);
+ }
+
+ if (con->status.change & UCSI_CONSTAT_CONNECT_CHANGE) {
+ if (con->status.connected)
+ ucsi_register_partner(con);
+ else
+ ucsi_unregister_partner(con);
+ }
+
+ ret = ucsi_ack(ucsi, UCSI_ACK_EVENT);
+ if (ret)
+ dev_err(ucsi->dev, "%s: ACK failed (%d)", __func__, ret);
+
+ trace_ucsi_connector_change(con->num, &con->status);
+
+out_unlock:
+ clear_bit(EVENT_PENDING, &ucsi->flags);
+ mutex_unlock(&ucsi->ppm_lock);
+}
+
+/**
+ * ucsi_notify - PPM notification handler
+ * @ucsi: Source UCSI Interface for the notifications
+ *
+ * Handle notifications from PPM of @ucsi.
+ */
+void ucsi_notify(struct ucsi *ucsi)
+{
+ struct ucsi_cci *cci;
+
+ /* There is no requirement to sync here, but no harm either. */
+ ucsi_sync(ucsi);
+
+ cci = &ucsi->ppm->data->cci;
+
+ if (cci->error)
+ ucsi->status = UCSI_ERROR;
+ else if (cci->busy)
+ ucsi->status = UCSI_BUSY;
+ else
+ ucsi->status = UCSI_IDLE;
+
+ if (cci->cmd_complete && test_bit(COMMAND_PENDING, &ucsi->flags)) {
+ complete(&ucsi->complete);
+ } else if (cci->ack_complete && test_bit(ACK_PENDING, &ucsi->flags)) {
+ complete(&ucsi->complete);
+ } else if (cci->connector_change) {
+ struct ucsi_connector *con;
+
+ con = &ucsi->connector[cci->connector_change - 1];
+
+ if (!test_and_set_bit(EVENT_PENDING, &ucsi->flags))
+ schedule_work(&con->work);
+ }
+
+ trace_ucsi_notify(ucsi->ppm->data->raw_cci);
+}
+EXPORT_SYMBOL_GPL(ucsi_notify);
+
+/* -------------------------------------------------------------------------- */
+
+static int ucsi_reset_connector(struct ucsi_connector *con, bool hard)
+{
+ struct ucsi_control ctrl;
+
+ UCSI_CMD_CONNECTOR_RESET(ctrl, con, hard);
+
+ return ucsi_run_command(con->ucsi, &ctrl, NULL, 0);
+}
+
+static int ucsi_reset_ppm(struct ucsi *ucsi)
+{
+ struct ucsi_control ctrl;
+ unsigned long tmo;
+ int ret;
+
+ ctrl.raw_cmd = 0;
+ ctrl.cmd.cmd = UCSI_PPM_RESET;
+ trace_ucsi_command(&ctrl);
+ ret = ucsi->ppm->cmd(ucsi->ppm, &ctrl);
+ if (ret)
+ goto err;
+
+ tmo = jiffies + msecs_to_jiffies(UCSI_TIMEOUT_MS);
+
+ do {
+ /* Here sync is critical. */
+ ret = ucsi_sync(ucsi);
+ if (ret)
+ goto err;
+
+ if (ucsi->ppm->data->cci.reset_complete)
+ break;
+
+ /* If the PPM is still doing something else, reset it again. */
+ if (ucsi->ppm->data->raw_cci) {
+ dev_warn_ratelimited(ucsi->dev,
+ "Failed to reset PPM! Trying again..\n");
+
+ trace_ucsi_command(&ctrl);
+ ret = ucsi->ppm->cmd(ucsi->ppm, &ctrl);
+ if (ret)
+ goto err;
+ }
+
+ /* Letting the PPM settle down. */
+ msleep(20);
+
+ ret = -ETIMEDOUT;
+ } while (time_is_after_jiffies(tmo));
+
+err:
+ trace_ucsi_reset_ppm(&ctrl, ret);
+
+ return ret;
+}
+
+static int ucsi_role_cmd(struct ucsi_connector *con, struct ucsi_control *ctrl)
+{
+ int ret;
+
+ ret = ucsi_run_command(con->ucsi, ctrl, NULL, 0);
+ if (ret == -ETIMEDOUT) {
+ struct ucsi_control c;
+
+ /* PPM most likely stopped responding. Resetting everything. */
+ ucsi_reset_ppm(con->ucsi);
+
+ UCSI_CMD_SET_NTFY_ENABLE(c, UCSI_ENABLE_NTFY_ALL);
+ ucsi_run_command(con->ucsi, &c, NULL, 0);
+
+ ucsi_reset_connector(con, true);
+ }
+
+ return ret;
+}
+
+static int
+ucsi_dr_swap(const struct typec_capability *cap, enum typec_data_role role)
+{
+ struct ucsi_connector *con = to_ucsi_connector(cap);
+ struct ucsi_control ctrl;
+ int ret = 0;
+
+ if (!con->partner)
+ return -ENOTCONN;
+
+ mutex_lock(&con->ucsi->ppm_lock);
+
+ if ((con->status.partner_type == UCSI_CONSTAT_PARTNER_TYPE_DFP &&
+ role == TYPEC_DEVICE) ||
+ (con->status.partner_type == UCSI_CONSTAT_PARTNER_TYPE_UFP &&
+ role == TYPEC_HOST))
+ goto out_unlock;
+
+ UCSI_CMD_SET_UOR(ctrl, con, role);
+ ret = ucsi_role_cmd(con, &ctrl);
+ if (ret < 0)
+ goto out_unlock;
+
+ mutex_unlock(&con->ucsi->ppm_lock);
+
+ if (!wait_for_completion_timeout(&con->complete,
+ msecs_to_jiffies(UCSI_SWAP_TIMEOUT_MS)))
+ return -ETIMEDOUT;
+
+ return 0;
+
+out_unlock:
+ mutex_unlock(&con->ucsi->ppm_lock);
+
+ return ret;
+}
+
+static int
+ucsi_pr_swap(const struct typec_capability *cap, enum typec_role role)
+{
+ struct ucsi_connector *con = to_ucsi_connector(cap);
+ struct ucsi_control ctrl;
+ int ret = 0;
+
+ if (!con->partner)
+ return -ENOTCONN;
+
+ mutex_lock(&con->ucsi->ppm_lock);
+
+ if (con->status.pwr_dir == role)
+ goto out_unlock;
+
+ UCSI_CMD_SET_PDR(ctrl, con, role);
+ ret = ucsi_role_cmd(con, &ctrl);
+ if (ret < 0)
+ goto out_unlock;
+
+ mutex_unlock(&con->ucsi->ppm_lock);
+
+ if (!wait_for_completion_timeout(&con->complete,
+ msecs_to_jiffies(UCSI_SWAP_TIMEOUT_MS)))
+ return -ETIMEDOUT;
+
+ mutex_lock(&con->ucsi->ppm_lock);
+
+ /* Something has gone wrong while swapping the role */
+ if (con->status.pwr_op_mode != UCSI_CONSTAT_PWR_OPMODE_PD) {
+ ucsi_reset_connector(con, true);
+ ret = -EPROTO;
+ }
+
+out_unlock:
+ mutex_unlock(&con->ucsi->ppm_lock);
+
+ return ret;
+}
+
+static struct fwnode_handle *ucsi_find_fwnode(struct ucsi_connector *con)
+{
+ struct fwnode_handle *fwnode;
+ int i = 1;
+
+ device_for_each_child_node(con->ucsi->dev, fwnode)
+ if (i++ == con->num)
+ return fwnode;
+ return NULL;
+}
+
+static int ucsi_register_port(struct ucsi *ucsi, int index)
+{
+ struct ucsi_connector *con = &ucsi->connector[index];
+ struct typec_capability *cap = &con->typec_cap;
+ enum typec_accessory *accessory = cap->accessory;
+ struct ucsi_control ctrl;
+ int ret;
+
+ INIT_WORK(&con->work, ucsi_connector_change);
+ init_completion(&con->complete);
+ con->num = index + 1;
+ con->ucsi = ucsi;
+
+ /* Get connector capability */
+ UCSI_CMD_GET_CONNECTOR_CAPABILITY(ctrl, con->num);
+ ret = ucsi_run_command(ucsi, &ctrl, &con->cap, sizeof(con->cap));
+ if (ret < 0)
+ return ret;
+
+ if (con->cap.op_mode & UCSI_CONCAP_OPMODE_DRP)
+ cap->type = TYPEC_PORT_DRP;
+ else if (con->cap.op_mode & UCSI_CONCAP_OPMODE_DFP)
+ cap->type = TYPEC_PORT_DFP;
+ else if (con->cap.op_mode & UCSI_CONCAP_OPMODE_UFP)
+ cap->type = TYPEC_PORT_UFP;
+
+ cap->revision = ucsi->cap.typec_version;
+ cap->pd_revision = ucsi->cap.pd_version;
+ cap->prefer_role = TYPEC_NO_PREFERRED_ROLE;
+
+ if (con->cap.op_mode & UCSI_CONCAP_OPMODE_AUDIO_ACCESSORY)
+ *accessory++ = TYPEC_ACCESSORY_AUDIO;
+ if (con->cap.op_mode & UCSI_CONCAP_OPMODE_DEBUG_ACCESSORY)
+ *accessory = TYPEC_ACCESSORY_DEBUG;
+
+ cap->fwnode = ucsi_find_fwnode(con);
+ cap->dr_set = ucsi_dr_swap;
+ cap->pr_set = ucsi_pr_swap;
+
+ /* Register the connector */
+ con->port = typec_register_port(ucsi->dev, cap);
+ if (!con->port)
+ return -ENODEV;
+
+ /* Get the status */
+ UCSI_CMD_GET_CONNECTOR_STATUS(ctrl, con->num);
+ ret = ucsi_run_command(ucsi, &ctrl, &con->status, sizeof(con->status));
+ if (ret < 0) {
+ dev_err(ucsi->dev, "con%d: failed to get status\n", con->num);
+ return 0;
+ }
+
+ ucsi_pwr_opmode_change(con);
+ typec_set_pwr_role(con->port, con->status.pwr_dir);
+
+ switch (con->status.partner_type) {
+ case UCSI_CONSTAT_PARTNER_TYPE_UFP:
+ typec_set_data_role(con->port, TYPEC_HOST);
+ break;
+ case UCSI_CONSTAT_PARTNER_TYPE_DFP:
+ typec_set_data_role(con->port, TYPEC_DEVICE);
+ break;
+ default:
+ break;
+ }
+
+ /* Check if there is already something connected */
+ if (con->status.connected)
+ ucsi_register_partner(con);
+
+ trace_ucsi_register_port(con->num, &con->status);
+
+ return 0;
+}
+
+static void ucsi_init(struct work_struct *work)
+{
+ struct ucsi *ucsi = container_of(work, struct ucsi, work);
+ struct ucsi_connector *con;
+ struct ucsi_control ctrl;
+ int ret;
+ int i;
+
+ mutex_lock(&ucsi->ppm_lock);
+
+ /* Reset the PPM */
+ ret = ucsi_reset_ppm(ucsi);
+ if (ret) {
+ dev_err(ucsi->dev, "failed to reset PPM!\n");
+ goto err;
+ }
+
+ /* Enable basic notifications */
+ UCSI_CMD_SET_NTFY_ENABLE(ctrl, UCSI_ENABLE_NTFY_CMD_COMPLETE |
+ UCSI_ENABLE_NTFY_ERROR);
+ ret = ucsi_run_command(ucsi, &ctrl, NULL, 0);
+ if (ret < 0)
+ goto err_reset;
+
+ /* Get PPM capabilities */
+ UCSI_CMD_GET_CAPABILITY(ctrl);
+ ret = ucsi_run_command(ucsi, &ctrl, &ucsi->cap, sizeof(ucsi->cap));
+ if (ret < 0)
+ goto err_reset;
+
+ if (!ucsi->cap.num_connectors) {
+ ret = -ENODEV;
+ goto err_reset;
+ }
+
+ /* Allocate the connectors. Released in ucsi_unregister_ppm() */
+ ucsi->connector = kcalloc(ucsi->cap.num_connectors + 1,
+ sizeof(*ucsi->connector), GFP_KERNEL);
+ if (!ucsi->connector) {
+ ret = -ENOMEM;
+ goto err_reset;
+ }
+
+ /* Register all connectors */
+ for (i = 0; i < ucsi->cap.num_connectors; i++) {
+ ret = ucsi_register_port(ucsi, i);
+ if (ret)
+ goto err_unregister;
+ }
+
+ /* Enable all notifications */
+ UCSI_CMD_SET_NTFY_ENABLE(ctrl, UCSI_ENABLE_NTFY_ALL);
+ ret = ucsi_run_command(ucsi, &ctrl, NULL, 0);
+ if (ret < 0)
+ goto err_unregister;
+
+ mutex_unlock(&ucsi->ppm_lock);
+
+ return;
+
+err_unregister:
+ for (con = ucsi->connector; con->port; con++) {
+ ucsi_unregister_partner(con);
+ typec_unregister_port(con->port);
+ con->port = NULL;
+ }
+
+err_reset:
+ ucsi_reset_ppm(ucsi);
+err:
+ mutex_unlock(&ucsi->ppm_lock);
+ dev_err(ucsi->dev, "PPM init failed (%d)\n", ret);
+}
+
+/**
+ * ucsi_register_ppm - Register UCSI PPM Interface
+ * @dev: Device interface to the PPM
+ * @ppm: The PPM interface
+ *
+ * Allocates UCSI instance, associates it with @ppm and returns it to the
+ * caller, and schedules initialization of the interface.
+ */
+struct ucsi *ucsi_register_ppm(struct device *dev, struct ucsi_ppm *ppm)
+{
+ struct ucsi *ucsi;
+
+ ucsi = kzalloc(sizeof(*ucsi), GFP_KERNEL);
+ if (!ucsi)
+ return ERR_PTR(-ENOMEM);
+
+ INIT_WORK(&ucsi->work, ucsi_init);
+ init_completion(&ucsi->complete);
+ mutex_init(&ucsi->ppm_lock);
+
+ ucsi->dev = dev;
+ ucsi->ppm = ppm;
+
+ /*
+ * Communication with the PPM takes a lot of time. It is not reasonable
+ * to initialize the driver here. Using a work for now.
+ */
+ queue_work(system_long_wq, &ucsi->work);
+
+ return ucsi;
+}
+EXPORT_SYMBOL_GPL(ucsi_register_ppm);
+
+/**
+ * ucsi_unregister_ppm - Unregister UCSI PPM Interface
+ * @ucsi: struct ucsi associated with the PPM
+ *
+ * Unregister UCSI PPM that was created with ucsi_register().
+ */
+void ucsi_unregister_ppm(struct ucsi *ucsi)
+{
+ struct ucsi_control ctrl;
+ int i;
+
+ /* Make sure that we are not in the middle of driver initialization */
+ cancel_work_sync(&ucsi->work);
+
+ mutex_lock(&ucsi->ppm_lock);
+
+ /* Disable everything except command complete notification */
+ UCSI_CMD_SET_NTFY_ENABLE(ctrl, UCSI_ENABLE_NTFY_CMD_COMPLETE)
+ ucsi_run_command(ucsi, &ctrl, NULL, 0);
+
+ mutex_unlock(&ucsi->ppm_lock);
+
+ for (i = 0; i < ucsi->cap.num_connectors; i++) {
+ cancel_work_sync(&ucsi->connector[i].work);
+ ucsi_unregister_partner(&ucsi->connector[i]);
+ typec_unregister_port(ucsi->connector[i].port);
+ }
+
+ ucsi_reset_ppm(ucsi);
+
+ kfree(ucsi->connector);
+ kfree(ucsi);
+}
+EXPORT_SYMBOL_GPL(ucsi_unregister_ppm);
+
+MODULE_AUTHOR("Heikki Krogerus <heikki.krogerus@linux.intel.com>");
+MODULE_LICENSE("GPL v2");
+MODULE_DESCRIPTION("USB Type-C Connector System Software Interface driver");
diff --git a/drivers/usb/misc/ucsi.h b/drivers/usb/typec/ucsi/ucsi.h
index 6dd11d1fe225..6b0d2f0918c6 100644
--- a/drivers/usb/misc/ucsi.h
+++ b/drivers/usb/typec/ucsi/ucsi.h
@@ -1,21 +1,25 @@
+#ifndef __DRIVER_USB_TYPEC_UCSI_H
+#define __DRIVER_USB_TYPEC_UCSI_H
+
+#include <linux/bitops.h>
#include <linux/types.h>
/* -------------------------------------------------------------------------- */
/* Command Status and Connector Change Indication (CCI) data structure */
struct ucsi_cci {
- unsigned int RESERVED1:1;
- unsigned int connector_change:7;
+ u8:1; /* reserved */
+ u8 connector_change:7;
u8 data_length;
- unsigned int RESERVED9:9;
- unsigned int not_supported:1;
- unsigned int cancel_complete:1;
- unsigned int reset_complete:1;
- unsigned int busy:1;
- unsigned int ack_complete:1;
- unsigned int error:1;
- unsigned int cmd_complete:1;
+ u16:9; /* reserved */
+ u16 not_supported:1;
+ u16 cancel_complete:1;
+ u16 reset_complete:1;
+ u16 busy:1;
+ u16 ack_complete:1;
+ u16 error:1;
+ u16 cmd_complete:1;
} __packed;
/* Default fields in CONTROL data structure */
@@ -25,16 +29,33 @@ struct ucsi_command {
u64 data:48;
} __packed;
+/* ACK Command structure */
+struct ucsi_ack_cmd {
+ u8 cmd;
+ u8 length;
+ u8 cci_ack:1;
+ u8 cmd_ack:1;
+ u8:6; /* reserved */
+} __packed;
+
+/* Connector Reset Command structure */
+struct ucsi_con_rst {
+ u8 cmd;
+ u8 length;
+ u8 con_num:7;
+ u8 hard_reset:1;
+} __packed;
+
/* Set USB Operation Mode Command structure */
struct ucsi_uor_cmd {
u8 cmd;
u8 length;
- u64 con_num:7;
- u64 role:3;
+ u16 con_num:7;
+ u16 role:3;
#define UCSI_UOR_ROLE_DFP BIT(0)
#define UCSI_UOR_ROLE_UFP BIT(1)
#define UCSI_UOR_ROLE_DRP BIT(2)
- u64 data:38;
+ u16:6; /* reserved */
} __packed;
struct ucsi_control {
@@ -42,20 +63,82 @@ struct ucsi_control {
u64 raw_cmd;
struct ucsi_command cmd;
struct ucsi_uor_cmd uor;
+ struct ucsi_ack_cmd ack;
+ struct ucsi_con_rst con_rst;
};
};
-struct ucsi_data {
- u16 version;
- u16 RESERVED;
- union {
- u32 raw_cci;
- struct ucsi_cci cci;
- };
- struct ucsi_control ctrl;
- u32 message_in[4];
- u32 message_out[4];
-} __packed;
+#define __UCSI_CMD(_ctrl_, _cmd_) \
+{ \
+ (_ctrl_).raw_cmd = 0; \
+ (_ctrl_).cmd.cmd = _cmd_; \
+}
+
+/* Helper for preparing ucsi_control for CONNECTOR_RESET command. */
+#define UCSI_CMD_CONNECTOR_RESET(_ctrl_, _con_, _hard_) \
+{ \
+ __UCSI_CMD(_ctrl_, UCSI_CONNECTOR_RESET) \
+ (_ctrl_).con_rst.con_num = (_con_)->num; \
+ (_ctrl_).con_rst.hard_reset = _hard_; \
+}
+
+/* Helper for preparing ucsi_control for ACK_CC_CI command. */
+#define UCSI_CMD_ACK(_ctrl_, _ack_) \
+{ \
+ __UCSI_CMD(_ctrl_, UCSI_ACK_CC_CI) \
+ (_ctrl_).ack.cci_ack = ((_ack_) == UCSI_ACK_EVENT); \
+ (_ctrl_).ack.cmd_ack = ((_ack_) == UCSI_ACK_CMD); \
+}
+
+/* Helper for preparing ucsi_control for SET_NOTIFY_ENABLE command. */
+#define UCSI_CMD_SET_NTFY_ENABLE(_ctrl_, _ntfys_) \
+{ \
+ __UCSI_CMD(_ctrl_, UCSI_SET_NOTIFICATION_ENABLE) \
+ (_ctrl_).cmd.data = _ntfys_; \
+}
+
+/* Helper for preparing ucsi_control for GET_CAPABILITY command. */
+#define UCSI_CMD_GET_CAPABILITY(_ctrl_) \
+{ \
+ __UCSI_CMD(_ctrl_, UCSI_GET_CAPABILITY) \
+}
+
+/* Helper for preparing ucsi_control for GET_CONNECTOR_CAPABILITY command. */
+#define UCSI_CMD_GET_CONNECTOR_CAPABILITY(_ctrl_, _con_) \
+{ \
+ __UCSI_CMD(_ctrl_, UCSI_GET_CONNECTOR_CAPABILITY) \
+ (_ctrl_).cmd.data = _con_; \
+}
+
+/* Helper for preparing ucsi_control for GET_CONNECTOR_STATUS command. */
+#define UCSI_CMD_GET_CONNECTOR_STATUS(_ctrl_, _con_) \
+{ \
+ __UCSI_CMD(_ctrl_, UCSI_GET_CONNECTOR_STATUS) \
+ (_ctrl_).cmd.data = _con_; \
+}
+
+#define __UCSI_ROLE(_ctrl_, _cmd_, _con_num_) \
+{ \
+ __UCSI_CMD(_ctrl_, _cmd_) \
+ (_ctrl_).uor.con_num = _con_num_; \
+ (_ctrl_).uor.role = UCSI_UOR_ROLE_DRP; \
+}
+
+/* Helper for preparing ucsi_control for SET_UOR command. */
+#define UCSI_CMD_SET_UOR(_ctrl_, _con_, _role_) \
+{ \
+ __UCSI_ROLE(_ctrl_, UCSI_SET_UOR, (_con_)->num) \
+ (_ctrl_).uor.role |= (_role_) == TYPEC_HOST ? UCSI_UOR_ROLE_DFP : \
+ UCSI_UOR_ROLE_UFP; \
+}
+
+/* Helper for preparing ucsi_control for SET_PDR command. */
+#define UCSI_CMD_SET_PDR(_ctrl_, _con_, _role_) \
+{ \
+ __UCSI_ROLE(_ctrl_, UCSI_SET_PDR, (_con_)->num) \
+ (_ctrl_).uor.role |= (_role_) == TYPEC_SOURCE ? UCSI_UOR_ROLE_DFP : \
+ UCSI_UOR_ROLE_UFP; \
+}
/* Commands */
#define UCSI_PPM_RESET 0x01
@@ -67,12 +150,12 @@ struct ucsi_data {
#define UCSI_GET_CONNECTOR_CAPABILITY 0x07
#define UCSI_SET_UOM 0x08
#define UCSI_SET_UOR 0x09
-#define UCSI_SET_PDM 0x0A
-#define UCSI_SET_PDR 0x0B
-#define UCSI_GET_ALTERNATE_MODES 0x0C
-#define UCSI_GET_CAM_SUPPORTED 0x0D
-#define UCSI_GET_CURRENT_CAM 0x0E
-#define UCSI_SET_NEW_CAM 0x0F
+#define UCSI_SET_PDM 0x0a
+#define UCSI_SET_PDR 0x0b
+#define UCSI_GET_ALTERNATE_MODES 0x0c
+#define UCSI_GET_CAM_SUPPORTED 0x0d
+#define UCSI_GET_CURRENT_CAM 0x0e
+#define UCSI_SET_NEW_CAM 0x0f
#define UCSI_GET_PDOS 0x10
#define UCSI_GET_CABLE_PROPERTY 0x11
#define UCSI_GET_CONNECTOR_STATUS 0x12
@@ -116,7 +199,7 @@ struct ucsi_capability {
#define UCSI_CAP_ATTR_POWER_AC_SUPPLY BIT(8)
#define UCSI_CAP_ATTR_POWER_OTHER BIT(10)
#define UCSI_CAP_ATTR_POWER_VBUS BIT(14)
- u8 num_connectors;
+ u32 num_connectors:8;
u32 features:24;
#define UCSI_CAP_SET_UOM BIT(0)
#define UCSI_CAP_SET_PDM BIT(1)
@@ -127,7 +210,7 @@ struct ucsi_capability {
#define UCSI_CAP_EXT_SUPPLY_NOTIFICATIONS BIT(6)
#define UCSI_CAP_PD_RESET BIT(7)
u8 num_alt_modes;
- u8 RESERVED;
+ u8 reserved;
u16 bc_version;
u16 pd_version;
u16 typec_version;
@@ -146,6 +229,12 @@ struct ucsi_connector_capability {
#define UCSI_CONCAP_OPMODE_ALT_MODE BIT(7)
u8 provider:1;
u8 consumer:1;
+ u8:6; /* reserved */
+} __packed;
+
+struct ucsi_altmode {
+ u16 svid;
+ u32 mid;
} __packed;
/* Data structure filled by PPM in response to GET_CABLE_PROPERTY command. */
@@ -161,9 +250,9 @@ struct ucsi_cable_property {
#define UCSI_CABLE_PROPERTY_PLUG_TYPE_C 2
#define UCSI_CABLE_PROPERTY_PLUG_OTHER 3
u8 mode_support:1;
- u8 RESERVED_2:2;
+ u8:2; /* reserved */
u8 latency:4;
- u8 RESERVED_4:4;
+ u8:4; /* reserved */
} __packed;
/* Data structure filled by PPM in response to GET_CONNECTOR_STATUS command. */
@@ -185,7 +274,7 @@ struct ucsi_connector_status {
#define UCSI_CONSTAT_PWR_OPMODE_DEFAULT 1
#define UCSI_CONSTAT_PWR_OPMODE_BC 2
#define UCSI_CONSTAT_PWR_OPMODE_PD 3
-#define UCSI_CONSTAT_PWR_OPMODE_TYPEC1_3 4
+#define UCSI_CONSTAT_PWR_OPMODE_TYPEC1_5 4
#define UCSI_CONSTAT_PWR_OPMODE_TYPEC3_0 5
u16 connected:1;
u16 pwr_dir:1;
@@ -195,7 +284,7 @@ struct ucsi_connector_status {
u16 partner_type:3;
#define UCSI_CONSTAT_PARTNER_TYPE_DFP 1
#define UCSI_CONSTAT_PARTNER_TYPE_UFP 2
-#define UCSI_CONSTAT_PARTNER_TYPE_CABLE_NO_UFP 3 /* Powered Cable */
+#define UCSI_CONSTAT_PARTNER_TYPE_CABLE 3 /* Powered Cable */
#define UCSI_CONSTAT_PARTNER_TYPE_CABLE_AND_UFP 4 /* Powered Cable */
#define UCSI_CONSTAT_PARTNER_TYPE_DEBUG 5
#define UCSI_CONSTAT_PARTNER_TYPE_AUDIO 6
@@ -208,8 +297,39 @@ struct ucsi_connector_status {
u8 provider_cap_limit_reason:4;
#define UCSI_CONSTAT_CAP_PWR_LOWERED 0
#define UCSI_CONSTAT_CAP_PWR_BUDGET_LIMIT 1
- u8 RESERVED:2;
+ u8:2; /* reserved */
} __packed;
/* -------------------------------------------------------------------------- */
+struct ucsi;
+
+struct ucsi_data {
+ u16 version;
+ u16 reserved;
+ union {
+ u32 raw_cci;
+ struct ucsi_cci cci;
+ };
+ struct ucsi_control ctrl;
+ u32 message_in[4];
+ u32 message_out[4];
+} __packed;
+
+/*
+ * struct ucsi_ppm - Interface to UCSI Platform Policy Manager
+ * @data: memory location to the UCSI data structures
+ * @cmd: UCSI command execution routine
+ * @sync: Refresh UCSI mailbox (the data structures)
+ */
+struct ucsi_ppm {
+ struct ucsi_data *data;
+ int (*cmd)(struct ucsi_ppm *, struct ucsi_control *);
+ int (*sync)(struct ucsi_ppm *);
+};
+
+struct ucsi *ucsi_register_ppm(struct device *dev, struct ucsi_ppm *ppm);
+void ucsi_unregister_ppm(struct ucsi *ucsi);
+void ucsi_notify(struct ucsi *ucsi);
+
+#endif /* __DRIVER_USB_TYPEC_UCSI_H */
diff --git a/drivers/usb/typec/ucsi/ucsi_acpi.c b/drivers/usb/typec/ucsi/ucsi_acpi.c
new file mode 100644
index 000000000000..cabd47612b0a
--- /dev/null
+++ b/drivers/usb/typec/ucsi/ucsi_acpi.c
@@ -0,0 +1,158 @@
+/*
+ * UCSI ACPI driver
+ *
+ * Copyright (C) 2017, Intel Corporation
+ * Author: Heikki Krogerus <heikki.krogerus@linux.intel.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/platform_device.h>
+#include <linux/module.h>
+#include <linux/acpi.h>
+
+#include "ucsi.h"
+
+#define UCSI_DSM_UUID "6f8398c2-7ca4-11e4-ad36-631042b5008f"
+#define UCSI_DSM_FUNC_WRITE 1
+#define UCSI_DSM_FUNC_READ 2
+
+struct ucsi_acpi {
+ struct device *dev;
+ struct ucsi *ucsi;
+ struct ucsi_ppm ppm;
+ guid_t guid;
+};
+
+static int ucsi_acpi_dsm(struct ucsi_acpi *ua, int func)
+{
+ union acpi_object *obj;
+
+ obj = acpi_evaluate_dsm(ACPI_HANDLE(ua->dev), &ua->guid, 1, func,
+ NULL);
+ if (!obj) {
+ dev_err(ua->dev, "%s: failed to evaluate _DSM %d\n",
+ __func__, func);
+ return -EIO;
+ }
+
+ ACPI_FREE(obj);
+ return 0;
+}
+
+static int ucsi_acpi_cmd(struct ucsi_ppm *ppm, struct ucsi_control *ctrl)
+{
+ struct ucsi_acpi *ua = container_of(ppm, struct ucsi_acpi, ppm);
+
+ ppm->data->ctrl.raw_cmd = ctrl->raw_cmd;
+
+ return ucsi_acpi_dsm(ua, UCSI_DSM_FUNC_WRITE);
+}
+
+static int ucsi_acpi_sync(struct ucsi_ppm *ppm)
+{
+ struct ucsi_acpi *ua = container_of(ppm, struct ucsi_acpi, ppm);
+
+ return ucsi_acpi_dsm(ua, UCSI_DSM_FUNC_READ);
+}
+
+static void ucsi_acpi_notify(acpi_handle handle, u32 event, void *data)
+{
+ struct ucsi_acpi *ua = data;
+
+ ucsi_notify(ua->ucsi);
+}
+
+static int ucsi_acpi_probe(struct platform_device *pdev)
+{
+ struct ucsi_acpi *ua;
+ struct resource *res;
+ acpi_status status;
+ int ret;
+
+ ua = devm_kzalloc(&pdev->dev, sizeof(*ua), GFP_KERNEL);
+ if (!ua)
+ return -ENOMEM;
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (!res) {
+ dev_err(&pdev->dev, "missing memory resource\n");
+ return -ENODEV;
+ }
+
+ /*
+ * NOTE: The memory region for the data structures is used also in an
+ * operation region, which means ACPI has already reserved it. Therefore
+ * it can not be requested here, and we can not use
+ * devm_ioremap_resource().
+ */
+ ua->ppm.data = devm_ioremap(&pdev->dev, res->start, resource_size(res));
+ if (!ua->ppm.data)
+ return -ENOMEM;
+
+ if (!ua->ppm.data->version)
+ return -ENODEV;
+
+ ret = guid_parse(UCSI_DSM_UUID, &ua->guid);
+ if (ret)
+ return ret;
+
+ ua->ppm.cmd = ucsi_acpi_cmd;
+ ua->ppm.sync = ucsi_acpi_sync;
+ ua->dev = &pdev->dev;
+
+ status = acpi_install_notify_handler(ACPI_HANDLE(&pdev->dev),
+ ACPI_DEVICE_NOTIFY,
+ ucsi_acpi_notify, ua);
+ if (ACPI_FAILURE(status)) {
+ dev_err(&pdev->dev, "failed to install notify handler\n");
+ return -ENODEV;
+ }
+
+ ua->ucsi = ucsi_register_ppm(&pdev->dev, &ua->ppm);
+ if (IS_ERR(ua->ucsi)) {
+ acpi_remove_notify_handler(ACPI_HANDLE(&pdev->dev),
+ ACPI_DEVICE_NOTIFY,
+ ucsi_acpi_notify);
+ return PTR_ERR(ua->ucsi);
+ }
+
+ platform_set_drvdata(pdev, ua);
+
+ return 0;
+}
+
+static int ucsi_acpi_remove(struct platform_device *pdev)
+{
+ struct ucsi_acpi *ua = platform_get_drvdata(pdev);
+
+ ucsi_unregister_ppm(ua->ucsi);
+
+ acpi_remove_notify_handler(ACPI_HANDLE(&pdev->dev), ACPI_DEVICE_NOTIFY,
+ ucsi_acpi_notify);
+
+ return 0;
+}
+
+static const struct acpi_device_id ucsi_acpi_match[] = {
+ { "PNP0CA0", 0 },
+ { },
+};
+MODULE_DEVICE_TABLE(acpi, ucsi_acpi_match);
+
+static struct platform_driver ucsi_acpi_platform_driver = {
+ .driver = {
+ .name = "ucsi_acpi",
+ .acpi_match_table = ACPI_PTR(ucsi_acpi_match),
+ },
+ .probe = ucsi_acpi_probe,
+ .remove = ucsi_acpi_remove,
+};
+
+module_platform_driver(ucsi_acpi_platform_driver);
+
+MODULE_AUTHOR("Heikki Krogerus <heikki.krogerus@linux.intel.com>");
+MODULE_LICENSE("GPL v2");
+MODULE_DESCRIPTION("UCSI ACPI driver");
diff --git a/drivers/usb/usbip/stub_main.c b/drivers/usb/usbip/stub_main.c
index e74fbb7f4a32..660180a5d5c4 100644
--- a/drivers/usb/usbip/stub_main.c
+++ b/drivers/usb/usbip/stub_main.c
@@ -261,7 +261,11 @@ void stub_device_cleanup_urbs(struct stub_device *sdev)
kmem_cache_free(stub_priv_cache, priv);
kfree(urb->transfer_buffer);
+ urb->transfer_buffer = NULL;
+
kfree(urb->setup_packet);
+ urb->setup_packet = NULL;
+
usb_free_urb(urb);
}
}
diff --git a/drivers/usb/usbip/stub_tx.c b/drivers/usb/usbip/stub_tx.c
index 6b1e8c3f0e4b..be50cef645d8 100644
--- a/drivers/usb/usbip/stub_tx.c
+++ b/drivers/usb/usbip/stub_tx.c
@@ -28,7 +28,11 @@ static void stub_free_priv_and_urb(struct stub_priv *priv)
struct urb *urb = priv->urb;
kfree(urb->setup_packet);
+ urb->setup_packet = NULL;
+
kfree(urb->transfer_buffer);
+ urb->transfer_buffer = NULL;
+
list_del(&priv->list);
kmem_cache_free(stub_priv_cache, priv);
usb_free_urb(urb);
diff --git a/drivers/usb/usbip/vhci.h b/drivers/usb/usbip/vhci.h
index 88b71c4e068f..5cfb59e98e44 100644
--- a/drivers/usb/usbip/vhci.h
+++ b/drivers/usb/usbip/vhci.h
@@ -72,6 +72,11 @@ struct vhci_unlink {
unsigned long unlink_seqnum;
};
+enum hub_speed {
+ HUB_SPEED_HIGH = 0,
+ HUB_SPEED_SUPER,
+};
+
/* Number of supported ports. Value has an upperbound of USB_MAXCHILDREN */
#ifdef CONFIG_USBIP_VHCI_HC_PORTS
#define VHCI_HC_PORTS CONFIG_USBIP_VHCI_HC_PORTS
@@ -79,6 +84,9 @@ struct vhci_unlink {
#define VHCI_HC_PORTS 8
#endif
+/* Each VHCI has 2 hubs (USB2 and USB3), each has VHCI_HC_PORTS ports */
+#define VHCI_PORTS (VHCI_HC_PORTS*2)
+
#ifdef CONFIG_USBIP_VHCI_NR_HCS
#define VHCI_NR_HCS CONFIG_USBIP_VHCI_NR_HCS
#else
@@ -87,10 +95,19 @@ struct vhci_unlink {
#define MAX_STATUS_NAME 16
-/* for usb_bus.hcpriv */
-struct vhci_hcd {
+struct vhci {
spinlock_t lock;
+ struct platform_device *pdev;
+
+ struct vhci_hcd *vhci_hcd_hs;
+ struct vhci_hcd *vhci_hcd_ss;
+};
+
+/* for usb_hcd.hcd_priv[0] */
+struct vhci_hcd {
+ struct vhci *vhci;
+
u32 port_status[VHCI_HC_PORTS];
unsigned resuming:1;
@@ -107,7 +124,7 @@ struct vhci_hcd {
};
extern int vhci_num_controllers;
-extern struct platform_device **vhci_pdevs;
+extern struct vhci *vhcis;
extern struct attribute_group vhci_attr_group;
/* vhci_hcd.c */
@@ -131,10 +148,10 @@ static inline __u32 port_to_rhport(__u32 port)
static inline int port_to_pdev_nr(__u32 port)
{
- return port / VHCI_HC_PORTS;
+ return port / VHCI_PORTS;
}
-static inline struct vhci_hcd *hcd_to_vhci(struct usb_hcd *hcd)
+static inline struct vhci_hcd *hcd_to_vhci_hcd(struct usb_hcd *hcd)
{
return (struct vhci_hcd *) (hcd->hcd_priv);
}
@@ -149,15 +166,14 @@ static inline const char *hcd_name(struct usb_hcd *hcd)
return (hcd)->self.bus_name;
}
-static inline struct usb_hcd *vhci_to_hcd(struct vhci_hcd *vhci)
+static inline struct usb_hcd *vhci_hcd_to_hcd(struct vhci_hcd *vhci_hcd)
{
- return container_of((void *) vhci, struct usb_hcd, hcd_priv);
+ return container_of((void *) vhci_hcd, struct usb_hcd, hcd_priv);
}
-static inline struct vhci_hcd *vdev_to_vhci(struct vhci_device *vdev)
+static inline struct vhci_hcd *vdev_to_vhci_hcd(struct vhci_device *vdev)
{
- return container_of(
- (void *)(vdev - vdev->rhport), struct vhci_hcd, vdev);
+ return container_of((void *)(vdev - vdev->rhport), struct vhci_hcd, vdev);
}
#endif /* __USBIP_VHCI_H */
diff --git a/drivers/usb/usbip/vhci_hcd.c b/drivers/usb/usbip/vhci_hcd.c
index 0585078638db..2c4b2fd40406 100644
--- a/drivers/usb/usbip/vhci_hcd.c
+++ b/drivers/usb/usbip/vhci_hcd.c
@@ -58,8 +58,7 @@ static const char driver_name[] = "vhci_hcd";
static const char driver_desc[] = "USB/IP Virtual Host Controller";
int vhci_num_controllers = VHCI_NR_HCS;
-
-struct platform_device **vhci_pdevs;
+struct vhci *vhcis;
static const char * const bit_desc[] = {
"CONNECTION", /*0*/
@@ -67,7 +66,7 @@ static const char * const bit_desc[] = {
"SUSPEND", /*2*/
"OVER_CURRENT", /*3*/
"RESET", /*4*/
- "R5", /*5*/
+ "L1", /*5*/
"R6", /*6*/
"R7", /*7*/
"POWER", /*8*/
@@ -83,7 +82,7 @@ static const char * const bit_desc[] = {
"C_SUSPEND", /*18*/
"C_OVER_CURRENT", /*19*/
"C_RESET", /*20*/
- "R21", /*21*/
+ "C_L1", /*21*/
"R22", /*22*/
"R23", /*23*/
"R24", /*24*/
@@ -96,10 +95,49 @@ static const char * const bit_desc[] = {
"R31", /*31*/
};
-static void dump_port_status_diff(u32 prev_status, u32 new_status)
+static const char * const bit_desc_ss[] = {
+ "CONNECTION", /*0*/
+ "ENABLE", /*1*/
+ "SUSPEND", /*2*/
+ "OVER_CURRENT", /*3*/
+ "RESET", /*4*/
+ "L1", /*5*/
+ "R6", /*6*/
+ "R7", /*7*/
+ "R8", /*8*/
+ "POWER", /*9*/
+ "HIGHSPEED", /*10*/
+ "PORT_TEST", /*11*/
+ "INDICATOR", /*12*/
+ "R13", /*13*/
+ "R14", /*14*/
+ "R15", /*15*/
+ "C_CONNECTION", /*16*/
+ "C_ENABLE", /*17*/
+ "C_SUSPEND", /*18*/
+ "C_OVER_CURRENT", /*19*/
+ "C_RESET", /*20*/
+ "C_BH_RESET", /*21*/
+ "C_LINK_STATE", /*22*/
+ "C_CONFIG_ERROR", /*23*/
+ "R24", /*24*/
+ "R25", /*25*/
+ "R26", /*26*/
+ "R27", /*27*/
+ "R28", /*28*/
+ "R29", /*29*/
+ "R30", /*30*/
+ "R31", /*31*/
+};
+
+static void dump_port_status_diff(u32 prev_status, u32 new_status, bool usb3)
{
int i = 0;
u32 bit = 1;
+ const char * const *desc = bit_desc;
+
+ if (usb3)
+ desc = bit_desc_ss;
pr_debug("status prev -> new: %08x -> %08x\n", prev_status, new_status);
while (bit) {
@@ -114,8 +152,12 @@ static void dump_port_status_diff(u32 prev_status, u32 new_status)
else
change = ' ';
- if (prev || new)
- pr_debug(" %c%s\n", change, bit_desc[i]);
+ if (prev || new) {
+ pr_debug(" %c%s\n", change, desc[i]);
+
+ if (bit == 1) /* USB_PORT_STAT_CONNECTION */
+ pr_debug(" %c%s\n", change, "USB_PORT_STAT_SPEED_5GBPS");
+ }
bit <<= 1;
i++;
}
@@ -124,7 +166,8 @@ static void dump_port_status_diff(u32 prev_status, u32 new_status)
void rh_port_connect(struct vhci_device *vdev, enum usb_device_speed speed)
{
- struct vhci_hcd *vhci = vdev_to_vhci(vdev);
+ struct vhci_hcd *vhci_hcd = vdev_to_vhci_hcd(vdev);
+ struct vhci *vhci = vhci_hcd->vhci;
int rhport = vdev->rhport;
u32 status;
unsigned long flags;
@@ -133,7 +176,7 @@ void rh_port_connect(struct vhci_device *vdev, enum usb_device_speed speed)
spin_lock_irqsave(&vhci->lock, flags);
- status = vhci->port_status[rhport];
+ status = vhci_hcd->port_status[rhport];
status |= USB_PORT_STAT_CONNECTION | (1 << USB_PORT_FEAT_C_CONNECTION);
@@ -148,16 +191,17 @@ void rh_port_connect(struct vhci_device *vdev, enum usb_device_speed speed)
break;
}
- vhci->port_status[rhport] = status;
+ vhci_hcd->port_status[rhport] = status;
spin_unlock_irqrestore(&vhci->lock, flags);
- usb_hcd_poll_rh_status(vhci_to_hcd(vhci));
+ usb_hcd_poll_rh_status(vhci_hcd_to_hcd(vhci_hcd));
}
static void rh_port_disconnect(struct vhci_device *vdev)
{
- struct vhci_hcd *vhci = vdev_to_vhci(vdev);
+ struct vhci_hcd *vhci_hcd = vdev_to_vhci_hcd(vdev);
+ struct vhci *vhci = vhci_hcd->vhci;
int rhport = vdev->rhport;
u32 status;
unsigned long flags;
@@ -166,15 +210,15 @@ static void rh_port_disconnect(struct vhci_device *vdev)
spin_lock_irqsave(&vhci->lock, flags);
- status = vhci->port_status[rhport];
+ status = vhci_hcd->port_status[rhport];
status &= ~USB_PORT_STAT_CONNECTION;
status |= (1 << USB_PORT_FEAT_C_CONNECTION);
- vhci->port_status[rhport] = status;
+ vhci_hcd->port_status[rhport] = status;
spin_unlock_irqrestore(&vhci->lock, flags);
- usb_hcd_poll_rh_status(vhci_to_hcd(vhci));
+ usb_hcd_poll_rh_status(vhci_hcd_to_hcd(vhci_hcd));
}
#define PORT_C_MASK \
@@ -197,17 +241,15 @@ static void rh_port_disconnect(struct vhci_device *vdev)
*/
static int vhci_hub_status(struct usb_hcd *hcd, char *buf)
{
- struct vhci_hcd *vhci;
- int retval;
+ struct vhci_hcd *vhci_hcd = hcd_to_vhci_hcd(hcd);
+ struct vhci *vhci = vhci_hcd->vhci;
+ int retval = DIV_ROUND_UP(VHCI_HC_PORTS + 1, 8);
int rhport;
int changed = 0;
unsigned long flags;
- retval = DIV_ROUND_UP(VHCI_HC_PORTS + 1, 8);
memset(buf, 0, retval);
- vhci = hcd_to_vhci(hcd);
-
spin_lock_irqsave(&vhci->lock, flags);
if (!HCD_HW_ACCESSIBLE(hcd)) {
usbip_dbg_vhci_rh("hw accessible flag not on?\n");
@@ -216,7 +258,7 @@ static int vhci_hub_status(struct usb_hcd *hcd, char *buf)
/* check pseudo status register for each port */
for (rhport = 0; rhport < VHCI_HC_PORTS; rhport++) {
- if ((vhci->port_status[rhport] & PORT_C_MASK)) {
+ if ((vhci_hcd->port_status[rhport] & PORT_C_MASK)) {
/* The status of a port has been changed, */
usbip_dbg_vhci_rh("port %d status changed\n", rhport);
@@ -233,6 +275,40 @@ done:
return changed ? retval : 0;
}
+/* usb 3.0 root hub device descriptor */
+static struct {
+ struct usb_bos_descriptor bos;
+ struct usb_ss_cap_descriptor ss_cap;
+} __packed usb3_bos_desc = {
+
+ .bos = {
+ .bLength = USB_DT_BOS_SIZE,
+ .bDescriptorType = USB_DT_BOS,
+ .wTotalLength = cpu_to_le16(sizeof(usb3_bos_desc)),
+ .bNumDeviceCaps = 1,
+ },
+ .ss_cap = {
+ .bLength = USB_DT_USB_SS_CAP_SIZE,
+ .bDescriptorType = USB_DT_DEVICE_CAPABILITY,
+ .bDevCapabilityType = USB_SS_CAP_TYPE,
+ .wSpeedSupported = cpu_to_le16(USB_5GBPS_OPERATION),
+ .bFunctionalitySupport = ilog2(USB_5GBPS_OPERATION),
+ },
+};
+
+static inline void
+ss_hub_descriptor(struct usb_hub_descriptor *desc)
+{
+ memset(desc, 0, sizeof *desc);
+ desc->bDescriptorType = USB_DT_SS_HUB;
+ desc->bDescLength = 12;
+ desc->wHubCharacteristics = cpu_to_le16(
+ HUB_CHAR_INDV_PORT_LPSM | HUB_CHAR_COMMON_OCPM);
+ desc->bNbrPorts = VHCI_HC_PORTS;
+ desc->u.ss.bHubHdrDecLat = 0x04; /* Worst case: 0.4 micro sec*/
+ desc->u.ss.DeviceRemovable = 0xffff;
+}
+
static inline void hub_descriptor(struct usb_hub_descriptor *desc)
{
int width;
@@ -253,7 +329,8 @@ static inline void hub_descriptor(struct usb_hub_descriptor *desc)
static int vhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,
u16 wIndex, char *buf, u16 wLength)
{
- struct vhci_hcd *dum;
+ struct vhci_hcd *vhci_hcd;
+ struct vhci *vhci;
int retval = 0;
int rhport;
unsigned long flags;
@@ -265,21 +342,24 @@ static int vhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,
/*
* NOTE:
- * wIndex shows the port number and begins from 1.
+ * wIndex (bits 0-7) shows the port number and begins from 1?
*/
+ wIndex = ((__u8)(wIndex & 0x00ff));
usbip_dbg_vhci_rh("typeReq %x wValue %x wIndex %x\n", typeReq, wValue,
wIndex);
+
if (wIndex > VHCI_HC_PORTS)
pr_err("invalid port number %d\n", wIndex);
- rhport = ((__u8)(wIndex & 0x00ff)) - 1;
+ rhport = wIndex - 1;
- dum = hcd_to_vhci(hcd);
+ vhci_hcd = hcd_to_vhci_hcd(hcd);
+ vhci = vhci_hcd->vhci;
- spin_lock_irqsave(&dum->lock, flags);
+ spin_lock_irqsave(&vhci->lock, flags);
/* store old status and compare now and old later */
if (usbip_dbg_flag_vhci_rh) {
- memcpy(prev_port_status, dum->port_status,
+ memcpy(prev_port_status, vhci_hcd->port_status,
sizeof(prev_port_status));
}
@@ -290,45 +370,56 @@ static int vhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,
case ClearPortFeature:
switch (wValue) {
case USB_PORT_FEAT_SUSPEND:
- if (dum->port_status[rhport] & USB_PORT_STAT_SUSPEND) {
+ if (hcd->speed == HCD_USB3) {
+ pr_err(" ClearPortFeature: USB_PORT_FEAT_SUSPEND req not "
+ "supported for USB 3.0 roothub\n");
+ goto error;
+ }
+ usbip_dbg_vhci_rh(
+ " ClearPortFeature: USB_PORT_FEAT_SUSPEND\n");
+ if (vhci_hcd->port_status[rhport] & USB_PORT_STAT_SUSPEND) {
/* 20msec signaling */
- dum->resuming = 1;
- dum->re_timeout =
- jiffies + msecs_to_jiffies(20);
+ vhci_hcd->resuming = 1;
+ vhci_hcd->re_timeout = jiffies + msecs_to_jiffies(20);
}
break;
case USB_PORT_FEAT_POWER:
usbip_dbg_vhci_rh(
" ClearPortFeature: USB_PORT_FEAT_POWER\n");
- dum->port_status[rhport] = 0;
- dum->resuming = 0;
- break;
- case USB_PORT_FEAT_C_RESET:
- usbip_dbg_vhci_rh(
- " ClearPortFeature: USB_PORT_FEAT_C_RESET\n");
- switch (dum->vdev[rhport].speed) {
- case USB_SPEED_HIGH:
- dum->port_status[rhport] |=
- USB_PORT_STAT_HIGH_SPEED;
- break;
- case USB_SPEED_LOW:
- dum->port_status[rhport] |=
- USB_PORT_STAT_LOW_SPEED;
- break;
- default:
- break;
- }
+ if (hcd->speed == HCD_USB3)
+ vhci_hcd->port_status[rhport] &= ~USB_SS_PORT_STAT_POWER;
+ else
+ vhci_hcd->port_status[rhport] &= ~USB_PORT_STAT_POWER;
break;
default:
usbip_dbg_vhci_rh(" ClearPortFeature: default %x\n",
wValue);
- dum->port_status[rhport] &= ~(1 << wValue);
+ vhci_hcd->port_status[rhport] &= ~(1 << wValue);
break;
}
break;
case GetHubDescriptor:
usbip_dbg_vhci_rh(" GetHubDescriptor\n");
- hub_descriptor((struct usb_hub_descriptor *) buf);
+ if (hcd->speed == HCD_USB3 &&
+ (wLength < USB_DT_SS_HUB_SIZE ||
+ wValue != (USB_DT_SS_HUB << 8))) {
+ pr_err("Wrong hub descriptor type for USB 3.0 roothub.\n");
+ goto error;
+ }
+ if (hcd->speed == HCD_USB3)
+ ss_hub_descriptor((struct usb_hub_descriptor *) buf);
+ else
+ hub_descriptor((struct usb_hub_descriptor *) buf);
+ break;
+ case DeviceRequest | USB_REQ_GET_DESCRIPTOR:
+ if (hcd->speed != HCD_USB3)
+ goto error;
+
+ if ((wValue >> 8) != USB_DT_BOS)
+ goto error;
+
+ memcpy(buf, &usb3_bos_desc, sizeof(usb3_bos_desc));
+ retval = sizeof(usb3_bos_desc);
break;
case GetHubStatus:
usbip_dbg_vhci_rh(" GetHubStatus\n");
@@ -336,7 +427,7 @@ static int vhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,
break;
case GetPortStatus:
usbip_dbg_vhci_rh(" GetPortStatus port %x\n", wIndex);
- if (wIndex > VHCI_HC_PORTS || wIndex < 1) {
+ if (wIndex < 1) {
pr_err("invalid port number %d\n", wIndex);
retval = -EPIPE;
}
@@ -346,36 +437,48 @@ static int vhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,
/* whoever resets or resumes must GetPortStatus to
* complete it!!
*/
- if (dum->resuming && time_after(jiffies, dum->re_timeout)) {
- dum->port_status[rhport] |=
- (1 << USB_PORT_FEAT_C_SUSPEND);
- dum->port_status[rhport] &=
- ~(1 << USB_PORT_FEAT_SUSPEND);
- dum->resuming = 0;
- dum->re_timeout = 0;
+ if (vhci_hcd->resuming && time_after(jiffies, vhci_hcd->re_timeout)) {
+ vhci_hcd->port_status[rhport] |= (1 << USB_PORT_FEAT_C_SUSPEND);
+ vhci_hcd->port_status[rhport] &= ~(1 << USB_PORT_FEAT_SUSPEND);
+ vhci_hcd->resuming = 0;
+ vhci_hcd->re_timeout = 0;
}
- if ((dum->port_status[rhport] & (1 << USB_PORT_FEAT_RESET)) !=
- 0 && time_after(jiffies, dum->re_timeout)) {
- dum->port_status[rhport] |=
- (1 << USB_PORT_FEAT_C_RESET);
- dum->port_status[rhport] &=
- ~(1 << USB_PORT_FEAT_RESET);
- dum->re_timeout = 0;
+ if ((vhci_hcd->port_status[rhport] & (1 << USB_PORT_FEAT_RESET)) !=
+ 0 && time_after(jiffies, vhci_hcd->re_timeout)) {
+ vhci_hcd->port_status[rhport] |= (1 << USB_PORT_FEAT_C_RESET);
+ vhci_hcd->port_status[rhport] &= ~(1 << USB_PORT_FEAT_RESET);
+ vhci_hcd->re_timeout = 0;
- if (dum->vdev[rhport].ud.status ==
+ if (vhci_hcd->vdev[rhport].ud.status ==
VDEV_ST_NOTASSIGNED) {
usbip_dbg_vhci_rh(
" enable rhport %d (status %u)\n",
rhport,
- dum->vdev[rhport].ud.status);
- dum->port_status[rhport] |=
+ vhci_hcd->vdev[rhport].ud.status);
+ vhci_hcd->port_status[rhport] |=
USB_PORT_STAT_ENABLE;
}
+
+ if (hcd->speed < HCD_USB3) {
+ switch (vhci_hcd->vdev[rhport].speed) {
+ case USB_SPEED_HIGH:
+ vhci_hcd->port_status[rhport] |=
+ USB_PORT_STAT_HIGH_SPEED;
+ break;
+ case USB_SPEED_LOW:
+ vhci_hcd->port_status[rhport] |=
+ USB_PORT_STAT_LOW_SPEED;
+ break;
+ default:
+ pr_err("vhci_device speed not set\n");
+ break;
+ }
+ }
}
- ((__le16 *) buf)[0] = cpu_to_le16(dum->port_status[rhport]);
+ ((__le16 *) buf)[0] = cpu_to_le16(vhci_hcd->port_status[rhport]);
((__le16 *) buf)[1] =
- cpu_to_le16(dum->port_status[rhport] >> 16);
+ cpu_to_le16(vhci_hcd->port_status[rhport] >> 16);
usbip_dbg_vhci_rh(" GetPortStatus bye %x %x\n", ((u16 *)buf)[0],
((u16 *)buf)[1]);
@@ -386,36 +489,119 @@ static int vhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,
break;
case SetPortFeature:
switch (wValue) {
+ case USB_PORT_FEAT_LINK_STATE:
+ usbip_dbg_vhci_rh(
+ " SetPortFeature: USB_PORT_FEAT_LINK_STATE\n");
+ if (hcd->speed != HCD_USB3) {
+ pr_err("USB_PORT_FEAT_LINK_STATE req not "
+ "supported for USB 2.0 roothub\n");
+ goto error;
+ }
+ /*
+ * Since this is dummy we don't have an actual link so
+ * there is nothing to do for the SET_LINK_STATE cmd
+ */
+ break;
+ case USB_PORT_FEAT_U1_TIMEOUT:
+ usbip_dbg_vhci_rh(
+ " SetPortFeature: USB_PORT_FEAT_U1_TIMEOUT\n");
+ case USB_PORT_FEAT_U2_TIMEOUT:
+ usbip_dbg_vhci_rh(
+ " SetPortFeature: USB_PORT_FEAT_U2_TIMEOUT\n");
+ /* TODO: add suspend/resume support! */
+ if (hcd->speed != HCD_USB3) {
+ pr_err("USB_PORT_FEAT_U1/2_TIMEOUT req not "
+ "supported for USB 2.0 roothub\n");
+ goto error;
+ }
+ break;
case USB_PORT_FEAT_SUSPEND:
usbip_dbg_vhci_rh(
" SetPortFeature: USB_PORT_FEAT_SUSPEND\n");
+ /* Applicable only for USB2.0 hub */
+ if (hcd->speed == HCD_USB3) {
+ pr_err("USB_PORT_FEAT_SUSPEND req not "
+ "supported for USB 3.0 roothub\n");
+ goto error;
+ }
+
+ vhci_hcd->port_status[rhport] |= USB_PORT_STAT_SUSPEND;
break;
+ case USB_PORT_FEAT_POWER:
+ usbip_dbg_vhci_rh(
+ " SetPortFeature: USB_PORT_FEAT_POWER\n");
+ if (hcd->speed == HCD_USB3)
+ vhci_hcd->port_status[rhport] |= USB_SS_PORT_STAT_POWER;
+ else
+ vhci_hcd->port_status[rhport] |= USB_PORT_STAT_POWER;
+ break;
+ case USB_PORT_FEAT_BH_PORT_RESET:
+ usbip_dbg_vhci_rh(
+ " SetPortFeature: USB_PORT_FEAT_BH_PORT_RESET\n");
+ /* Applicable only for USB3.0 hub */
+ if (hcd->speed != HCD_USB3) {
+ pr_err("USB_PORT_FEAT_BH_PORT_RESET req not "
+ "supported for USB 2.0 roothub\n");
+ goto error;
+ }
+ /* FALLS THROUGH */
case USB_PORT_FEAT_RESET:
usbip_dbg_vhci_rh(
" SetPortFeature: USB_PORT_FEAT_RESET\n");
- /* if it's already running, disconnect first */
- if (dum->port_status[rhport] & USB_PORT_STAT_ENABLE) {
- dum->port_status[rhport] &=
- ~(USB_PORT_STAT_ENABLE |
- USB_PORT_STAT_LOW_SPEED |
- USB_PORT_STAT_HIGH_SPEED);
- /* FIXME test that code path! */
+ /* if it's already enabled, disable */
+ if (hcd->speed == HCD_USB3) {
+ vhci_hcd->port_status[rhport] = 0;
+ vhci_hcd->port_status[rhport] =
+ (USB_SS_PORT_STAT_POWER |
+ USB_PORT_STAT_CONNECTION |
+ USB_PORT_STAT_RESET);
+ } else if (vhci_hcd->port_status[rhport] & USB_PORT_STAT_ENABLE) {
+ vhci_hcd->port_status[rhport] &= ~(USB_PORT_STAT_ENABLE
+ | USB_PORT_STAT_LOW_SPEED
+ | USB_PORT_STAT_HIGH_SPEED);
}
+
/* 50msec reset signaling */
- dum->re_timeout = jiffies + msecs_to_jiffies(50);
+ vhci_hcd->re_timeout = jiffies + msecs_to_jiffies(50);
- /* FALLTHROUGH */
+ /* FALLS THROUGH */
default:
usbip_dbg_vhci_rh(" SetPortFeature: default %d\n",
wValue);
- dum->port_status[rhport] |= (1 << wValue);
- break;
+ if (hcd->speed == HCD_USB3) {
+ if ((vhci_hcd->port_status[rhport] &
+ USB_SS_PORT_STAT_POWER) != 0) {
+ vhci_hcd->port_status[rhport] |= (1 << wValue);
+ }
+ } else
+ if ((vhci_hcd->port_status[rhport] &
+ USB_PORT_STAT_POWER) != 0) {
+ vhci_hcd->port_status[rhport] |= (1 << wValue);
+ }
+ }
+ break;
+ case GetPortErrorCount:
+ usbip_dbg_vhci_rh(" GetPortErrorCount\n");
+ if (hcd->speed != HCD_USB3) {
+ pr_err("GetPortErrorCount req not "
+ "supported for USB 2.0 roothub\n");
+ goto error;
+ }
+ /* We'll always return 0 since this is a dummy hub */
+ *(__le32 *) buf = cpu_to_le32(0);
+ break;
+ case SetHubDepth:
+ usbip_dbg_vhci_rh(" SetHubDepth\n");
+ if (hcd->speed != HCD_USB3) {
+ pr_err("SetHubDepth req not supported for "
+ "USB 2.0 roothub\n");
+ goto error;
}
break;
-
default:
- pr_err("default: no such request\n");
-
+ pr_err("default hub control req: %04x v%04x i%04x l%d\n",
+ typeReq, wValue, wIndex, wLength);
+error:
/* "protocol stall" on error */
retval = -EPIPE;
}
@@ -425,12 +611,16 @@ static int vhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,
/* Only dump valid port status */
if (rhport >= 0) {
dump_port_status_diff(prev_port_status[rhport],
- dum->port_status[rhport]);
+ vhci_hcd->port_status[rhport],
+ hcd->speed == HCD_USB3);
}
}
usbip_dbg_vhci_rh(" bye\n");
- spin_unlock_irqrestore(&dum->lock, flags);
+ spin_unlock_irqrestore(&vhci->lock, flags);
+
+ if ((vhci_hcd->port_status[rhport] & PORT_C_MASK) != 0)
+ usb_hcd_poll_rh_status(hcd);
return retval;
}
@@ -438,14 +628,14 @@ static int vhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,
static void vhci_tx_urb(struct urb *urb, struct vhci_device *vdev)
{
struct vhci_priv *priv;
- struct vhci_hcd *vhci;
+ struct vhci_hcd *vhci_hcd;
unsigned long flags;
if (!vdev) {
pr_err("could not get virtual device");
return;
}
- vhci = vdev_to_vhci(vdev);
+ vhci_hcd = vdev_to_vhci_hcd(vdev);
priv = kzalloc(sizeof(struct vhci_priv), GFP_ATOMIC);
if (!priv) {
@@ -455,7 +645,7 @@ static void vhci_tx_urb(struct urb *urb, struct vhci_device *vdev)
spin_lock_irqsave(&vdev->priv_lock, flags);
- priv->seqnum = atomic_inc_return(&vhci->seqnum);
+ priv->seqnum = atomic_inc_return(&vhci_hcd->seqnum);
if (priv->seqnum == 0xffff)
dev_info(&urb->dev->dev, "seqnum max\n");
@@ -470,10 +660,10 @@ static void vhci_tx_urb(struct urb *urb, struct vhci_device *vdev)
spin_unlock_irqrestore(&vdev->priv_lock, flags);
}
-static int vhci_urb_enqueue(struct usb_hcd *hcd, struct urb *urb,
- gfp_t mem_flags)
+static int vhci_urb_enqueue(struct usb_hcd *hcd, struct urb *urb, gfp_t mem_flags)
{
- struct vhci_hcd *vhci = hcd_to_vhci(hcd);
+ struct vhci_hcd *vhci_hcd = hcd_to_vhci_hcd(hcd);
+ struct vhci *vhci = vhci_hcd->vhci;
struct device *dev = &urb->dev->dev;
u8 portnum = urb->dev->portnum;
int ret = 0;
@@ -487,7 +677,7 @@ static int vhci_urb_enqueue(struct usb_hcd *hcd, struct urb *urb,
pr_err("invalid port number %d\n", portnum);
return -ENODEV;
}
- vdev = &vhci->vdev[portnum-1];
+ vdev = &vhci_hcd->vdev[portnum-1];
/* patch to usb_sg_init() is in 2.5.60 */
BUG_ON(!urb->transfer_buffer && urb->transfer_buffer_length);
@@ -640,7 +830,8 @@ no_need_unlink:
*/
static int vhci_urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int status)
{
- struct vhci_hcd *vhci = hcd_to_vhci(hcd);
+ struct vhci_hcd *vhci_hcd = hcd_to_vhci_hcd(hcd);
+ struct vhci *vhci = vhci_hcd->vhci;
struct vhci_priv *priv;
struct vhci_device *vdev;
unsigned long flags;
@@ -691,7 +882,7 @@ static int vhci_urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int status)
usb_hcd_unlink_urb_from_ep(hcd, urb);
spin_unlock_irqrestore(&vhci->lock, flags);
- usb_hcd_giveback_urb(vhci_to_hcd(vhci), urb, urb->status);
+ usb_hcd_giveback_urb(hcd, urb, urb->status);
spin_lock_irqsave(&vhci->lock, flags);
} else {
@@ -709,7 +900,7 @@ static int vhci_urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int status)
return -ENOMEM;
}
- unlink->seqnum = atomic_inc_return(&vhci->seqnum);
+ unlink->seqnum = atomic_inc_return(&vhci_hcd->seqnum);
if (unlink->seqnum == 0xffff)
pr_info("seqnum max\n");
@@ -733,8 +924,9 @@ static int vhci_urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int status)
static void vhci_device_unlink_cleanup(struct vhci_device *vdev)
{
- struct vhci_hcd *vhci = vdev_to_vhci(vdev);
- struct usb_hcd *hcd = vhci_to_hcd(vhci);
+ struct vhci_hcd *vhci_hcd = vdev_to_vhci_hcd(vdev);
+ struct usb_hcd *hcd = vhci_hcd_to_hcd(vhci_hcd);
+ struct vhci *vhci = vhci_hcd->vhci;
struct vhci_unlink *unlink, *tmp;
unsigned long flags;
@@ -846,7 +1038,6 @@ static void vhci_shutdown_connection(struct usbip_device *ud)
pr_info("disconnect device\n");
}
-
static void vhci_device_reset(struct usbip_device *ud)
{
struct vhci_device *vdev = container_of(ud, struct vhci_device, ud);
@@ -918,29 +1109,58 @@ static int hcd_name_to_id(const char *name)
return val;
}
+static int vhci_setup(struct usb_hcd *hcd)
+{
+ struct vhci *vhci = *((void **)dev_get_platdata(hcd->self.controller));
+ hcd->self.sg_tablesize = ~0;
+ if (usb_hcd_is_primary_hcd(hcd)) {
+ vhci->vhci_hcd_hs = hcd_to_vhci_hcd(hcd);
+ vhci->vhci_hcd_hs->vhci = vhci;
+ /*
+ * Mark the first roothub as being USB 2.0.
+ * The USB 3.0 roothub will be registered later by
+ * vhci_hcd_probe()
+ */
+ hcd->speed = HCD_USB2;
+ hcd->self.root_hub->speed = USB_SPEED_HIGH;
+ } else {
+ vhci->vhci_hcd_ss = hcd_to_vhci_hcd(hcd);
+ vhci->vhci_hcd_ss->vhci = vhci;
+ hcd->speed = HCD_USB3;
+ hcd->self.root_hub->speed = USB_SPEED_SUPER;
+ }
+ return 0;
+}
+
static int vhci_start(struct usb_hcd *hcd)
{
- struct vhci_hcd *vhci = hcd_to_vhci(hcd);
+ struct vhci_hcd *vhci_hcd = hcd_to_vhci_hcd(hcd);
int id, rhport;
- int err = 0;
+ int err;
usbip_dbg_vhci_hc("enter vhci_start\n");
+ if (usb_hcd_is_primary_hcd(hcd))
+ spin_lock_init(&vhci_hcd->vhci->lock);
+
/* initialize private data of usb_hcd */
for (rhport = 0; rhport < VHCI_HC_PORTS; rhport++) {
- struct vhci_device *vdev = &vhci->vdev[rhport];
+ struct vhci_device *vdev = &vhci_hcd->vdev[rhport];
vhci_device_init(vdev);
vdev->rhport = rhport;
}
- atomic_set(&vhci->seqnum, 0);
- spin_lock_init(&vhci->lock);
+ atomic_set(&vhci_hcd->seqnum, 0);
hcd->power_budget = 0; /* no limit */
hcd->uses_new_polling = 1;
+#ifdef CONFIG_USB_OTG
+ hcd->self.otg_port = 1;
+#endif
+
id = hcd_name_to_id(hcd_name(hcd));
if (id < 0) {
pr_err("invalid vhci name %s\n", hcd_name(hcd));
@@ -948,7 +1168,7 @@ static int vhci_start(struct usb_hcd *hcd)
}
/* vhci_hcd is now ready to be controlled through sysfs */
- if (id == 0) {
+ if (id == 0 && usb_hcd_is_primary_hcd(hcd)) {
err = vhci_init_attr_group();
if (err) {
pr_err("init attr group\n");
@@ -968,21 +1188,21 @@ static int vhci_start(struct usb_hcd *hcd)
static void vhci_stop(struct usb_hcd *hcd)
{
- struct vhci_hcd *vhci = hcd_to_vhci(hcd);
+ struct vhci_hcd *vhci_hcd = hcd_to_vhci_hcd(hcd);
int id, rhport;
usbip_dbg_vhci_hc("stop VHCI controller\n");
/* 1. remove the userland interface of vhci_hcd */
id = hcd_name_to_id(hcd_name(hcd));
- if (id == 0) {
+ if (id == 0 && usb_hcd_is_primary_hcd(hcd)) {
sysfs_remove_group(&hcd_dev(hcd)->kobj, &vhci_attr_group);
vhci_finish_attr_group();
}
/* 2. shutdown all the ports of vhci_hcd */
for (rhport = 0; rhport < VHCI_HC_PORTS; rhport++) {
- struct vhci_device *vdev = &vhci->vdev[rhport];
+ struct vhci_device *vdev = &vhci_hcd->vdev[rhport];
usbip_event_add(&vdev->ud, VDEV_EVENT_REMOVED);
usbip_stop_eh(&vdev->ud);
@@ -1000,7 +1220,7 @@ static int vhci_get_frame_number(struct usb_hcd *hcd)
/* FIXME: suspend/resume */
static int vhci_bus_suspend(struct usb_hcd *hcd)
{
- struct vhci_hcd *vhci = hcd_to_vhci(hcd);
+ struct vhci *vhci = *((void **)dev_get_platdata(hcd->self.controller));
unsigned long flags;
dev_dbg(&hcd->self.root_hub->dev, "%s\n", __func__);
@@ -1014,7 +1234,7 @@ static int vhci_bus_suspend(struct usb_hcd *hcd)
static int vhci_bus_resume(struct usb_hcd *hcd)
{
- struct vhci_hcd *vhci = hcd_to_vhci(hcd);
+ struct vhci *vhci = *((void **)dev_get_platdata(hcd->self.controller));
int rc = 0;
unsigned long flags;
@@ -1036,13 +1256,32 @@ static int vhci_bus_resume(struct usb_hcd *hcd)
#define vhci_bus_resume NULL
#endif
+/* Change a group of bulk endpoints to support multiple stream IDs */
+static int vhci_alloc_streams(struct usb_hcd *hcd, struct usb_device *udev,
+ struct usb_host_endpoint **eps, unsigned int num_eps,
+ unsigned int num_streams, gfp_t mem_flags)
+{
+ dev_dbg(&hcd->self.root_hub->dev, "vhci_alloc_streams not implemented\n");
+ return 0;
+}
+
+/* Reverts a group of bulk endpoints back to not using stream IDs. */
+static int vhci_free_streams(struct usb_hcd *hcd, struct usb_device *udev,
+ struct usb_host_endpoint **eps, unsigned int num_eps,
+ gfp_t mem_flags)
+{
+ dev_dbg(&hcd->self.root_hub->dev, "vhci_free_streams not implemented\n");
+ return 0;
+}
+
static struct hc_driver vhci_hc_driver = {
.description = driver_name,
.product_desc = driver_desc,
.hcd_priv_size = sizeof(struct vhci_hcd),
- .flags = HCD_USB2,
+ .flags = HCD_USB3 | HCD_SHARED,
+ .reset = vhci_setup,
.start = vhci_start,
.stop = vhci_stop,
@@ -1055,11 +1294,16 @@ static struct hc_driver vhci_hc_driver = {
.hub_control = vhci_hub_control,
.bus_suspend = vhci_bus_suspend,
.bus_resume = vhci_bus_resume,
+
+ .alloc_streams = vhci_alloc_streams,
+ .free_streams = vhci_free_streams,
};
static int vhci_hcd_probe(struct platform_device *pdev)
{
- struct usb_hcd *hcd;
+ struct vhci *vhci = *((void **)dev_get_platdata(&pdev->dev));
+ struct usb_hcd *hcd_hs;
+ struct usb_hcd *hcd_ss;
int ret;
usbip_dbg_vhci_hc("name %s id %d\n", pdev->name, pdev->id);
@@ -1068,43 +1312,68 @@ static int vhci_hcd_probe(struct platform_device *pdev)
* Allocate and initialize hcd.
* Our private data is also allocated automatically.
*/
- hcd = usb_create_hcd(&vhci_hc_driver, &pdev->dev, dev_name(&pdev->dev));
- if (!hcd) {
- pr_err("create hcd failed\n");
+ hcd_hs = usb_create_hcd(&vhci_hc_driver, &pdev->dev, dev_name(&pdev->dev));
+ if (!hcd_hs) {
+ pr_err("create primary hcd failed\n");
return -ENOMEM;
}
- hcd->has_tt = 1;
+ hcd_hs->has_tt = 1;
/*
* Finish generic HCD structure initialization and register.
* Call the driver's reset() and start() routines.
*/
- ret = usb_add_hcd(hcd, 0, 0);
+ ret = usb_add_hcd(hcd_hs, 0, 0);
if (ret != 0) {
- pr_err("usb_add_hcd failed %d\n", ret);
- usb_put_hcd(hcd);
- return ret;
+ pr_err("usb_add_hcd hs failed %d\n", ret);
+ goto put_usb2_hcd;
+ }
+
+ hcd_ss = usb_create_shared_hcd(&vhci_hc_driver, &pdev->dev,
+ dev_name(&pdev->dev), hcd_hs);
+ if (!hcd_ss) {
+ ret = -ENOMEM;
+ pr_err("create shared hcd failed\n");
+ goto remove_usb2_hcd;
+ }
+
+ ret = usb_add_hcd(hcd_ss, 0, 0);
+ if (ret) {
+ pr_err("usb_add_hcd ss failed %d\n", ret);
+ goto put_usb3_hcd;
}
usbip_dbg_vhci_hc("bye\n");
return 0;
+
+put_usb3_hcd:
+ usb_put_hcd(hcd_ss);
+remove_usb2_hcd:
+ usb_remove_hcd(hcd_hs);
+put_usb2_hcd:
+ usb_put_hcd(hcd_hs);
+ vhci->vhci_hcd_hs = NULL;
+ vhci->vhci_hcd_ss = NULL;
+ return ret;
}
static int vhci_hcd_remove(struct platform_device *pdev)
{
- struct usb_hcd *hcd;
-
- hcd = platform_get_drvdata(pdev);
- if (!hcd)
- return 0;
+ struct vhci *vhci = *((void **)dev_get_platdata(&pdev->dev));
/*
* Disconnects the root hub,
* then reverses the effects of usb_add_hcd(),
* invoking the HCD's stop() methods.
*/
- usb_remove_hcd(hcd);
- usb_put_hcd(hcd);
+ usb_remove_hcd(vhci_hcd_to_hcd(vhci->vhci_hcd_ss));
+ usb_put_hcd(vhci_hcd_to_hcd(vhci->vhci_hcd_ss));
+
+ usb_remove_hcd(vhci_hcd_to_hcd(vhci->vhci_hcd_hs));
+ usb_put_hcd(vhci_hcd_to_hcd(vhci->vhci_hcd_hs));
+
+ vhci->vhci_hcd_hs = NULL;
+ vhci->vhci_hcd_ss = NULL;
return 0;
}
@@ -1115,23 +1384,32 @@ static int vhci_hcd_remove(struct platform_device *pdev)
static int vhci_hcd_suspend(struct platform_device *pdev, pm_message_t state)
{
struct usb_hcd *hcd;
- struct vhci_hcd *vhci;
+ struct vhci *vhci;
int rhport;
int connected = 0;
int ret = 0;
unsigned long flags;
+ dev_dbg(&pdev->dev, "%s\n", __func__);
+
hcd = platform_get_drvdata(pdev);
if (!hcd)
return 0;
- vhci = hcd_to_vhci(hcd);
+
+ vhci = *((void **)dev_get_platdata(hcd->self.controller));
spin_lock_irqsave(&vhci->lock, flags);
- for (rhport = 0; rhport < VHCI_HC_PORTS; rhport++)
- if (vhci->port_status[rhport] & USB_PORT_STAT_CONNECTION)
+ for (rhport = 0; rhport < VHCI_HC_PORTS; rhport++) {
+ if (vhci->vhci_hcd_hs->port_status[rhport] &
+ USB_PORT_STAT_CONNECTION)
connected += 1;
+ if (vhci->vhci_hcd_ss->port_status[rhport] &
+ USB_PORT_STAT_CONNECTION)
+ connected += 1;
+ }
+
spin_unlock_irqrestore(&vhci->lock, flags);
if (connected > 0) {
@@ -1179,34 +1457,16 @@ static struct platform_driver vhci_driver = {
},
};
-static int add_platform_device(int id)
-{
- struct platform_device *pdev;
- int dev_nr;
-
- if (id == 0)
- dev_nr = -1;
- else
- dev_nr = id;
-
- pdev = platform_device_register_simple(driver_name, dev_nr, NULL, 0);
- if (IS_ERR(pdev))
- return PTR_ERR(pdev);
-
- *(vhci_pdevs + id) = pdev;
- return 0;
-}
-
static void del_platform_devices(void)
{
struct platform_device *pdev;
int i;
for (i = 0; i < vhci_num_controllers; i++) {
- pdev = *(vhci_pdevs + i);
+ pdev = vhcis[i].pdev;
if (pdev != NULL)
platform_device_unregister(pdev);
- *(vhci_pdevs + i) = NULL;
+ vhcis[i].pdev = NULL;
}
sysfs_remove_link(&platform_bus.kobj, driver_name);
}
@@ -1221,28 +1481,51 @@ static int __init vhci_hcd_init(void)
if (vhci_num_controllers < 1)
vhci_num_controllers = 1;
- vhci_pdevs = kcalloc(vhci_num_controllers, sizeof(void *), GFP_KERNEL);
- if (vhci_pdevs == NULL)
+ vhcis = kcalloc(vhci_num_controllers, sizeof(struct vhci), GFP_KERNEL);
+ if (vhcis == NULL)
return -ENOMEM;
+ for (i = 0; i < vhci_num_controllers; i++) {
+ vhcis[i].pdev = platform_device_alloc(driver_name, i);
+ if (!vhcis[i].pdev) {
+ i--;
+ while (i >= 0)
+ platform_device_put(vhcis[i--].pdev);
+ ret = -ENOMEM;
+ goto err_device_alloc;
+ }
+ }
+ for (i = 0; i < vhci_num_controllers; i++) {
+ void *vhci = &vhcis[i];
+ ret = platform_device_add_data(vhcis[i].pdev, &vhci, sizeof(void *));
+ if (ret)
+ goto err_driver_register;
+ }
+
ret = platform_driver_register(&vhci_driver);
if (ret)
goto err_driver_register;
for (i = 0; i < vhci_num_controllers; i++) {
- ret = add_platform_device(i);
- if (ret)
- goto err_platform_device_register;
+ ret = platform_device_add(vhcis[i].pdev);
+ if (ret < 0) {
+ i--;
+ while (i >= 0)
+ platform_device_del(vhcis[i--].pdev);
+ goto err_add_hcd;
+ }
}
pr_info(DRIVER_DESC " v" USBIP_VERSION "\n");
return ret;
-err_platform_device_register:
- del_platform_devices();
+err_add_hcd:
platform_driver_unregister(&vhci_driver);
err_driver_register:
- kfree(vhci_pdevs);
+ for (i = 0; i < vhci_num_controllers; i++)
+ platform_device_put(vhcis[i].pdev);
+err_device_alloc:
+ kfree(vhcis);
return ret;
}
@@ -1250,7 +1533,7 @@ static void __exit vhci_hcd_exit(void)
{
del_platform_devices();
platform_driver_unregister(&vhci_driver);
- kfree(vhci_pdevs);
+ kfree(vhcis);
}
module_init(vhci_hcd_init);
diff --git a/drivers/usb/usbip/vhci_rx.c b/drivers/usb/usbip/vhci_rx.c
index fc2d319e2360..ef2f2d5ca6b2 100644
--- a/drivers/usb/usbip/vhci_rx.c
+++ b/drivers/usb/usbip/vhci_rx.c
@@ -70,7 +70,8 @@ struct urb *pickup_urb_and_free_priv(struct vhci_device *vdev, __u32 seqnum)
static void vhci_recv_ret_submit(struct vhci_device *vdev,
struct usbip_header *pdu)
{
- struct vhci_hcd *vhci = vdev_to_vhci(vdev);
+ struct vhci_hcd *vhci_hcd = vdev_to_vhci_hcd(vdev);
+ struct vhci *vhci = vhci_hcd->vhci;
struct usbip_device *ud = &vdev->ud;
struct urb *urb;
unsigned long flags;
@@ -82,7 +83,7 @@ static void vhci_recv_ret_submit(struct vhci_device *vdev,
if (!urb) {
pr_err("cannot find a urb of seqnum %u\n", pdu->base.seqnum);
pr_info("max seqnum %d\n",
- atomic_read(&vhci->seqnum));
+ atomic_read(&vhci_hcd->seqnum));
usbip_event_add(ud, VDEV_EVENT_ERROR_TCP);
return;
}
@@ -107,10 +108,10 @@ static void vhci_recv_ret_submit(struct vhci_device *vdev,
usbip_dbg_vhci_rx("now giveback urb %p\n", urb);
spin_lock_irqsave(&vhci->lock, flags);
- usb_hcd_unlink_urb_from_ep(vhci_to_hcd(vhci), urb);
+ usb_hcd_unlink_urb_from_ep(vhci_hcd_to_hcd(vhci_hcd), urb);
spin_unlock_irqrestore(&vhci->lock, flags);
- usb_hcd_giveback_urb(vhci_to_hcd(vhci), urb, urb->status);
+ usb_hcd_giveback_urb(vhci_hcd_to_hcd(vhci_hcd), urb, urb->status);
usbip_dbg_vhci_rx("Leave\n");
}
@@ -143,7 +144,8 @@ static struct vhci_unlink *dequeue_pending_unlink(struct vhci_device *vdev,
static void vhci_recv_ret_unlink(struct vhci_device *vdev,
struct usbip_header *pdu)
{
- struct vhci_hcd *vhci = vdev_to_vhci(vdev);
+ struct vhci_hcd *vhci_hcd = vdev_to_vhci_hcd(vdev);
+ struct vhci *vhci = vhci_hcd->vhci;
struct vhci_unlink *unlink;
struct urb *urb;
unsigned long flags;
@@ -177,10 +179,10 @@ static void vhci_recv_ret_unlink(struct vhci_device *vdev,
pr_info("urb->status %d\n", urb->status);
spin_lock_irqsave(&vhci->lock, flags);
- usb_hcd_unlink_urb_from_ep(vhci_to_hcd(vhci), urb);
+ usb_hcd_unlink_urb_from_ep(vhci_hcd_to_hcd(vhci_hcd), urb);
spin_unlock_irqrestore(&vhci->lock, flags);
- usb_hcd_giveback_urb(vhci_to_hcd(vhci), urb, urb->status);
+ usb_hcd_giveback_urb(vhci_hcd_to_hcd(vhci_hcd), urb, urb->status);
}
kfree(unlink);
diff --git a/drivers/usb/usbip/vhci_sysfs.c b/drivers/usb/usbip/vhci_sysfs.c
index b96e5b189269..5778b640ba9c 100644
--- a/drivers/usb/usbip/vhci_sysfs.c
+++ b/drivers/usb/usbip/vhci_sysfs.c
@@ -29,13 +29,51 @@
/* TODO: refine locking ?*/
+/*
+ * output example:
+ * hub port sta spd dev socket local_busid
+ * hs 0000 004 000 00000000 c5a7bb80 1-2.3
+ * ................................................
+ * ss 0008 004 000 00000000 d8cee980 2-3.4
+ * ................................................
+ *
+ * IP address can be retrieved from a socket pointer address by looking
+ * up /proc/net/{tcp,tcp6}. Also, a userland program may remember a
+ * port number and its peer IP address.
+ */
+static void port_show_vhci(char **out, int hub, int port, struct vhci_device *vdev)
+{
+ if (hub == HUB_SPEED_HIGH)
+ *out += sprintf(*out, "hs %04u %03u ",
+ port, vdev->ud.status);
+ else /* hub == HUB_SPEED_SUPER */
+ *out += sprintf(*out, "ss %04u %03u ",
+ port, vdev->ud.status);
+
+ if (vdev->ud.status == VDEV_ST_USED) {
+ *out += sprintf(*out, "%03u %08x ",
+ vdev->speed, vdev->devid);
+ *out += sprintf(*out, "%16p %s",
+ vdev->ud.tcp_socket,
+ dev_name(&vdev->udev->dev));
+
+ } else {
+ *out += sprintf(*out, "000 00000000 ");
+ *out += sprintf(*out, "0000000000000000 0-0");
+ }
+
+ *out += sprintf(*out, "\n");
+}
+
/* Sysfs entry to show port status */
static ssize_t status_show_vhci(int pdev_nr, char *out)
{
- struct platform_device *pdev = *(vhci_pdevs + pdev_nr);
- struct vhci_hcd *vhci;
+ struct platform_device *pdev = vhcis[pdev_nr].pdev;
+ struct vhci *vhci;
+ struct usb_hcd *hcd;
+ struct vhci_hcd *vhci_hcd;
char *s = out;
- int i = 0;
+ int i;
unsigned long flags;
if (!pdev || !out) {
@@ -43,41 +81,27 @@ static ssize_t status_show_vhci(int pdev_nr, char *out)
return 0;
}
- vhci = hcd_to_vhci(platform_get_drvdata(pdev));
+ hcd = platform_get_drvdata(pdev);
+ vhci_hcd = hcd_to_vhci_hcd(hcd);
+ vhci = vhci_hcd->vhci;
spin_lock_irqsave(&vhci->lock, flags);
- /*
- * output example:
- * port sta spd dev socket local_busid
- * 0000 004 000 00000000 c5a7bb80 1-2.3
- * 0001 004 000 00000000 d8cee980 2-3.4
- *
- * IP address can be retrieved from a socket pointer address by looking
- * up /proc/net/{tcp,tcp6}. Also, a userland program may remember a
- * port number and its peer IP address.
- */
for (i = 0; i < VHCI_HC_PORTS; i++) {
- struct vhci_device *vdev = &vhci->vdev[i];
+ struct vhci_device *vdev = &vhci->vhci_hcd_hs->vdev[i];
spin_lock(&vdev->ud.lock);
- out += sprintf(out, "%04u %03u ",
- (pdev_nr * VHCI_HC_PORTS) + i,
- vdev->ud.status);
-
- if (vdev->ud.status == VDEV_ST_USED) {
- out += sprintf(out, "%03u %08x ",
- vdev->speed, vdev->devid);
- out += sprintf(out, "%16p %s",
- vdev->ud.tcp_socket,
- dev_name(&vdev->udev->dev));
-
- } else {
- out += sprintf(out, "000 00000000 ");
- out += sprintf(out, "0000000000000000 0-0");
- }
+ port_show_vhci(&out, HUB_SPEED_HIGH,
+ pdev_nr * VHCI_PORTS + i, vdev);
+ spin_unlock(&vdev->ud.lock);
+ }
- out += sprintf(out, "\n");
+ for (i = 0; i < VHCI_HC_PORTS; i++) {
+ struct vhci_device *vdev = &vhci->vhci_hcd_ss->vdev[i];
+
+ spin_lock(&vdev->ud.lock);
+ port_show_vhci(&out, HUB_SPEED_SUPER,
+ pdev_nr * VHCI_PORTS + VHCI_HC_PORTS + i, vdev);
spin_unlock(&vdev->ud.lock);
}
@@ -92,8 +116,16 @@ static ssize_t status_show_not_ready(int pdev_nr, char *out)
int i = 0;
for (i = 0; i < VHCI_HC_PORTS; i++) {
- out += sprintf(out, "%04u %03u ",
- (pdev_nr * VHCI_HC_PORTS) + i,
+ out += sprintf(out, "hs %04u %03u ",
+ (pdev_nr * VHCI_PORTS) + i,
+ VDEV_ST_NOTASSIGNED);
+ out += sprintf(out, "000 00000000 0000000000000000 0-0");
+ out += sprintf(out, "\n");
+ }
+
+ for (i = 0; i < VHCI_HC_PORTS; i++) {
+ out += sprintf(out, "ss %04u %03u ",
+ (pdev_nr * VHCI_PORTS) + VHCI_HC_PORTS + i,
VDEV_ST_NOTASSIGNED);
out += sprintf(out, "000 00000000 0000000000000000 0-0");
out += sprintf(out, "\n");
@@ -125,7 +157,7 @@ static ssize_t status_show(struct device *dev,
int pdev_nr;
out += sprintf(out,
- "port sta spd dev socket local_busid\n");
+ "hub port sta spd dev socket local_busid\n");
pdev_nr = status_name_to_id(attr->attr.name);
if (pdev_nr < 0)
@@ -141,15 +173,19 @@ static ssize_t nports_show(struct device *dev, struct device_attribute *attr,
{
char *s = out;
- out += sprintf(out, "%d\n", VHCI_HC_PORTS * vhci_num_controllers);
+ /*
+ * Half the ports are for SPEED_HIGH and half for SPEED_SUPER, thus the * 2.
+ */
+ out += sprintf(out, "%d\n", VHCI_PORTS * vhci_num_controllers);
return out - s;
}
static DEVICE_ATTR_RO(nports);
/* Sysfs entry to shutdown a virtual connection */
-static int vhci_port_disconnect(struct vhci_hcd *vhci, __u32 rhport)
+static int vhci_port_disconnect(struct vhci_hcd *vhci_hcd, __u32 rhport)
{
- struct vhci_device *vdev = &vhci->vdev[rhport];
+ struct vhci_device *vdev = &vhci_hcd->vdev[rhport];
+ struct vhci *vhci = vhci_hcd->vhci;
unsigned long flags;
usbip_dbg_vhci_sysfs("enter\n");
@@ -195,6 +231,7 @@ static ssize_t store_detach(struct device *dev, struct device_attribute *attr,
{
__u32 port = 0, pdev_nr = 0, rhport = 0;
struct usb_hcd *hcd;
+ struct vhci_hcd *vhci_hcd;
int ret;
if (kstrtoint(buf, 10, &port) < 0)
@@ -206,13 +243,20 @@ static ssize_t store_detach(struct device *dev, struct device_attribute *attr,
if (!valid_port(pdev_nr, rhport))
return -EINVAL;
- hcd = platform_get_drvdata(*(vhci_pdevs + pdev_nr));
+ hcd = platform_get_drvdata(vhcis[pdev_nr].pdev);
if (hcd == NULL) {
dev_err(dev, "port is not ready %u\n", port);
return -EAGAIN;
}
- ret = vhci_port_disconnect(hcd_to_vhci(hcd), rhport);
+ usbip_dbg_vhci_sysfs("rhport %d\n", rhport);
+
+ if ((port / VHCI_HC_PORTS) % 2)
+ vhci_hcd = hcd_to_vhci_hcd(hcd)->vhci->vhci_hcd_ss;
+ else
+ vhci_hcd = hcd_to_vhci_hcd(hcd)->vhci->vhci_hcd_hs;
+
+ ret = vhci_port_disconnect(vhci_hcd, rhport);
if (ret < 0)
return -EINVAL;
@@ -233,6 +277,7 @@ static int valid_args(__u32 pdev_nr, __u32 rhport, enum usb_device_speed speed)
case USB_SPEED_FULL:
case USB_SPEED_HIGH:
case USB_SPEED_WIRELESS:
+ case USB_SPEED_SUPER:
break;
default:
pr_err("Failed attach request for unsupported USB speed: %s\n",
@@ -262,8 +307,9 @@ static ssize_t store_attach(struct device *dev, struct device_attribute *attr,
int sockfd = 0;
__u32 port = 0, pdev_nr = 0, rhport = 0, devid = 0, speed = 0;
struct usb_hcd *hcd;
- struct vhci_hcd *vhci;
+ struct vhci_hcd *vhci_hcd;
struct vhci_device *vdev;
+ struct vhci *vhci;
int err;
unsigned long flags;
@@ -287,13 +333,19 @@ static ssize_t store_attach(struct device *dev, struct device_attribute *attr,
if (!valid_args(pdev_nr, rhport, speed))
return -EINVAL;
- hcd = platform_get_drvdata(*(vhci_pdevs + pdev_nr));
+ hcd = platform_get_drvdata(vhcis[pdev_nr].pdev);
if (hcd == NULL) {
dev_err(dev, "port %d is not ready\n", port);
return -EAGAIN;
}
- vhci = hcd_to_vhci(hcd);
- vdev = &vhci->vdev[rhport];
+
+ vhci_hcd = hcd_to_vhci_hcd(hcd);
+ vhci = vhci_hcd->vhci;
+
+ if (speed == USB_SPEED_SUPER)
+ vdev = &vhci->vhci_hcd_ss->vdev[rhport];
+ else
+ vdev = &vhci->vhci_hcd_hs->vdev[rhport];
/* Extract socket from fd. */
socket = sockfd_lookup(sockfd, &err);
diff --git a/drivers/uwb/i1480/dfu/phy.c b/drivers/uwb/i1480/dfu/phy.c
index 3b1a87de8e63..1ac8526bb689 100644
--- a/drivers/uwb/i1480/dfu/phy.c
+++ b/drivers/uwb/i1480/dfu/phy.c
@@ -126,6 +126,7 @@ int i1480_mpi_read(struct i1480 *i1480, u8 *data, u16 srcaddr, size_t size)
dev_err(i1480->dev, "MPI-READ: command execution failed: %d\n",
reply->bResultCode);
result = -EIO;
+ goto out;
}
for (cnt = 0; cnt < size; cnt++) {
if (reply->data[cnt].page != (srcaddr + cnt) >> 8)
diff --git a/drivers/vfio/virqfd.c b/drivers/vfio/virqfd.c
index 27c89cd5d70b..4797217e5e72 100644
--- a/drivers/vfio/virqfd.c
+++ b/drivers/vfio/virqfd.c
@@ -43,7 +43,7 @@ static void virqfd_deactivate(struct virqfd *virqfd)
queue_work(vfio_irqfd_cleanup_wq, &virqfd->shutdown);
}
-static int virqfd_wakeup(wait_queue_t *wait, unsigned mode, int sync, void *key)
+static int virqfd_wakeup(wait_queue_entry_t *wait, unsigned mode, int sync, void *key)
{
struct virqfd *virqfd = container_of(wait, struct virqfd, wait);
unsigned long flags = (unsigned long)key;
diff --git a/drivers/vhost/vhost.c b/drivers/vhost/vhost.c
index 042030e5a035..e4613a3c362d 100644
--- a/drivers/vhost/vhost.c
+++ b/drivers/vhost/vhost.c
@@ -165,7 +165,7 @@ static void vhost_poll_func(struct file *file, wait_queue_head_t *wqh,
add_wait_queue(wqh, &poll->wait);
}
-static int vhost_poll_wakeup(wait_queue_t *wait, unsigned mode, int sync,
+static int vhost_poll_wakeup(wait_queue_entry_t *wait, unsigned mode, int sync,
void *key)
{
struct vhost_poll *poll = container_of(wait, struct vhost_poll, wait);
diff --git a/drivers/vhost/vhost.h b/drivers/vhost/vhost.h
index f55671d53f28..f72095868b93 100644
--- a/drivers/vhost/vhost.h
+++ b/drivers/vhost/vhost.h
@@ -31,7 +31,7 @@ struct vhost_work {
struct vhost_poll {
poll_table table;
wait_queue_head_t *wqh;
- wait_queue_t wait;
+ wait_queue_entry_t wait;
struct vhost_work work;
unsigned long mask;
struct vhost_dev *dev;
diff --git a/drivers/video/fbdev/core/fbmon.c b/drivers/video/fbdev/core/fbmon.c
index 687ebb053438..41d7979d81c5 100644
--- a/drivers/video/fbdev/core/fbmon.c
+++ b/drivers/video/fbdev/core/fbmon.c
@@ -1048,7 +1048,7 @@ void fb_edid_add_monspecs(unsigned char *edid, struct fb_monspecs *specs)
for (i = 0; i < (128 - edid[2]) / DETAILED_TIMING_DESCRIPTION_SIZE;
i++, block += DETAILED_TIMING_DESCRIPTION_SIZE)
- if (PIXEL_CLOCK)
+ if (PIXEL_CLOCK != 0)
edt[num++] = block - edid;
/* Yikes, EDID data is totally useless */
diff --git a/drivers/video/fbdev/smscufx.c b/drivers/video/fbdev/smscufx.c
index ec2e7e353685..449fceaf79d5 100644
--- a/drivers/video/fbdev/smscufx.c
+++ b/drivers/video/fbdev/smscufx.c
@@ -1646,8 +1646,9 @@ static int ufx_usb_probe(struct usb_interface *interface,
dev_dbg(dev->gdev, "%s %s - serial #%s\n",
usbdev->manufacturer, usbdev->product, usbdev->serial);
dev_dbg(dev->gdev, "vid_%04x&pid_%04x&rev_%04x driver's ufx_data struct at %p\n",
- usbdev->descriptor.idVendor, usbdev->descriptor.idProduct,
- usbdev->descriptor.bcdDevice, dev);
+ le16_to_cpu(usbdev->descriptor.idVendor),
+ le16_to_cpu(usbdev->descriptor.idProduct),
+ le16_to_cpu(usbdev->descriptor.bcdDevice), dev);
dev_dbg(dev->gdev, "console enable=%d\n", console);
dev_dbg(dev->gdev, "fb_defio enable=%d\n", fb_defio);
diff --git a/drivers/video/fbdev/udlfb.c b/drivers/video/fbdev/udlfb.c
index 6a3c353de7c3..05ef657235df 100644
--- a/drivers/video/fbdev/udlfb.c
+++ b/drivers/video/fbdev/udlfb.c
@@ -1105,8 +1105,8 @@ static int dlfb_ops_blank(int blank_mode, struct fb_info *info)
char *bufptr;
struct urb *urb;
- pr_info("/dev/fb%d FB_BLANK mode %d --> %d\n",
- info->node, dev->blank_mode, blank_mode);
+ pr_debug("/dev/fb%d FB_BLANK mode %d --> %d\n",
+ info->node, dev->blank_mode, blank_mode);
if ((dev->blank_mode == FB_BLANK_POWERDOWN) &&
(blank_mode != FB_BLANK_POWERDOWN)) {
@@ -1613,8 +1613,9 @@ static int dlfb_usb_probe(struct usb_interface *interface,
pr_info("%s %s - serial #%s\n",
usbdev->manufacturer, usbdev->product, usbdev->serial);
pr_info("vid_%04x&pid_%04x&rev_%04x driver's dlfb_data struct at %p\n",
- usbdev->descriptor.idVendor, usbdev->descriptor.idProduct,
- usbdev->descriptor.bcdDevice, dev);
+ le16_to_cpu(usbdev->descriptor.idVendor),
+ le16_to_cpu(usbdev->descriptor.idProduct),
+ le16_to_cpu(usbdev->descriptor.bcdDevice), dev);
pr_info("console enable=%d\n", console);
pr_info("fb_defio enable=%d\n", fb_defio);
pr_info("shadow enable=%d\n", shadow);
diff --git a/drivers/video/fbdev/via/viafbdev.c b/drivers/video/fbdev/via/viafbdev.c
index f9718f012aae..badee04ef496 100644
--- a/drivers/video/fbdev/via/viafbdev.c
+++ b/drivers/video/fbdev/via/viafbdev.c
@@ -1630,16 +1630,14 @@ static void viafb_init_proc(struct viafb_shared *shared)
}
static void viafb_remove_proc(struct viafb_shared *shared)
{
- struct proc_dir_entry *viafb_entry = shared->proc_entry,
- *iga1_entry = shared->iga1_proc_entry,
- *iga2_entry = shared->iga2_proc_entry;
+ struct proc_dir_entry *viafb_entry = shared->proc_entry;
if (!viafb_entry)
return;
- remove_proc_entry("output_devices", iga2_entry);
+ remove_proc_entry("output_devices", shared->iga2_proc_entry);
remove_proc_entry("iga2", viafb_entry);
- remove_proc_entry("output_devices", iga1_entry);
+ remove_proc_entry("output_devices", shared->iga1_proc_entry);
remove_proc_entry("iga1", viafb_entry);
remove_proc_entry("supported_output_devices", viafb_entry);
diff --git a/drivers/virtio/virtio_balloon.c b/drivers/virtio/virtio_balloon.c
index 408c174ef0d5..22caf808bfab 100644
--- a/drivers/virtio/virtio_balloon.c
+++ b/drivers/virtio/virtio_balloon.c
@@ -663,6 +663,12 @@ static int virtballoon_restore(struct virtio_device *vdev)
}
#endif
+static int virtballoon_validate(struct virtio_device *vdev)
+{
+ __virtio_clear_bit(vdev, VIRTIO_F_IOMMU_PLATFORM);
+ return 0;
+}
+
static unsigned int features[] = {
VIRTIO_BALLOON_F_MUST_TELL_HOST,
VIRTIO_BALLOON_F_STATS_VQ,
@@ -675,6 +681,7 @@ static struct virtio_driver virtio_balloon_driver = {
.driver.name = KBUILD_MODNAME,
.driver.owner = THIS_MODULE,
.id_table = id_table,
+ .validate = virtballoon_validate,
.probe = virtballoon_probe,
.remove = virtballoon_remove,
.config_changed = virtballoon_changed,
diff --git a/drivers/xen/events/events_base.c b/drivers/xen/events/events_base.c
index b52852f38cff..2e567d8433b3 100644
--- a/drivers/xen/events/events_base.c
+++ b/drivers/xen/events/events_base.c
@@ -1343,8 +1343,12 @@ static int set_affinity_irq(struct irq_data *data, const struct cpumask *dest,
bool force)
{
unsigned tcpu = cpumask_first_and(dest, cpu_online_mask);
+ int ret = rebind_irq_to_cpu(data->irq, tcpu);
- return rebind_irq_to_cpu(data->irq, tcpu);
+ if (!ret)
+ irq_data_update_effective_affinity(data, cpumask_of(tcpu));
+
+ return ret;
}
static void enable_dynirq(struct irq_data *data)
diff --git a/drivers/xen/manage.c b/drivers/xen/manage.c
index c1ec8ee80924..9e35032351a0 100644
--- a/drivers/xen/manage.c
+++ b/drivers/xen/manage.c
@@ -190,6 +190,7 @@ static void do_poweroff(void)
{
switch (system_state) {
case SYSTEM_BOOTING:
+ case SYSTEM_SCHEDULING:
orderly_poweroff(true);
break;
case SYSTEM_RUNNING:
diff --git a/drivers/xen/mcelog.c b/drivers/xen/mcelog.c
index a493c7315e94..6cc1c15bcd84 100644
--- a/drivers/xen/mcelog.c
+++ b/drivers/xen/mcelog.c
@@ -408,6 +408,8 @@ static int __init xen_late_init_mcelog(void)
if (ret)
goto deregister;
+ pr_info("/dev/mcelog registered by Xen\n");
+
return 0;
deregister:
diff --git a/drivers/xen/privcmd.c b/drivers/xen/privcmd.c
index 7a92a5e1d40c..feca75b07fdd 100644
--- a/drivers/xen/privcmd.c
+++ b/drivers/xen/privcmd.c
@@ -362,8 +362,8 @@ static int mmap_batch_fn(void *data, int nr, void *state)
st->global_error = 1;
}
}
- st->va += PAGE_SIZE * nr;
- st->index += nr;
+ st->va += XEN_PAGE_SIZE * nr;
+ st->index += nr / XEN_PFN_PER_PAGE;
return 0;
}
diff --git a/drivers/xen/tmem.c b/drivers/xen/tmem.c
index 4ac2ca8a7656..bf13d1ec51f3 100644
--- a/drivers/xen/tmem.c
+++ b/drivers/xen/tmem.c
@@ -233,12 +233,12 @@ static int tmem_cleancache_init_fs(size_t pagesize)
return xen_tmem_new_pool(uuid_private, 0, pagesize);
}
-static int tmem_cleancache_init_shared_fs(char *uuid, size_t pagesize)
+static int tmem_cleancache_init_shared_fs(uuid_t *uuid, size_t pagesize)
{
struct tmem_pool_uuid shared_uuid;
- shared_uuid.uuid_lo = *(u64 *)uuid;
- shared_uuid.uuid_hi = *(u64 *)(&uuid[8]);
+ shared_uuid.uuid_lo = *(u64 *)&uuid->b[0];
+ shared_uuid.uuid_hi = *(u64 *)&uuid->b[8];
return xen_tmem_new_pool(shared_uuid, TMEM_POOL_SHARED, pagesize);
}